diff --git a/Makefile b/Makefile index ca7f2a3a3ffa..840fdcd094d8 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 95 +SUBLEVEL = 96 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index af4e8c8a5422..6582c4adc182 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c @@ -83,13 +83,16 @@ static int save_trace(struct stackframe *frame, void *d) return trace->nr_entries >= trace->max_entries; } -void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) +/* This must be noinline to so that our skip calculation works correctly */ +static noinline void __save_stack_trace(struct task_struct *tsk, + struct stack_trace *trace, unsigned int nosched) { struct stack_trace_data data; struct stackframe frame; data.trace = trace; data.skip = trace->skip; + data.no_sched_functions = nosched; if (tsk != current) { #ifdef CONFIG_SMP @@ -102,7 +105,6 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) trace->entries[trace->nr_entries++] = ULONG_MAX; return; #else - data.no_sched_functions = 1; frame.fp = thread_saved_fp(tsk); frame.sp = thread_saved_sp(tsk); frame.lr = 0; /* recovered from the stack */ @@ -111,11 +113,12 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) } else { register unsigned long current_sp asm ("sp"); - data.no_sched_functions = 0; + /* We don't want this function nor the caller */ + data.skip += 2; frame.fp = (unsigned long)__builtin_frame_address(0); frame.sp = current_sp; frame.lr = (unsigned long)__builtin_return_address(0); - frame.pc = (unsigned long)save_stack_trace_tsk; + frame.pc = (unsigned long)__save_stack_trace; } walk_stackframe(&frame, save_trace, &data); @@ -123,9 +126,14 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) trace->entries[trace->nr_entries++] = ULONG_MAX; } +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) +{ + __save_stack_trace(tsk, trace, 1); +} + void save_stack_trace(struct stack_trace *trace) { - save_stack_trace_tsk(current, trace); + __save_stack_trace(current, trace, 0); } EXPORT_SYMBOL_GPL(save_stack_trace); #endif diff --git a/arch/arm/mach-msm/board-m2.c b/arch/arm/mach-msm/board-m2.c index ea5573d78edf..edd0b99ee548 100644 --- a/arch/arm/mach-msm/board-m2.c +++ b/arch/arm/mach-msm/board-m2.c @@ -4120,7 +4120,7 @@ static struct gpio_keys_button gpio_keys_button[] = { .gpio = -1, .active_low = 1, .wakeup = 0, - .debounce_interval = 5, /* ms */ + .debounce_interval = 8, /* ms */ .desc = "Vol Up", }, { @@ -4129,7 +4129,7 @@ static struct gpio_keys_button gpio_keys_button[] = { .gpio = -1, .active_low = 1, .wakeup = 0, - .debounce_interval = 5, /* ms */ + .debounce_interval = 8, /* ms */ .desc = "Vol Down", }, { diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 47853debb3b9..025415e7346a 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -142,9 +142,9 @@ struct _lowcore { __u8 pad_0x02fc[0x0300-0x02fc]; /* 0x02fc */ /* Interrupt response block */ - __u8 irb[64]; /* 0x0300 */ + __u8 irb[96]; /* 0x0300 */ - __u8 pad_0x0340[0x0e00-0x0340]; /* 0x0340 */ + __u8 pad_0x0360[0x0e00-0x0360]; /* 0x0360 */ /* * 0xe00 contains the address of the IPL Parameter Information @@ -288,12 +288,13 @@ struct _lowcore { __u8 pad_0x03a0[0x0400-0x03a0]; /* 0x03a0 */ /* Interrupt response block. */ - __u8 irb[64]; /* 0x0400 */ + __u8 irb[96]; /* 0x0400 */ + __u8 pad_0x0460[0x0480-0x0460]; /* 0x0460 */ /* Per cpu primary space access list */ - __u32 paste[16]; /* 0x0440 */ + __u32 paste[16]; /* 0x0480 */ - __u8 pad_0x0480[0x0e00-0x0480]; /* 0x0480 */ + __u8 pad_0x04c0[0x0e00-0x04c0]; /* 0x04c0 */ /* * 0xe00 contains the address of the IPL Parameter Information diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 2af4ccd88d16..e1e7f9c831da 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -426,9 +426,10 @@ sysenter_past_esp: jnz sysenter_audit sysenter_do_call: cmpl $(NR_syscalls), %eax - jae syscall_badsys + jae sysenter_badsys call *sys_call_table(,%eax,4) movl %eax,PT_EAX(%esp) +sysenter_after_call: LOCKDEP_SYS_EXIT DISABLE_INTERRUPTS(CLBR_ANY) TRACE_IRQS_OFF @@ -550,11 +551,6 @@ ENTRY(iret_exc) CFI_RESTORE_STATE ldt_ss: - larl PT_OLDSS(%esp), %eax - jnz restore_nocheck - testl $0x00400000, %eax # returning to 32bit stack? - jnz restore_nocheck # allright, normal return - #ifdef CONFIG_PARAVIRT /* * The kernel can't run on a non-flat stack if paravirt mode @@ -683,7 +679,12 @@ END(syscall_fault) syscall_badsys: movl $-ENOSYS,PT_EAX(%esp) - jmp resume_userspace + jmp syscall_exit +END(syscall_badsys) + +sysenter_badsys: + movl $-ENOSYS,PT_EAX(%esp) + jmp sysenter_after_call END(syscall_badsys) CFI_ENDPROC /* diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl index fd1f10348130..b6c54909d361 100644 --- a/arch/x86/syscalls/syscall_64.tbl +++ b/arch/x86/syscalls/syscall_64.tbl @@ -212,10 +212,10 @@ 203 common sched_setaffinity sys_sched_setaffinity 204 common sched_getaffinity sys_sched_getaffinity 205 64 set_thread_area -206 common io_setup sys_io_setup +206 64 io_setup sys_io_setup 207 common io_destroy sys_io_destroy 208 common io_getevents sys_io_getevents -209 common io_submit sys_io_submit +209 64 io_submit sys_io_submit 210 common io_cancel sys_io_cancel 211 64 get_thread_area 212 common lookup_dcookie sys_lookup_dcookie @@ -353,3 +353,5 @@ 540 x32 process_vm_writev compat_sys_process_vm_writev 541 x32 setsockopt compat_sys_setsockopt 542 x32 getsockopt compat_sys_getsockopt +543 x32 io_setup compat_sys_io_setup +544 x32 io_submit compat_sys_io_submit diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 0bf5ec2d5818..06d2d22281b2 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -57,6 +57,12 @@ EXPORT_SYMBOL(acpi_root_dir); #ifdef CONFIG_X86 +#ifdef CONFIG_ACPI_CUSTOM_DSDT +static inline int set_copy_dsdt(const struct dmi_system_id *id) +{ + return 0; +} +#else static int set_copy_dsdt(const struct dmi_system_id *id) { printk(KERN_NOTICE "%s detected - " @@ -64,6 +70,7 @@ static int set_copy_dsdt(const struct dmi_system_id *id) acpi_gbl_copy_dsdt_locally = 1; return 0; } +#endif static struct dmi_system_id dsdt_dmi_table[] __initdata = { /* diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c index 25373df1dcf8..5d069c79bd8b 100644 --- a/drivers/char/applicom.c +++ b/drivers/char/applicom.c @@ -345,7 +345,6 @@ static int __init applicom_init(void) free_irq(apbs[i].irq, &dummy); iounmap(apbs[i].RamIO); } - pci_disable_device(dev); return ret; } diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 230f435c7ad8..75fa2e7b87b5 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -861,7 +861,17 @@ struct hid_report *hid_validate_values(struct hid_device *hid, * ->numbered being checked, which may not always be the case when * drivers go to access report values. */ - report = hid->report_enum[type].report_id_hash[id]; + if (id == 0) { + /* + * Validating on id 0 means we should examine the first + * report in the list. + */ + report = list_entry( + hid->report_enum[type].report_list.next, + struct hid_report, list); + } else { + report = hid->report_enum[type].report_id_hash[id]; + } if (!report) { hid_err(hid, "missing %s %u\n", hid_report_names[type], id); return NULL; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index e836de065f61..b5eff86600a6 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -4,6 +4,13 @@ menu "Misc devices" +config GAMMA_CONTROL + bool "Gamma Control for OLED" + depends on FB_MSM_MIPI_DSI_SAMSUNG_OLED + default y + help + This adds full support for shifting RGB panel colors. + config SENSORS_LIS3LV02D tristate depends on INPUT diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index db450855aa4b..39afa6f7d3df 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -85,3 +85,4 @@ obj-$(CONFIG_OPTICAL_TAOS_TRITON) += taos.o obj-$(CONFIG_SAMSUNG_JACK) += sec_jack.o obj-$(CONFIG_OPTICAL_BH1721) += bh1721.o obj-$(CONFIG_VP_A2220) += a2220.o +obj-$(CONFIG_GAMMA_CONTROL) += gamma_control.o diff --git a/drivers/misc/gamma_control.c b/drivers/misc/gamma_control.c new file mode 100644 index 000000000000..c30fcaaf3143 --- /dev/null +++ b/drivers/misc/gamma_control.c @@ -0,0 +1,370 @@ +/* + * Copyright 2013 Francisco Franco + * 2014 Reworked for Samsung OLED, Luis Cruz + * + * 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 + +#define GAMMACONTROL_VERSION 2 + + // r g b +int v255_val[3] = { 0, 0, 0}; +int v1_val[3] = { 0, 0, 0}; +int v171_val[3] = { 0, 0, 0}; +int v87_val[3] = { 0, 0, 0}; +#if !defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_WVGA_PT) && !defined(FB_MSM_MIPI_MAGNA_OLED_VIDEO_WVGA_PT) +int v59_val[3] = { 0, 0, 0}; +int v35_val[3] = { 0, 0, 0}; +int v15_val[3] = { 0, 0, 0}; +#else +int v43_val[3] = { 0, 0, 0}; +int v19_val[3] = { 0, 0, 0}; +#endif +int tuner[3] = { 0, 0, 0}; + +int color_mods[5][21] = { + { 0, 0, 5, -18, -16, -10, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0, 3 }, + { 0, 0, 2, -9, -8, -5, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, -2, 9, 8, 5, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1 }, + { 0, 0, -5, 18, 16, 10, 0, 0, -3, 0, 0, -3, 0, 0, -3, 0, 0, -3, 0, 0, -3 } +}; + +extern void panel_load_colors(void); + +static ssize_t v255_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d %d %d\n", v255_val[0], v255_val[1], v255_val[2]); +} + +static ssize_t v255_store(struct device * dev, struct device_attribute * attr, const char * buf, size_t size) +{ + int new_r, new_g, new_b; + + sscanf(buf, "%d %d %d", &new_r, &new_g, &new_b); + + if (new_r != v255_val[0] || new_g != v255_val[1] || new_b != v255_val[2]) { + pr_debug("New v255: %d %d %d\n", new_r, new_g, new_b); + v255_val[0] = new_r; + v255_val[1] = new_g; + v255_val[2] = new_b; + panel_load_colors(); + } + + return size; +} + +static ssize_t v1_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d %d %d\n", v1_val[0], v1_val[1], v1_val[2]); +} + +static ssize_t v1_store(struct device * dev, struct device_attribute * attr, const char * buf, size_t size) +{ + int new_r, new_g, new_b; + + sscanf(buf, "%d %d %d", &new_r, &new_g, &new_b); + + if (new_r != v1_val[0] || new_g != v1_val[1] || new_b != v1_val[2]) { + pr_debug("New v1: %d %d %d\n", new_r, new_g, new_b); + v1_val[0] = new_r; + v1_val[1] = new_g; + v1_val[2] = new_b; + panel_load_colors(); + } + + return size; +} + +static ssize_t v171_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d %d %d\n", v171_val[0], v171_val[1], v171_val[2]); +} + +static ssize_t v171_store(struct device * dev, struct device_attribute * attr, const char * buf, size_t size) +{ + int new_r, new_g, new_b; + + sscanf(buf, "%d %d %d", &new_r, &new_g, &new_b); + + if (new_r != v171_val[0] || new_g != v171_val[1] || new_b != v171_val[2]) { + pr_debug("New v171: %d %d %d\n", new_r, new_g, new_b); + v171_val[0] = new_r; + v171_val[1] = new_g; + v171_val[2] = new_b; + panel_load_colors(); + } + + return size; +} + +static ssize_t v87_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d %d %d\n", v87_val[0], v87_val[1], v87_val[2]); +} + +static ssize_t v87_store(struct device * dev, struct device_attribute * attr, const char * buf, size_t size) +{ + int new_r, new_g, new_b; + + sscanf(buf, "%d %d %d", &new_r, &new_g, &new_b); + + if (new_r != v87_val[0] || new_g != v87_val[1] || new_b != v87_val[2]) { + pr_debug("New v87: %d %d %d\n", new_r, new_g, new_b); + v87_val[0] = new_r; + v87_val[1] = new_g; + v87_val[2] = new_b; + panel_load_colors(); + } + + return size; +} + +#if !defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_WVGA_PT) && !defined(FB_MSM_MIPI_MAGNA_OLED_VIDEO_WVGA_PT) +static ssize_t v59_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d %d %d\n", v59_val[0], v59_val[1], v59_val[2]); +} + +static ssize_t v59_store(struct device * dev, struct device_attribute * attr, const char * buf, size_t size) +{ + int new_r, new_g, new_b; + + sscanf(buf, "%d %d %d", &new_r, &new_g, &new_b); + + if (new_r != v59_val[0] || new_g != v59_val[1] || new_b != v59_val[2]) { + pr_debug("New v59: %d %d %d\n", new_r, new_g, new_b); + v59_val[0] = new_r; + v59_val[1] = new_g; + v59_val[2] = new_b; + panel_load_colors(); + } + + return size; +} + +static ssize_t v35_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d %d %d\n", v35_val[0], v35_val[1], v35_val[2]); +} + +static ssize_t v35_store(struct device * dev, struct device_attribute * attr, const char * buf, size_t size) +{ + int new_r, new_g, new_b; + + sscanf(buf, "%d %d %d", &new_r, &new_g, &new_b); + + if (new_r != v35_val[0] || new_g != v35_val[1] || new_b != v35_val[2]) { + pr_debug("New v35: %d %d %d\n", new_r, new_g, new_b); + v35_val[0] = new_r; + v35_val[1] = new_g; + v35_val[2] = new_b; + panel_load_colors(); + } + + return size; +} + +static ssize_t v15_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d %d %d\n", v15_val[0], v15_val[1], v15_val[2]); +} + +static ssize_t v15_store(struct device * dev, struct device_attribute * attr, const char * buf, size_t size) +{ + int new_r, new_g, new_b; + + sscanf(buf, "%d %d %d", &new_r, &new_g, &new_b); + + if (new_r != v15_val[0] || new_g != v15_val[1] || new_b != v15_val[2]) { + pr_debug("New v15: %d %d %d\n", new_r, new_g, new_b); + v15_val[0] = new_r; + v15_val[1] = new_g; + v15_val[2] = new_b; + panel_load_colors(); + } + + return size; +} + +#else /* CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_WVGA_PT */ +static ssize_t v43_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d %d %d\n", v43_val[0], v43_val[1], v43_val[2]); +} + +static ssize_t v43_store(struct device * dev, struct device_attribute * attr, const char * buf, size_t size) +{ + int new_r, new_g, new_b; + + sscanf(buf, "%d %d %d", &new_r, &new_g, &new_b); + + if (new_r != v43_val[0] || new_g != v43_val[1] || new_b != v43_val[2]) { + pr_debug("New v43: %d %d %d\n", new_r, new_g, new_b); + v43_val[0] = new_r; + v43_val[1] = new_g; + v43_val[2] = new_b; + panel_load_colors(); + } + + return size; +} + +static ssize_t v19_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d %d %d\n", v19_val[0], v19_val[1], v19_val[2]); +} + +static ssize_t v19_store(struct device * dev, struct device_attribute * attr, const char * buf, size_t size) +{ + int new_r, new_g, new_b; + + sscanf(buf, "%d %d %d", &new_r, &new_g, &new_b); + + if (new_r != v19_val[0] || new_g != v19_val[1] || new_b != v19_val[2]) { + pr_debug("New v19: %d %d %d\n", new_r, new_g, new_b); + v19_val[0] = new_r; + v19_val[1] = new_g; + v19_val[2] = new_b; + panel_load_colors(); + } + + return size; +} +#endif /* CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_WVGA_PT */ + +static ssize_t tuner_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d %d %d\n", tuner[0], tuner[1], tuner[2]); +} + +static ssize_t tuner_store(struct device * dev, struct device_attribute * attr, const char * buf, size_t size) +{ + int new_r, new_g, new_b; + + sscanf(buf, "%d %d %d", &new_r, &new_g, &new_b); + + if (new_r > 5 || new_r < 0 || new_g > 5 || new_g < 0 || new_b > 5 || new_b < 0) { + new_r = new_g = new_b = 2; + } + + if (new_r != tuner[0] || new_g != tuner[1] || new_b != tuner[2]) { + pr_debug("New master tuner: %d %d %d\n", new_r, new_g, new_b); + tuner[0] = new_r; + tuner[1] = new_g; + tuner[2] = new_b; + v255_val[0] = color_mods[new_r][0]; + v255_val[1] = color_mods[new_g][0]; + v255_val[2] = color_mods[new_b][0]; + v1_val[0] = color_mods[new_r][1]; + v1_val[1] = color_mods[new_g][1]; + v1_val[2] = color_mods[new_b][1]; + v171_val[0] = color_mods[new_r][2]; + v171_val[1] = color_mods[new_g][2]; + v171_val[2] = color_mods[new_b][2]; + v87_val[0] = color_mods[new_r][3]; + v87_val[1] = color_mods[new_g][3]; + v87_val[2] = color_mods[new_b][3]; +#if !defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_WVGA_PT) && !defined(FB_MSM_MIPI_MAGNA_OLED_VIDEO_WVGA_PT) + v59_val[0] = color_mods[new_r][4]; + v59_val[1] = color_mods[new_g][4]; + v59_val[2] = color_mods[new_b][4]; + v35_val[0] = color_mods[new_r][5]; + v35_val[1] = color_mods[new_g][5]; + v35_val[2] = color_mods[new_b][5]; + v15_val[0] = color_mods[new_r][6]; + v15_val[1] = color_mods[new_g][6]; + v15_val[2] = color_mods[new_b][6]; +#else + v43_val[0] = color_mods[new_r][4]; + v43_val[1] = color_mods[new_g][4]; + v43_val[2] = color_mods[new_b][4]; + v19_val[0] = color_mods[new_r][5]; + v19_val[1] = color_mods[new_g][5]; + v19_val[2] = color_mods[new_b][5]; +#endif + + panel_load_colors(); + } + + return size; +} + +static ssize_t gammacontrol_version(struct device * dev, struct device_attribute * attr, char * buf) +{ + return sprintf(buf, "%u\n", GAMMACONTROL_VERSION); +} + +static DEVICE_ATTR(v255rgb, 0644, v255_show, v255_store); +static DEVICE_ATTR(v1rgb, 0644, v1_show, v1_store); +static DEVICE_ATTR(v171rgb, 0644, v171_show, v171_store); +static DEVICE_ATTR(v87rgb, 0644, v87_show, v87_store); +#if !defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_WVGA_PT) && !defined(FB_MSM_MIPI_MAGNA_OLED_VIDEO_WVGA_PT) +static DEVICE_ATTR(v59rgb, 0644, v59_show, v59_store); +static DEVICE_ATTR(v35rgb, 0644, v35_show, v35_store); +static DEVICE_ATTR(v15rgb, 0644, v15_show, v15_store); +#else +static DEVICE_ATTR(v43rgb, 0644, v43_show, v43_store); +static DEVICE_ATTR(v19rgb, 0644, v19_show, v19_store); +#endif +static DEVICE_ATTR(version, 0644, gammacontrol_version, NULL); +static DEVICE_ATTR(tuner, 0644, tuner_show, tuner_store); + +static struct attribute *gammacontrol_attributes[] = +{ + &dev_attr_v255rgb.attr, + &dev_attr_v1rgb.attr, + &dev_attr_v171rgb.attr, + &dev_attr_v87rgb.attr, +#if !defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_WVGA_PT) && !defined(FB_MSM_MIPI_MAGNA_OLED_VIDEO_WVGA_PT) + &dev_attr_v59rgb.attr, + &dev_attr_v35rgb.attr, + &dev_attr_v15rgb.attr, +#else + &dev_attr_v43rgb.attr, + &dev_attr_v19rgb.attr, +#endif + &dev_attr_tuner.attr, + &dev_attr_version.attr, + NULL +}; + +static struct attribute_group gammacontrol_group = +{ + .attrs = gammacontrol_attributes, +}; + +static struct miscdevice gammacontrol_device = +{ + .minor = MISC_DYNAMIC_MINOR, + .name = "gammacontrol", +}; + +static int __init gammacontrol_init(void) +{ + int ret; + + pr_info("%s misc_register(%s)\n", __FUNCTION__, gammacontrol_device.name); + + ret = misc_register(&gammacontrol_device); + + if (ret) { + pr_err("%s misc_register(%s) fail\n", __FUNCTION__, gammacontrol_device.name); + return 1; + } + + if (sysfs_create_group(&gammacontrol_device.this_device->kobj, &gammacontrol_group) < 0) { + pr_err("%s sysfs_create_group fail\n", __FUNCTION__); + pr_err("Failed to create sysfs group for device (%s)!\n", gammacontrol_device.name); + } + + return 0; +} + +device_initcall(gammacontrol_init); diff --git a/drivers/motor/tspdrv.c b/drivers/motor/tspdrv.c index 69291cbc775e..c1411b0ac85a 100644 --- a/drivers/motor/tspdrv.c +++ b/drivers/motor/tspdrv.c @@ -527,6 +527,12 @@ static ssize_t write(struct file *file, const char *buf, size_t count, return 0; } + /* Check buffer size */ + if ((count <= SPI_HEADER_SIZE) || (count > SPI_BUFFER_SIZE)) { + DbgOut((KERN_ERR "tspdrv: invalid write buffer size.\n")); + return 0; + } + /* Copy immediately the input buffer */ if (0 != copy_from_user(g_cwrite_buffer, buf, count)) { /* Failed to copy all the data, exit */ @@ -534,12 +540,6 @@ static ssize_t write(struct file *file, const char *buf, size_t count, return 0; } - /* Check buffer size */ - if ((count <= SPI_HEADER_SIZE) || (count > SPI_BUFFER_SIZE)) { - DbgOut((KERN_ERR "tspdrv: invalid write buffer size.\n")); - return 0; - } - while (i < count) { int nindex_free_buffer; /* initialized below */ @@ -552,6 +552,7 @@ static ssize_t write(struct file *file, const char *buf, size_t count, ** (Should never happen). */ DbgOut((KERN_EMERG "tspdrv: invalid buffer index.\n")); + return 0; } /* Check bit depth */ @@ -572,6 +573,7 @@ static ssize_t write(struct file *file, const char *buf, size_t count, ** (Should never happen). */ DbgOut((KERN_EMERG "tspdrv: invalid data size.\n")); + return 0; } /* Check actuator index */ diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c index 5f92b865f64b..a28c5d312447 100644 --- a/drivers/net/can/sja1000/peak_pci.c +++ b/drivers/net/can/sja1000/peak_pci.c @@ -547,7 +547,7 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev, { struct sja1000_priv *priv; struct peak_pci_chan *chan; - struct net_device *dev; + struct net_device *dev, *prev_dev; void __iomem *cfg_base, *reg_base; u16 sub_sys_id, icr; int i, err, channels; @@ -681,11 +681,13 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev, writew(0x0, cfg_base + PITA_ICR + 2); chan = NULL; - for (dev = pci_get_drvdata(pdev); dev; dev = chan->prev_dev) { - unregister_sja1000dev(dev); - free_sja1000dev(dev); + for (dev = pci_get_drvdata(pdev); dev; dev = prev_dev) { priv = netdev_priv(dev); chan = priv->priv; + prev_dev = chan->prev_dev; + + unregister_sja1000dev(dev); + free_sja1000dev(dev); } /* free any PCIeC resources too */ @@ -719,10 +721,12 @@ static void __devexit peak_pci_remove(struct pci_dev *pdev) /* Loop over all registered devices */ while (1) { + struct net_device *prev_dev = chan->prev_dev; + dev_info(&pdev->dev, "removing device %s\n", dev->name); unregister_sja1000dev(dev); free_sja1000dev(dev); - dev = chan->prev_dev; + dev = prev_dev; if (!dev) { /* do that only for first channel */ diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index 91c3f298c283..73b0b2a5b7b3 100755 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -3,12 +3,12 @@ # SDIO Basic feature ##################### -DHDCFLAGS += -Wall -Wstrict-prototypes -Dlinux -DLINUX -DBCMDRIVER \ +DHDCFLAGS += -Wall -Wstrict-prototypes -Dlinux -DLINUX -DBCMDRIVER \ -DBCMDONGLEHOST -DUNRELEASEDCHIP -DBCMDMA32 -DBCMFILEIMAGE \ -DDHDTHREAD -DBDC -DOOB_INTR_ONLY \ - -DDHD_BCMEVENTS -DSHOW_EVENTS -DBCMDBG \ - -DMMC_SDIO_ABORT -DBCMSDIO -DBCMLXSDMMC -DWLP2P \ - -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT \ + -DDHD_BCMEVENTS -DSHOW_EVENTS \ + -DMMC_SDIO_ABORT -DBCMSDIO -DBCMLXSDMMC -DWLP2P \ + -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT \ -DKEEP_ALIVE -DCSCAN -DPKT_FILTER_SUPPORT \ -DEMBEDDED_PLATFORM -DPNO_SUPPORT @@ -21,7 +21,7 @@ DHDCFLAGS += -DWL_CFG80211 # Debug DHDCFLAGS += -DSIMPLE_MAC_PRINT -DHDCFLAGS += -DDEBUGFS_CFG80211 +#DHDCFLAGS += -DDEBUGFS_CFG80211 # Print out kernel panic point of file and line info when assertion happened DHDCFLAGS += -DBCMASSERT_LOG @@ -392,9 +392,9 @@ DHDCFLAGS += -include "dhd_sec_feature.h" # Others ######### -#EXTRA_LDFLAGS += --strip-debug +EXTRA_LDFLAGS += --strip-debug -EXTRA_CFLAGS += $(DHDCFLAGS) -DDHD_DEBUG +EXTRA_CFLAGS += $(DHDCFLAGS) EXTRA_CFLAGS += -DSRCBASE=\"$(src)\" EXTRA_CFLAGS += -I$(src)/include/ -I$(src)/ KBUILD_CFLAGS += -I$(LINUXDIR)/include -I$(shell pwd) diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index b0b2b296bc74..7b4911af2068 100755 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -411,14 +411,86 @@ int dhd_pno_clean(dhd_pub_t *dhd); * Wake locks are an Android power management concept. They are used by applications and services * to request CPU resources. */ -extern int dhd_os_wake_lock(dhd_pub_t *pub); -extern int dhd_os_wake_unlock(dhd_pub_t *pub); -extern int dhd_os_wake_lock_timeout(dhd_pub_t *pub); -extern int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val); -extern int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val); -extern int dhd_os_wake_lock_ctrl_timeout_cancel(dhd_pub_t *pub); -extern int dhd_os_wd_wake_lock(dhd_pub_t *pub); -extern int dhd_os_wd_wake_unlock(dhd_pub_t *pub); +#ifdef CONFIG_HAS_WAKELOCK +struct dhd_info; +#define dhd_info_t struct dhd_info + +enum { + DHD_WL_rx = 0, + DHD_WL_ctrl, +}; + +#define dhd_wake_func(fn) \ + extern int dhd_int_wake_##fn (dhd_info_t *dhd); \ + static inline int dhd_os_wake_##fn (dhd_pub_t *pub) \ + { return dhd_int_wake_##fn ((dhd_info_t *)pub->info); } + +extern int dhd_int_wake_timeout_enable(dhd_info_t *dhd, int val, int wl); +extern int dhd_int_wake_timeout_cancel(dhd_info_t *dhd, int wl); +#define dhd_tmout_func(fn) \ + static inline int dhd_os_wake_lock_##fn##_timeout_enable \ + (dhd_pub_t *pub, int val) \ + { return dhd_int_wake_timeout_enable((dhd_info_t *)pub->info, val, \ + DHD_WL_##fn ); } \ + static inline int dhd_os_wake_lock_##fn##_timeout_cancel \ + (dhd_pub_t *pub) \ + { return dhd_int_wake_timeout_cancel((dhd_info_t *)pub->info, \ + DHD_WL_##fn ); } + +#define net_wake_func(fn) \ + static inline int net_os_wake_##fn (struct net_device *dev) \ + { \ + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); \ + return dhd?dhd_int_wake_##fn (dhd):0; \ + } + +#define net_tmout_func(fn) \ + static inline int net_os_wake_lock_##fn##_timeout_enable \ + (struct net_device *dev, int val) \ + { \ + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); \ + return dhd ? dhd_int_wake_timeout_enable(dhd, val, \ + DHD_WL_##fn ) : 0; \ + } \ + static inline int net_os_wake_lock_##fn##_timeout_cancel \ + (struct net_device *dev) \ + { \ + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); \ + return dhd ? dhd_int_wake_timeout_cancel(dhd, \ + DHD_WL_##fn ) : 0; \ + } \ + +/* Core wake functions */ +dhd_wake_func(lock); +dhd_wake_func(unlock); +dhd_wake_func(lock_timeout); +dhd_tmout_func(rx); +dhd_tmout_func(ctrl); + +/* struct net_device wrappers */ +net_wake_func(lock); +net_wake_func(unlock); +net_wake_func(lock_timeout); +net_tmout_func(rx); +net_tmout_func(ctrl); + +#define DHD_WD_LOCK (1) +#define DHD_WD_WAIVE (2) +extern int dhd_int_wd_wake_lock(dhd_info_t *dhd); +extern int dhd_int_wd_wake_unlock(dhd_info_t *dhd); +static inline int dhd_os_wd_wake_lock(dhd_pub_t *pub) +{ return (pub && pub->info) ? dhd_int_wd_wake_lock(pub->info) : 0; } +static inline int dhd_os_wd_wake_unlock(dhd_pub_t *pub) +{ return (pub && pub->info) ? dhd_int_wd_wake_unlock(pub->info) : 0; } + +#undef dhd_wake_func +#undef dhd_tmount_func +#undef net_wake_func +#undef net_tmout_func +#undef dhd_info_t +#else +#error CONFIG_HAS_WAKELOCK is required +#endif inline static void MUTEX_LOCK_SOFTAP_SET_INIT(dhd_pub_t * dhdp) { diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index ea3433e3f64e..aed29bc56a66 100755 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -72,7 +72,9 @@ #ifdef WLMEDIA_HTSF extern void htsf_update(struct dhd_info *dhd, void *data); #endif +#ifdef DHD_DEBUG int dhd_msg_level = DHD_ERROR_VAL; +#endif #include @@ -359,7 +361,9 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch wl_cfg80211_enable_trace(FALSE, WL_DBG_DBG); if (!(int_val & DHD_WL_VAL2)) #endif /* WL_CFG80211 */ +#ifdef DHD_DEBUG dhd_msg_level = int_val; +#endif break; case IOV_GVAL(IOV_BCMERRORSTR): bcm_strncpy_s((char *)arg, len, bcmerrorstr(dhd_pub->bcmerror), BCME_STRLEN); diff --git a/drivers/net/wireless/bcmdhd/dhd_dbg.h b/drivers/net/wireless/bcmdhd/dhd_dbg.h index 66fc074b709b..03869e6ed870 100755 --- a/drivers/net/wireless/bcmdhd/dhd_dbg.h +++ b/drivers/net/wireless/bcmdhd/dhd_dbg.h @@ -127,7 +127,11 @@ #define DHD_BLOG(cp, size) #define DHD_NONE(args) +#ifdef DHD_DEBUG extern int dhd_msg_level; +#else +#define dhd_msg_level (0) +#endif /* Defines msg bits */ #include diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index da6b2a2dc4e4..1916fc0995bf 100755 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -244,6 +245,10 @@ extern wl_iw_extra_params_t g_wl_iw_params; #endif /* defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) */ #endif /* CUSTOMER_HW4 && CONFIG_PARTIALSUSPEND_SLP */ +#ifdef CONFIG_HAS_WAKELOCK +static void _dhd_release_wakelock_timer(unsigned long data); +#endif + extern int dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd); #ifdef PKT_FILTER_SUPPORT @@ -394,10 +399,9 @@ typedef struct dhd_info { /* Wakelocks */ #if defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + unsigned long wl_timeout[2]; + struct timer_list wl_timer; struct wake_lock wl_wifi; /* Wifi wakelock */ - struct wake_lock wl_rxwake; /* Wifi rx wakelock */ - struct wake_lock wl_ctrlwake; /* Wifi ctrl wakelock */ - struct wake_lock wl_wdwake; /* Wifi wd wakelock */ #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) @@ -409,11 +413,7 @@ typedef struct dhd_info { #endif spinlock_t wakelock_spinlock; uint32 wakelock_counter; - bool waive_wakelock; - uint32 wakelock_before_waive; - int wakelock_wd_counter; - int wakelock_rx_timeout_enable; - int wakelock_ctrl_timeout_enable; + unsigned int wakelock_wd_state; /* Thread to issue ioctl for multicast */ wait_queue_head_t ctrl_wait; @@ -484,7 +484,9 @@ static void dhd_set_mcast_list_handler(void *handle, void *event_info, u8 event) static void dhd_inet6_work_handler(void *dhd_info, void *event_data, u8 event); /* Error bits */ +#ifdef DHD_DEBUG module_param(dhd_msg_level, int, 0); +#endif #ifdef ARP_OFFLOAD_SUPPORT /* ARP offload enable */ @@ -2287,8 +2289,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) if (dhd->rxthread_enabled && skbhead) dhd_sched_rxf(dhdp, skbhead); - DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(dhdp, tout_rx); - DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhdp, tout_ctrl); + DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhdp, max(tout_rx, tout_ctrl)); } void @@ -2546,13 +2547,12 @@ dhd_dpc_thread(void *data) #endif /* CUSTOMER_HW4 */ } dhd_os_wd_timer_extend(&dhd->pub, FALSE); - DHD_OS_WAKE_UNLOCK(&dhd->pub); } else { if (dhd->pub.up) dhd_bus_stop(dhd->pub.bus, TRUE); - DHD_OS_WAKE_UNLOCK(&dhd->pub); } + DHD_OS_WAKE_UNLOCK(&dhd->pub); } else break; @@ -3844,15 +3844,13 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) /* Initialize Wakelock stuff */ spin_lock_init(&dhd->wakelock_spinlock); dhd->wakelock_counter = 0; - dhd->wakelock_wd_counter = 0; - dhd->wakelock_rx_timeout_enable = 0; - dhd->wakelock_ctrl_timeout_enable = 0; - dhd->waive_wakelock = FALSE; + dhd->wakelock_wd_state = 0; #ifdef CONFIG_HAS_WAKELOCK + dhd->wl_timeout[0] = dhd->wl_timeout[1] = jiffies; wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake"); - wake_lock_init(&dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake"); - wake_lock_init(&dhd->wl_ctrlwake, WAKE_LOCK_SUSPEND, "wlan_ctrl_wake"); - wake_lock_init(&dhd->wl_wdwake, WAKE_LOCK_SUSPEND, "wlan_wd_wake"); + init_timer_deferrable(&dhd->wl_timer); + dhd->wl_timer.function = _dhd_release_wakelock_timer; + dhd->wl_timer.data = (unsigned long)dhd; #endif /* CONFIG_HAS_WAKELOCK */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) mutex_init(&dhd->dhd_net_if_mutex); @@ -5764,13 +5762,11 @@ void dhd_detach(dhd_pub_t *dhdp) DHD_TRACE(("wd wakelock count:%d\n", dhd->wakelock_wd_counter)); #ifdef CONFIG_HAS_WAKELOCK dhd->wakelock_counter = 0; - dhd->wakelock_wd_counter = 0; - dhd->wakelock_rx_timeout_enable = 0; - dhd->wakelock_ctrl_timeout_enable = 0; + dhd->wakelock_wd_state = 0; + del_timer_sync(&dhd->wl_timer); + if (wake_lock_active(&dhd->wl_wifi)) + wake_unlock(&dhd->wl_wifi); wake_lock_destroy(&dhd->wl_wifi); - wake_lock_destroy(&dhd->wl_rxwake); - wake_lock_destroy(&dhd->wl_ctrlwake); - wake_lock_destroy(&dhd->wl_wdwake); #endif /* CONFIG_HAS_WAKELOCK */ } @@ -6886,294 +6882,264 @@ write_to_file(dhd_pub_t *dhd, uint8 *buf, int size) } #endif /* DHD_DEBUG */ -int dhd_os_wake_lock_timeout(dhd_pub_t *pub) +#ifdef CONFIG_HAS_WAKELOCK +#define time_latest(a,b) (time_after(a,b)?a:b) +#define dhd_wl_timeout(d) (time_latest(d->wl_timeout[0], d->wl_timeout[1])) +/* _dhd_release_wakelock_timer: gets scheduled for the current timeout, re-arms + * itself as needed. wake_lock/unlock are called far too frequently to do + * anything heavyweight. + */ +static void _dhd_release_wakelock_timer(unsigned long data) { - dhd_info_t *dhd = (dhd_info_t *)(pub->info); + dhd_info_t *dhd = (dhd_info_t *)data; unsigned long flags; - int ret = 0; - if (dhd) { - spin_lock_irqsave(&dhd->wakelock_spinlock, flags); - ret = dhd->wakelock_rx_timeout_enable > dhd->wakelock_ctrl_timeout_enable ? - dhd->wakelock_rx_timeout_enable : dhd->wakelock_ctrl_timeout_enable; -#ifdef CONFIG_HAS_WAKELOCK - if (dhd->wakelock_rx_timeout_enable) - wake_lock_timeout(&dhd->wl_rxwake, - msecs_to_jiffies(dhd->wakelock_rx_timeout_enable)); - if (dhd->wakelock_ctrl_timeout_enable) - wake_lock_timeout(&dhd->wl_ctrlwake, - msecs_to_jiffies(dhd->wakelock_ctrl_timeout_enable)); -#endif - dhd->wakelock_rx_timeout_enable = 0; - dhd->wakelock_ctrl_timeout_enable = 0; - spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); + + if (time_after(dhd_wl_timeout(dhd), jiffies)) { + mod_timer(&dhd->wl_timer, dhd_wl_timeout(dhd)); + goto out; + } + if (dhd->wakelock_counter) { + goto out; } - return ret; -} -int net_os_wake_lock_timeout(struct net_device *dev) -{ - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - int ret = 0; + if (wake_lock_active(&dhd->wl_wifi)) + wake_unlock(&dhd->wl_wifi); - if (dhd) - ret = dhd_os_wake_lock_timeout(&dhd->pub); - return ret; +out: + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); } -int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val) +/* _dhd_acquire_wakelock: take the wakelock and handle housekeeping + * + * Called with wakelock_spinlock held. + */ +static int _dhd_acquire_wakelock(dhd_info_t *dhd) { - dhd_info_t *dhd = (dhd_info_t *)(pub->info); - unsigned long flags; + int ret; - if (dhd) { - spin_lock_irqsave(&dhd->wakelock_spinlock, flags); - if (val > dhd->wakelock_rx_timeout_enable) - dhd->wakelock_rx_timeout_enable = val; - spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); - } - return 0; -} + if (!(dhd->wakelock_counter || + wake_lock_active(&dhd->wl_wifi))) + wake_lock(&dhd->wl_wifi); -int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val) -{ - dhd_info_t *dhd = (dhd_info_t *)(pub->info); - unsigned long flags; + ret = ++dhd->wakelock_counter; - if (dhd) { - spin_lock_irqsave(&dhd->wakelock_spinlock, flags); - if (val > dhd->wakelock_ctrl_timeout_enable) - dhd->wakelock_ctrl_timeout_enable = val; - spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); - } - return 0; + return ret; } -int dhd_os_wake_lock_ctrl_timeout_cancel(dhd_pub_t *pub) +/* _dhd_release_wakelock: release the wakelock and handle housekeeping + * + * Called with wakelock_spinlock held. + */ +static int _dhd_release_wakelock(dhd_info_t *dhd) { - dhd_info_t *dhd = (dhd_info_t *)(pub->info); - unsigned long flags; + int ret = 0; - if (dhd) { - spin_lock_irqsave(&dhd->wakelock_spinlock, flags); - dhd->wakelock_ctrl_timeout_enable = 0; -#ifdef CONFIG_HAS_WAKELOCK - if (wake_lock_active(&dhd->wl_ctrlwake)) - wake_unlock(&dhd->wl_ctrlwake); -#endif - spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); + if (likely(dhd->wakelock_counter > 0)) { + ret = --dhd->wakelock_counter; + } else { + pr_warn("%s: unbalanced wakelock calls!\n", __func__); + return 0; } - return 0; -} -int net_os_wake_lock_rx_timeout_enable(struct net_device *dev, int val) -{ - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - int ret = 0; + if (!dhd->wakelock_counter) { + // Whenever possible, don't modify the timers. + if (time_after_eq(jiffies, dhd_wl_timeout(dhd))) { + //del_timer(&dhd->wl_timer); + if (likely(wake_lock_active(&dhd->wl_wifi))) + wake_unlock(&dhd->wl_wifi); + } else if (timer_pending(&dhd->wl_timer)) { + if (unlikely(time_after(dhd->wl_timer.expires, + dhd_wl_timeout(dhd)))) { + mod_timer_pending(&dhd->wl_timer, + dhd_wl_timeout(dhd)); + } + } else { + dhd->wl_timer.expires = dhd_wl_timeout(dhd); + add_timer(&dhd->wl_timer); + } + } - if (dhd) - ret = dhd_os_wake_lock_rx_timeout_enable(&dhd->pub, val); return ret; } -int net_os_wake_lock_ctrl_timeout_enable(struct net_device *dev, int val) +/* dhd_int_wake_lock: enable long-running wakelock */ +int dhd_int_wake_lock(dhd_info_t *dhd) { - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); + ret = _dhd_acquire_wakelock(dhd); + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); - if (dhd) - ret = dhd_os_wake_lock_ctrl_timeout_enable(&dhd->pub, val); return ret; } -int dhd_os_wake_lock(dhd_pub_t *pub) +/* dhd_int_wake_unlock: disable long-running wakelock, maybe kick off timer */ +int dhd_int_wake_unlock(dhd_info_t *dhd) { - dhd_info_t *dhd = (dhd_info_t *)(pub->info); - unsigned long flags; int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); + ret = _dhd_release_wakelock(dhd); + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); - if (dhd) { - spin_lock_irqsave(&dhd->wakelock_spinlock, flags); - if (dhd->wakelock_counter == 0 && !dhd->waive_wakelock) { -#ifdef CONFIG_HAS_WAKELOCK - wake_lock(&dhd->wl_wifi); -#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) - dhd_bus_dev_pm_stay_awake(pub); -#endif - } - dhd->wakelock_counter++; - ret = dhd->wakelock_counter; - spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); - } return ret; } -int net_os_wake_lock(struct net_device *dev) +/* dhd_int_wake_lock_timeout: no-op. + * + * Originally used to finalize timeout requests and schedule timeouts on + * separate wakelocks, timeout is now checked by dhd_int_wake_unlock. + */ +int dhd_int_wake_lock_timeout(dhd_info_t *dhd) { - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - int ret = 0; - - if (dhd) - ret = dhd_os_wake_lock(&dhd->pub); - return ret; + return time_after(dhd_wl_timeout(dhd), jiffies); } -int dhd_os_wake_unlock(dhd_pub_t *pub) +/* dhd_int_wake_timeout_enable: advance wakelock timeout. */ +int dhd_int_wake_timeout_enable(dhd_info_t *dhd, int val, int wl) { - dhd_info_t *dhd = (dhd_info_t *)(pub->info); - unsigned long flags; - int ret = 0; + unsigned long flags, tmout; - dhd_os_wake_lock_timeout(pub); - if (dhd) { - spin_lock_irqsave(&dhd->wakelock_spinlock, flags); - if (dhd->wakelock_counter > 0) { - dhd->wakelock_counter--; - if (dhd->wakelock_counter == 0 && !dhd->waive_wakelock) { -#ifdef CONFIG_HAS_WAKELOCK - wake_unlock(&dhd->wl_wifi); -#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) - dhd_bus_dev_pm_relax(pub); -#endif - } - ret = dhd->wakelock_counter; - } - spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); - } - return ret; + if (!val) + return 0; + + tmout = jiffies + msecs_to_jiffies(val); + + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); + + // Timeout will only be checked when wl_wifi gets unlocked + if (unlikely(!wake_lock_active(&dhd->wl_wifi))) + pr_warn("%s: wakelock not active!\n", __func__); + + if (time_after(tmout, dhd->wl_timeout[wl])) + dhd->wl_timeout[wl] = tmout; + + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); + + return 0; } -int dhd_os_check_wakelock(dhd_pub_t *pub) +/* dhd_int_wake_timeout_cancel: cancel a running timeout */ +int dhd_int_wake_timeout_cancel(dhd_info_t *dhd, int wl) { -#if defined(CONFIG_HAS_WAKELOCK) || (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) - dhd_info_t *dhd; + unsigned long flags; + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); - if (!pub) - return 0; - dhd = (dhd_info_t *)(pub->info); -#endif /* CONFIG_HAS_WAKELOCK || BCMSDIO */ + dhd->wl_timeout[wl] = jiffies; + // wake_unlock will pick up the updated timeout when it's called + + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); -#ifdef CONFIG_HAS_WAKELOCK - /* Indicate to the SD Host to avoid going to suspend if internal locks are up */ - if (dhd && (wake_lock_active(&dhd->wl_wifi) || - (wake_lock_active(&dhd->wl_wdwake)))) - return 1; -#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) - if (dhd && (dhd->wakelock_counter > 0) && dhd_bus_dev_pm_enabled(pub)) - return 1; -#endif return 0; } -int net_os_wake_unlock(struct net_device *dev) + +/* dhd_os_check_wakelock: determine whether wlan wakelocks are held */ +int dhd_os_check_wakelock(dhd_pub_t *pub) { - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); int ret = 0; - if (dhd) - ret = dhd_os_wake_unlock(&dhd->pub); + if (likely(pub)) { + unsigned long flags; + spin_lock_irqsave(&pub->info->wakelock_spinlock, flags); + + // rx & ctrl wakelocks aren't considered; don't check wl_wifi + ret = !!pub->info->wakelock_counter; + + spin_unlock_irqrestore(&pub->info->wakelock_spinlock, flags); + } + return ret; } -int dhd_os_wd_wake_lock(dhd_pub_t *pub) +/* dhd_int_wd_wake_lock: take wakelock unless waived + * + * The original code counted wd_wake_lock calls, but immediately unlocked on + * wd_wake_unlock. Why bother? + */ +int dhd_int_wd_wake_lock(dhd_info_t *dhd) { - dhd_info_t *dhd = (dhd_info_t *)(pub->info); + int ret; unsigned long flags; - int ret = 0; - if (dhd) { - spin_lock_irqsave(&dhd->wakelock_spinlock, flags); - if (dhd->wakelock_wd_counter == 0 && !dhd->waive_wakelock) { -#ifdef CONFIG_HAS_WAKELOCK - /* if wakelock_wd_counter was never used : lock it at once */ - wake_lock(&dhd->wl_wdwake); -#endif + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); + + if (!(dhd->wakelock_wd_state & DHD_WD_LOCK)) { + dhd->wakelock_wd_state |= DHD_WD_LOCK; + if (!(dhd->wakelock_wd_state & DHD_WD_WAIVE)) { + _dhd_acquire_wakelock(dhd); } - dhd->wakelock_wd_counter++; - ret = dhd->wakelock_wd_counter; - spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); } + ret = dhd->wakelock_wd_state & DHD_WD_LOCK; + + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); + return ret; } -int dhd_os_wd_wake_unlock(dhd_pub_t *pub) +/* dhd_int_wd_wake_unlock: release wakelock unless waived */ +int dhd_int_wd_wake_unlock(dhd_info_t *dhd) { - dhd_info_t *dhd = (dhd_info_t *)(pub->info); unsigned long flags; - int ret = 0; - if (dhd) { - spin_lock_irqsave(&dhd->wakelock_spinlock, flags); - if (dhd->wakelock_wd_counter > 0) { - dhd->wakelock_wd_counter = 0; - if (!dhd->waive_wakelock) { -#ifdef CONFIG_HAS_WAKELOCK - wake_unlock(&dhd->wl_wdwake); -#endif - } + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); + + if (dhd->wakelock_wd_state & DHD_WD_LOCK) { + dhd->wakelock_wd_state &= ~DHD_WD_LOCK; + if (!(dhd->wakelock_wd_state & DHD_WD_WAIVE)) { + _dhd_release_wakelock(dhd); } - spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); } - return ret; + + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); + + return 0; } #ifdef PROP_TXSTATUS -/* waive wakelocks for operations such as IOVARs in suspend function, must be closed - * by a paired function call to dhd_wakelock_restore. returns current wakelock counter - */ -int dhd_wakelock_waive(dhd_info_t *dhdinfo) +/* dhd_wakelock_waive: waive and possibly release wakelock */ +int dhd_wakelock_waive(dhd_info_t *dhd) { + int ret; unsigned long flags; - int ret = 0; - spin_lock_irqsave(&dhdinfo->wakelock_spinlock, flags); - /* dhd_wakelock_waive/dhd_wakelock_restore must be paired */ - if (dhdinfo->waive_wakelock) - goto exit; - /* record current lock status */ - dhdinfo->wakelock_before_waive = dhdinfo->wakelock_counter; - dhdinfo->waive_wakelock = TRUE; + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); + + if (dhd->wakelock_wd_state == DHD_WD_LOCK) { + dhd->wakelock_wd_state |= DHD_WD_WAIVE; + _dhd_release_wakelock(dhd); + } + ret = dhd->wakelock_wd_state & DHD_WD_LOCK; + + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); -exit: - ret = dhdinfo->wakelock_wd_counter; - spin_unlock_irqrestore(&dhdinfo->wakelock_spinlock, flags); return ret; } -int dhd_wakelock_restore(dhd_info_t *dhdinfo) +/* dhd_wakelock_restore: restore and possibly acquire wakelock */ +int dhd_wakelock_restore(dhd_info_t *dhd) { + int ret; unsigned long flags; - int ret = 0; - spin_lock_irqsave(&dhdinfo->wakelock_spinlock, flags); - /* dhd_wakelock_waive/dhd_wakelock_restore must be paired */ - if (!dhdinfo->waive_wakelock) - goto exit; + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); - dhdinfo->waive_wakelock = FALSE; - /* if somebody else acquires wakelock between dhd_wakelock_waive/dhd_wakelock_restore, - * we need to make it up by calling wake_lock or pm_stay_awake. or if somebody releases - * the lock in between, do the same by calling wake_unlock or pm_relax - */ - if (dhdinfo->wakelock_before_waive == 0 && dhdinfo->wakelock_counter > 0) { -#ifdef CONFIG_HAS_WAKELOCK - wake_lock(&dhdinfo->wl_wifi); -#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) - dhd_bus_dev_pm_stay_awake(&dhdinfo->pub); -#endif - } else if (dhdinfo->wakelock_before_waive > 0 && dhdinfo->wakelock_counter == 0) { -#ifdef CONFIG_HAS_WAKELOCK - wake_unlock(&dhdinfo->wl_wifi); -#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) - dhd_bus_dev_pm_relax(&dhdinfo->pub); -#endif + if (dhd->wakelock_wd_state == DHD_WD_LOCK | DHD_WD_WAIVE) { + dhd->wakelock_wd_state &= ~DHD_WD_WAIVE; + _dhd_acquire_wakelock(dhd); } - dhdinfo->wakelock_before_waive = 0; -exit: - ret = dhdinfo->wakelock_wd_counter; - spin_unlock_irqrestore(&dhdinfo->wakelock_spinlock, flags); + ret = dhd->wakelock_wd_state & DHD_WD_LOCK; + + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); + return ret; } #endif /* PROP_TXSTATUS */ +#endif /* CONFIG_HAS_WAKELOCK */ bool dhd_os_check_if_up(dhd_pub_t *pub) { diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index 745ebf7f3683..9a14b2b93eb8 100755 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -163,7 +163,7 @@ extern bool bcmsdh_fatal_error(void *sdh); /* Packet free applicable unconditionally for sdio and sdspi. Conditional if * bufpool was present for gspi bus. */ -#define PKTFREE2() if ((bus->bus != SPI_BUS) || bus->usebufpool) \ +#define PKTFREE2() if ((DHD_BUS != SPI_BUS) || bus->usebufpool) \ PKTFREE(bus->dhd->osh, pkt, FALSE); DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep); @@ -227,7 +227,6 @@ typedef struct dhd_bus { uint32 orig_ramsize; /* Size of RAM in SOCRAM (bytes) */ uint32 srmemsize; /* Size of SRMEM */ - uint32 bus; /* gSPI or SDIO bus */ uint32 bus_num; /* bus number */ uint32 slot_num; /* slot ID */ uint32 hostintmask; /* Copy of Host Interrupt Mask */ @@ -4665,7 +4664,7 @@ dhdsdio_read_control(dhd_bus_t *bus, uint8 *hdr, uint len, uint doff) DHD_TRACE(("%s: Enter\n", __FUNCTION__)); /* Control data already received in aligned rxctl */ - if ((bus->bus == SPI_BUS) && (!bus->usebufpool)) + if ((DHD_BUS == SPI_BUS) && (!bus->usebufpool)) goto gotpkt; ASSERT(bus->rxbuf); @@ -4685,7 +4684,7 @@ dhdsdio_read_control(dhd_bus_t *bus, uint8 *hdr, uint len, uint doff) goto gotpkt; /* Copy the full data pkt in gSPI case and process ioctl. */ - if (bus->bus == SPI_BUS) { + if (DHD_BUS == SPI_BUS) { bcopy(hdr, bus->rxctl, len); goto gotpkt; } @@ -5242,7 +5241,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) #ifdef BCMSPI /* Get pktlen from gSPI device F0 reg. */ - if (bus->bus == SPI_BUS) { + if (DHD_BUS == SPI_BUS) { /* Peek in dstatus bits and find out size to do rx-read. */ dstatus = bcmsdh_get_dstatus(bus->sdh); if (dstatus == 0) @@ -5302,7 +5301,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) uint16 nextlen = bus->nextlen; bus->nextlen = 0; - if (bus->bus == SPI_BUS) { + if (DHD_BUS == SPI_BUS) { rdlen = len = nextlen; } else { @@ -5328,7 +5327,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) /* Allocate a packet buffer */ dhd_os_sdlock_rxq(bus->dhd); if (!(pkt = PKTGET(osh, rdlen + DHD_SDALIGN, FALSE))) { - if (bus->bus == SPI_BUS) { + if (DHD_BUS == SPI_BUS) { bus->usebufpool = FALSE; bus->rxctl = bus->rxbuf; if (dhd_alignctl) { @@ -5371,7 +5370,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) bus->rxc_errors++; dhd_os_sdunlock_rxq(bus->dhd); dhdsdio_rxfail(bus, TRUE, - (bus->bus == SPI_BUS) ? FALSE : TRUE); + (DHD_BUS == SPI_BUS) ? FALSE : TRUE); continue; } } else { @@ -5384,7 +5383,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) continue; } } else { - if (bus->bus == SPI_BUS) + if (DHD_BUS == SPI_BUS) bus->usebufpool = TRUE; ASSERT(!PKTLINK(pkt)); @@ -5421,7 +5420,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) * gSPI */ dhdsdio_rxfail(bus, TRUE, - (bus->bus == SPI_BUS) ? FALSE : TRUE); + (DHD_BUS == SPI_BUS) ? FALSE : TRUE); continue; } } @@ -5472,7 +5471,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) /* Check for consistency with readahead info */ #ifdef BCMSPI - if (bus->bus == SPI_BUS) { + if (DHD_BUS == SPI_BUS) { if (bus->dwordmode) { uint16 spilen; if ((bus->sih->chip == BCM4329_CHIP_ID) && @@ -5495,7 +5494,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) dhd_os_sdlock_rxq(bus->dhd); PKTFREE2(); dhd_os_sdunlock_rxq(bus->dhd); - dhdsdio_rxfail(bus, TRUE, (bus->bus == SPI_BUS) ? FALSE : TRUE); + dhdsdio_rxfail(bus, TRUE, (DHD_BUS == SPI_BUS) ? FALSE : TRUE); GSPI_PR55150_BAILOUT; continue; } @@ -5509,7 +5508,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) #ifdef BCMSPI /* Save the readahead length if there is one */ - if (bus->bus == SPI_BUS) { + if (DHD_BUS == SPI_BUS) { /* Use reconstructed dstatus bits and find out readahead size */ dstatus = bcmsdh_get_dstatus((void *)bus->sdh); DHD_INFO(("Device status from bit-reconstruction = 0x%x\n", @@ -5572,7 +5571,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) /* Check window for sanity */ if ((uint8)(txmax - bus->tx_seq) > 0x70) { #ifdef BCMSPI - if ((bus->bus == SPI_BUS) && !(dstatus & STATUS_F2_RX_READY)) { + if ((DHD_BUS == SPI_BUS) && !(dstatus & STATUS_F2_RX_READY)) { DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", __FUNCTION__, txmax, bus->tx_seq)); txmax = bus->tx_seq + 2; @@ -5596,7 +5595,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) #endif if (chan == SDPCM_CONTROL_CHANNEL) { - if (bus->bus == SPI_BUS) { + if (DHD_BUS == SPI_BUS) { dhdsdio_read_control(bus, rxbuf, len, doff); if (bus->usebufpool) { dhd_os_sdlock_rxq(bus->dhd); @@ -5617,7 +5616,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) } } - if ((bus->bus == SPI_BUS) && !bus->usebufpool) { + if ((DHD_BUS == SPI_BUS) && !bus->usebufpool) { DHD_ERROR(("Received %d bytes on %d channel. Running out of " "rx pktbuf's or not yet malloced.\n", len, chan)); continue; @@ -5639,7 +5638,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) goto deliver; } /* gSPI frames should not be handled in fractions */ - if (bus->bus == SPI_BUS) { + if (DHD_BUS == SPI_BUS) { break; } @@ -7114,7 +7113,6 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, bzero(bus, sizeof(dhd_bus_t)); bus->sdh = sdh; bus->cl_devid = (uint16)devid; - bus->bus = DHD_BUS; bus->bus_num = bus_no; bus->slot_num = slot; bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1; @@ -8655,7 +8653,7 @@ uint dhd_bus_chippkg_id(dhd_pub_t *dhdp) int dhd_bus_get_ids(struct dhd_bus *bus, uint32 *bus_type, uint32 *bus_num, uint32 *slot_num) { - *bus_type = bus->bus; + *bus_type = DHD_BUS; *bus_num = bus->bus_num; *slot_num = bus->slot_num; return 0; diff --git a/drivers/net/wireless/bcmdhd/dhd_wlfc.c b/drivers/net/wireless/bcmdhd/dhd_wlfc.c index 4f338791e50c..f5aef8436f5d 100755 --- a/drivers/net/wireless/bcmdhd/dhd_wlfc.c +++ b/drivers/net/wireless/bcmdhd/dhd_wlfc.c @@ -174,7 +174,7 @@ _dhd_wlfc_hanger_create(osl_t *osh, int max_items) wlfc_hanger_t* hanger; /* allow only up to a specific size for now */ - ASSERT(max_items == WLFC_HANGER_MAXITEMS); + ASSERT(max_items <= WLFC_HANGER_MAXITEMS); if ((hanger = (wlfc_hanger_t*)MALLOC(osh, WLFC_HANGER_SIZE(max_items))) == NULL) return NULL; diff --git a/drivers/net/wireless/bcmdhd/dhd_wlfc.h b/drivers/net/wireless/bcmdhd/dhd_wlfc.h index 5262233d3fdb..e7427a1316d7 100755 --- a/drivers/net/wireless/bcmdhd/dhd_wlfc.h +++ b/drivers/net/wireless/bcmdhd/dhd_wlfc.h @@ -64,8 +64,7 @@ typedef enum ewlfc_mac_entry_action { typedef struct wlfc_hanger_item { uint8 state; uint8 gen; - uint8 pad[2]; - uint32 identifier; + uint16 identifier; void* pkt; #ifdef PROP_TXSTATUS_DEBUG uint32 push_time; @@ -74,18 +73,18 @@ typedef struct wlfc_hanger_item { } wlfc_hanger_item_t; typedef struct wlfc_hanger { - int max_items; + uint16 max_items; + uint16 slot_pos; uint32 pushed; uint32 popped; uint32 failed_to_push; uint32 failed_to_pop; uint32 failed_slotfind; - uint32 slot_pos; - wlfc_hanger_item_t items[1]; + wlfc_hanger_item_t items[0]; } wlfc_hanger_t; -#define WLFC_HANGER_SIZE(n) ((sizeof(wlfc_hanger_t) - \ - sizeof(wlfc_hanger_item_t)) + ((n)*sizeof(wlfc_hanger_item_t))) +#define WLFC_HANGER_SIZE(n) (sizeof(wlfc_hanger_t) + \ + (n)*sizeof(wlfc_hanger_item_t)) #define WLFC_STATE_OPEN 1 #define WLFC_STATE_CLOSE 2 diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index d5f3539f11aa..f78787ec5e7b 100755 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -115,11 +115,13 @@ static struct device *cfg80211_parent_dev = NULL; /* g_bcm_cfg should be static. Do not change */ static struct bcm_cfg80211 *g_bcm_cfg = NULL; +#ifdef DEBUGFS_CFG80211 #ifdef CUSTOMER_HW4 u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_P2P_ACTION; #else u32 wl_dbg_level = WL_DBG_ERR; #endif +#endif #define MAX_WAIT_TIME 1500 @@ -486,7 +488,7 @@ static void wl_ch_to_chanspec(int ch, * information element utilities */ static void wl_rst_ie(struct bcm_cfg80211 *cfg); -static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v); +static __maybe_unused s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v); static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size); static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size); static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size); @@ -535,7 +537,7 @@ static void wl_delay(u32 ms); * ibss mode utilities */ static bool wl_is_ibssmode(struct bcm_cfg80211 *cfg, struct net_device *ndev); -static __used bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg); +static __maybe_unused bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg); /* * link up/down , default configuration utilities @@ -558,7 +560,7 @@ int wl_cfg80211_get_ioctl_version(void); /* * find most significant bit set */ -static __used u32 wl_find_msb(u16 bit16); +static __maybe_unused u32 wl_find_msb(u16 bit16); /* * rfkill support @@ -4677,7 +4679,7 @@ void wl_cfg80211_update_power_mode(struct net_device *dev) dev->ieee80211_ptr->ps = (pm == PM_OFF) ? false : true; } -static __used u32 wl_find_msb(u16 bit16) +static __maybe_unused u32 wl_find_msb(u16 bit16) { u32 ret = 0; @@ -11315,7 +11317,7 @@ static bool wl_is_ibssmode(struct bcm_cfg80211 *cfg, struct net_device *ndev) return wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS; } -static __used bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg) +static __maybe_unused bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg) { return cfg->ibss_starter; } @@ -11327,7 +11329,7 @@ static void wl_rst_ie(struct bcm_cfg80211 *cfg) ie->offset = 0; } -static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v) +static __maybe_unused s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v) { struct wl_ie *ie = wl_to_ie(cfg); s32 err = 0; @@ -12201,6 +12203,7 @@ int wl_cfg80211_do_driver_init(struct net_device *net) return 0; } +#ifdef DEBUGFS_CFG80211 void wl_cfg80211_enable_trace(bool set, u32 level) { if (set) @@ -12208,6 +12211,7 @@ void wl_cfg80211_enable_trace(bool set, u32 level) else wl_dbg_level |= (WL_DBG_LEVEL & level); } +#endif #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \ 2, 0)) static s32 diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index 75dd37a352dc..fcef5f7a0b20 100755 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -942,7 +942,11 @@ extern s32 wl_cfg80211_get_best_channels(struct net_device *dev, char* command, extern int wl_cfg80211_hang(struct net_device *dev, u16 reason); extern s32 wl_mode_to_nl80211_iftype(s32 mode); int wl_cfg80211_do_driver_init(struct net_device *net); +#ifdef DEBUGFS_CFG80211 void wl_cfg80211_enable_trace(bool set, u32 level); +#else +static inline void wl_cfg80211_enable_trace(bool set, u32 level) { } +#endif extern s32 wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify); extern s32 wl_cfg80211_if_is_group_owner(void); extern chanspec_t wl_ch_host_to_driver(u16 channel); diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c index 12b4949c1170..ef574255ae80 100755 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c @@ -222,110 +222,6 @@ bool wl_cfgp2p_is_p2p_gas_action(void *frame, u32 frame_len) return false; } #endif /* CUSTOMER_HW4 */ -void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len, u32 channel) -{ - wifi_p2p_pub_act_frame_t *pact_frm; - wifi_p2p_action_frame_t *act_frm; - wifi_p2psd_gas_pub_act_frame_t *sd_act_frm; - if (!frame || frame_len <= 2) - return; - - if (wl_cfgp2p_is_pub_action(frame, frame_len)) { - pact_frm = (wifi_p2p_pub_act_frame_t *)frame; - switch (pact_frm->subtype) { - case P2P_PAF_GON_REQ: - CFGP2P_ACTION(("%s P2P Group Owner Negotiation Req Frame," - " channel=%d\n", (tx)? "TX": "RX", channel)); - break; - case P2P_PAF_GON_RSP: - CFGP2P_ACTION(("%s P2P Group Owner Negotiation Rsp Frame," - " channel=%d\n", (tx)? "TX": "RX", channel)); - break; - case P2P_PAF_GON_CONF: - CFGP2P_ACTION(("%s P2P Group Owner Negotiation Confirm Frame," - " channel=%d\n", (tx)? "TX": "RX", channel)); - break; - case P2P_PAF_INVITE_REQ: - CFGP2P_ACTION(("%s P2P Invitation Request Frame," - " channel=%d\n", (tx)? "TX": "RX", channel)); - break; - case P2P_PAF_INVITE_RSP: - CFGP2P_ACTION(("%s P2P Invitation Response Frame," - " channel=%d\n", (tx)? "TX": "RX", channel)); - break; - case P2P_PAF_DEVDIS_REQ: - CFGP2P_ACTION(("%s P2P Device Discoverability Request Frame," - " channel=%d\n", (tx)? "TX": "RX", channel)); - break; - case P2P_PAF_DEVDIS_RSP: - CFGP2P_ACTION(("%s P2P Device Discoverability Response Frame," - " channel=%d\n", (tx)? "TX": "RX", channel)); - break; - case P2P_PAF_PROVDIS_REQ: - CFGP2P_ACTION(("%s P2P Provision Discovery Request Frame," - " channel=%d\n", (tx)? "TX": "RX", channel)); - break; - case P2P_PAF_PROVDIS_RSP: - CFGP2P_ACTION(("%s P2P Provision Discovery Response Frame," - " channel=%d\n", (tx)? "TX": "RX", channel)); - break; - default: - CFGP2P_ACTION(("%s Unknown P2P Public Action Frame," - " channel=%d\n", (tx)? "TX": "RX", channel)); - - } - - } else if (wl_cfgp2p_is_p2p_action(frame, frame_len)) { - act_frm = (wifi_p2p_action_frame_t *)frame; - switch (act_frm->subtype) { - case P2P_AF_NOTICE_OF_ABSENCE: - CFGP2P_ACTION(("%s P2P Notice of Absence Frame," - " channel=%d\n", (tx)? "TX": "RX", channel)); - break; - case P2P_AF_PRESENCE_REQ: - CFGP2P_ACTION(("%s P2P Presence Request Frame," - " channel=%d\n", (tx)? "TX": "RX", channel)); - break; - case P2P_AF_PRESENCE_RSP: - CFGP2P_ACTION(("%s P2P Presence Response Frame," - " channel=%d\n", (tx)? "TX": "RX", channel)); - break; - case P2P_AF_GO_DISC_REQ: - CFGP2P_ACTION(("%s P2P Discoverability Request Frame," - " channel=%d\n", (tx)? "TX": "RX", channel)); - break; - default: - CFGP2P_ACTION(("%s Unknown P2P Action Frame," - " channel=%d\n", (tx)? "TX": "RX", channel)); - } - - } else if (wl_cfgp2p_is_gas_action(frame, frame_len)) { - sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame; - switch (sd_act_frm->action) { - case P2PSD_ACTION_ID_GAS_IREQ: - CFGP2P_ACTION(("%s P2P GAS Initial Request," - " channel=%d\n", (tx)? "TX" : "RX", channel)); - break; - case P2PSD_ACTION_ID_GAS_IRESP: - CFGP2P_ACTION(("%s P2P GAS Initial Response," - " channel=%d\n", (tx)? "TX" : "RX", channel)); - break; - case P2PSD_ACTION_ID_GAS_CREQ: - CFGP2P_ACTION(("%s P2P GAS Comback Request," - " channel=%d\n", (tx)? "TX" : "RX", channel)); - break; - case P2PSD_ACTION_ID_GAS_CRESP: - CFGP2P_ACTION(("%s P2P GAS Comback Response," - " channel=%d\n", (tx)? "TX" : "RX", channel)); - break; - default: - CFGP2P_ACTION(("%s Unknown P2P GAS Frame," - " channel=%d\n", (tx)? "TX" : "RX", channel)); - } - - - } -} /* * Initialize variables related to P2P diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h index 0e6318423dff..a1b92cd7c570 100755 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h @@ -29,7 +29,11 @@ #include struct bcm_cfg80211; +#ifdef DEBUGFS_CFG80211 extern u32 wl_dbg_level; +#else +#define wl_dbg_level (0) +#endif typedef struct wifi_p2p_ie wifi_wfd_ie_t; /* Enumeration of the usages of the BSSCFGs used by the P2P Library. Do not @@ -239,8 +243,8 @@ wl_cfgp2p_find_gas_subtype(u8 subtype, u8* data, u32 len); extern bool wl_cfgp2p_is_p2p_gas_action(void *frame, u32 frame_len); #endif /* CUSTOMER_HW4 */ -extern void -wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len, u32 channel); +static inline void wl_cfgp2p_print_actframe(bool tx, void *frame, + u32 frame_len, u32 channel) { } extern s32 wl_cfgp2p_init_priv(struct bcm_cfg80211 *cfg); extern void diff --git a/drivers/net/wireless/bcmdhd/wldev_common.h b/drivers/net/wireless/bcmdhd/wldev_common.h index 378d7bd5ceba..e27ebddfa4a1 100755 --- a/drivers/net/wireless/bcmdhd/wldev_common.h +++ b/drivers/net/wireless/bcmdhd/wldev_common.h @@ -94,10 +94,6 @@ extern void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec, boo extern void dhd_bus_band_set(struct net_device *dev, uint band); extern int wldev_set_country(struct net_device *dev, char *country_code, bool notify, bool user_enforced); -extern int net_os_wake_lock(struct net_device *dev); -extern int net_os_wake_unlock(struct net_device *dev); -extern int net_os_wake_lock_timeout(struct net_device *dev); -extern int net_os_wake_lock_timeout_enable(struct net_device *dev, int val); extern int net_os_set_dtim_skip(struct net_device *dev, int val); extern int net_os_set_suspend_disable(struct net_device *dev, int val); extern int net_os_set_suspend(struct net_device *dev, int val, int force); diff --git a/drivers/staging/tidspbridge/core/dsp-clock.c b/drivers/staging/tidspbridge/core/dsp-clock.c index c7df34e6b60b..f82581428bb0 100644 --- a/drivers/staging/tidspbridge/core/dsp-clock.c +++ b/drivers/staging/tidspbridge/core/dsp-clock.c @@ -213,7 +213,7 @@ int dsp_clk_enable(enum dsp_clk_id clk_id) case GPT_CLK: status = omap_dm_timer_start(timer[clk_id - 1]); break; -#ifdef CONFIG_OMAP_MCBSP +#ifdef CONFIG_SND_OMAP_SOC_MCBSP case MCBSP_CLK: omap_mcbsp_request(MCBSP_ID(clk_id)); omap2_mcbsp_set_clks_src(MCBSP_ID(clk_id), MCBSP_CLKS_PAD_SRC); @@ -289,7 +289,7 @@ int dsp_clk_disable(enum dsp_clk_id clk_id) case GPT_CLK: status = omap_dm_timer_stop(timer[clk_id - 1]); break; -#ifdef CONFIG_OMAP_MCBSP +#ifdef CONFIG_SND_OMAP_SOC_MCBSP case MCBSP_CLK: omap2_mcbsp_set_clks_src(MCBSP_ID(clk_id), MCBSP_CLKS_PRCM_SRC); omap_mcbsp_free(MCBSP_ID(clk_id)); diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index 8b68f7b82631..fa4e21b882a0 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -177,7 +177,7 @@ static int rd_build_device_space(struct rd_dev *rd_dev) - 1; for (j = 0; j < sg_per_table; j++) { - pg = alloc_pages(GFP_KERNEL, 0); + pg = alloc_pages(GFP_KERNEL | __GFP_ZERO, 0); if (!pg) { pr_err("Unable to allocate scatterlist" " pages for struct rd_dev_sg_table\n"); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 787d14272330..eefbfda69c4b 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -532,6 +532,10 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) dwc3_remove_requests(dwc, dep); + /* make sure HW endpoint isn't stalled */ + if (dep->flags & DWC3_EP_STALL) + __dwc3_gadget_ep_set_halt(dep, 0); + reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); reg &= ~DWC3_DALEPENA_EP(dep->number); dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index e58b16442971..d9eaaa3b3e44 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1499,7 +1499,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) } break; -#ifndef CONFIG_USB_GADGET_PXA25X +#ifndef CONFIG_USB_PXA25X /* PXA automagically handles this request too */ case USB_REQ_GET_CONFIGURATION: if (ctrl->bRequestType != 0x80) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 78933512c18b..90dcf54cd7e8 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -555,6 +555,14 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = { DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), }, }, + { + /* HASEE E200 */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HASEE"), + DMI_MATCH(DMI_BOARD_NAME, "E210"), + DMI_MATCH(DMI_BIOS_VERSION, "6.00"), + }, + }, { } }; @@ -564,9 +572,14 @@ static void __devinit ehci_bios_handoff(struct pci_dev *pdev, { int try_handoff = 1, tried_handoff = 0; - /* The Pegatron Lucid tablet sporadically waits for 98 seconds trying - * the handoff on its unused controller. Skip it. */ - if (pdev->vendor == 0x8086 && pdev->device == 0x283a) { + /* + * The Pegatron Lucid tablet sporadically waits for 98 seconds trying + * the handoff on its unused controller. Skip it. + * + * The HASEE E200 hangs when the semaphore is set (bugzilla #77021). + */ + if (pdev->vendor == 0x8086 && (pdev->device == 0x283a || + pdev->device == 0x27cc)) { if (dmi_check_system(ehci_dmi_nohandoff_table)) try_handoff = 0; } diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 055b84adedac..174be05ba2c7 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -7,9 +7,10 @@ #include #include #include - +#include #include +#define SIMPLE_IO_TIMEOUT 10000 /* in milliseconds */ /*-------------------------------------------------------------------------*/ @@ -355,6 +356,7 @@ static int simple_io( int max = urb->transfer_buffer_length; struct completion completion; int retval = 0; + unsigned long expire; urb->context = &completion; while (retval == 0 && iterations-- > 0) { @@ -367,9 +369,15 @@ static int simple_io( if (retval != 0) break; - /* NOTE: no timeouts; can't be broken out of by interrupt */ - wait_for_completion(&completion); - retval = urb->status; + expire = msecs_to_jiffies(SIMPLE_IO_TIMEOUT); + if (!wait_for_completion_timeout(&completion, expire)) { + usb_kill_urb(urb); + retval = (urb->status == -ENOENT ? + -ETIMEDOUT : urb->status); + } else { + retval = urb->status; + } + urb->dev = udev; if (retval == 0 && usb_pipein(urb->pipe)) retval = simple_check_buf(tdev, urb); @@ -462,6 +470,14 @@ alloc_sglist(int nents, int max, int vary) return sg; } +static void sg_timeout(unsigned long _req) +{ + struct usb_sg_request *req = (struct usb_sg_request *) _req; + + req->status = -ETIMEDOUT; + usb_sg_cancel(req); +} + static int perform_sglist( struct usbtest_dev *tdev, unsigned iterations, @@ -473,6 +489,9 @@ static int perform_sglist( { struct usb_device *udev = testdev_to_usbdev(tdev); int retval = 0; + struct timer_list sg_timer; + + setup_timer_on_stack(&sg_timer, sg_timeout, (unsigned long) req); while (retval == 0 && iterations-- > 0) { retval = usb_sg_init(req, udev, pipe, @@ -483,7 +502,10 @@ static int perform_sglist( if (retval) break; + mod_timer(&sg_timer, jiffies + + msecs_to_jiffies(SIMPLE_IO_TIMEOUT)); usb_sg_wait(req); + del_timer_sync(&sg_timer); retval = req->status; /* FIXME check resulting data pattern */ @@ -1135,6 +1157,11 @@ static int unlink1(struct usbtest_dev *dev, int pipe, int size, int async) urb->context = &completion; urb->complete = unlink1_callback; + if (usb_pipeout(urb->pipe)) { + simple_fill_buf(urb); + urb->transfer_flags |= URB_ZERO_PACKET; + } + /* keep the endpoint busy. there are lots of hc/hcd-internal * states, and testing should get to all of them over time. * @@ -1265,6 +1292,11 @@ static int unlink_queued(struct usbtest_dev *dev, int pipe, unsigned num, unlink_queued_callback, &ctx); ctx.urbs[i]->transfer_dma = buf_dma; ctx.urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; + + if (usb_pipeout(ctx.urbs[i]->pipe)) { + simple_fill_buf(ctx.urbs[i]); + ctx.urbs[i]->transfer_flags |= URB_ZERO_PACKET; + } } /* Submit all the URBs and then unlink URBs num - 4 and num - 2. */ diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index e9c113dab5c4..137353d5e3aa 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1928,6 +1928,7 @@ static int option_send_setup(struct usb_serial_port *port) struct usb_wwan_port_private *portdata; int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; int val = 0; + int res; dbg("%s", __func__); if (is_blacklisted(ifNum, OPTION_BLACKLIST_SENDSETUP, @@ -1943,9 +1944,17 @@ static int option_send_setup(struct usb_serial_port *port) if (portdata->rts_state) val |= 0x02; - return usb_control_msg(serial->dev, - usb_rcvctrlpipe(serial->dev, 0), - 0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT); + res = usb_autopm_get_interface(serial->interface); + if (res) + return res; + + res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + 0x22, 0x21, val, ifNum, NULL, + 0, USB_CTRL_SET_TIMEOUT); + + usb_autopm_put_interface(serial->interface); + + return res; } MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 3f5e4a73ddd5..bd79d68b51c1 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -59,6 +59,7 @@ struct sierra_intf_private { spinlock_t susp_lock; unsigned int suspended:1; int in_flight; + unsigned int open_ports; }; static int sierra_set_power_state(struct usb_device *udev, __u16 swiState) @@ -801,6 +802,7 @@ static void sierra_close(struct usb_serial_port *port) struct usb_serial *serial = port->serial; struct sierra_port_private *portdata; struct sierra_intf_private *intfdata = port->serial->private; + struct urb *urb; dev_dbg(&port->dev, "%s\n", __func__); @@ -812,7 +814,6 @@ static void sierra_close(struct usb_serial_port *port) if (serial->dev) { mutex_lock(&serial->disc_mutex); if (!serial->disconnected) { - serial->interface->needs_remote_wakeup = 0; /* odd error handling due to pm counters */ if (!usb_autopm_get_interface(serial->interface)) sierra_send_setup(port); @@ -823,8 +824,21 @@ static void sierra_close(struct usb_serial_port *port) mutex_unlock(&serial->disc_mutex); spin_lock_irq(&intfdata->susp_lock); portdata->opened = 0; + if (--intfdata->open_ports == 0) + serial->interface->needs_remote_wakeup = 0; spin_unlock_irq(&intfdata->susp_lock); + for (;;) { + urb = usb_get_from_anchor(&portdata->delayed); + if (!urb) + break; + kfree(urb->transfer_buffer); + usb_free_urb(urb); + usb_autopm_put_interface_async(serial->interface); + spin_lock(&portdata->lock); + portdata->outstanding_urbs--; + spin_unlock(&portdata->lock); + } /* Stop reading urbs */ sierra_stop_rx_urbs(port); @@ -867,23 +881,29 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port) usb_sndbulkpipe(serial->dev, endpoint) | USB_DIR_IN); err = sierra_submit_rx_urbs(port, GFP_KERNEL); - if (err) { - /* get rid of everything as in close */ - sierra_close(port); - /* restore balance for autopm */ - if (!serial->disconnected) - usb_autopm_put_interface(serial->interface); - return err; - } + if (err) + goto err_submit; + sierra_send_setup(port); - serial->interface->needs_remote_wakeup = 1; spin_lock_irq(&intfdata->susp_lock); portdata->opened = 1; + if (++intfdata->open_ports == 1) + serial->interface->needs_remote_wakeup = 1; spin_unlock_irq(&intfdata->susp_lock); usb_autopm_put_interface(serial->interface); return 0; + +err_submit: + sierra_stop_rx_urbs(port); + + for (i = 0; i < portdata->num_in_urbs; i++) { + sierra_release_urb(portdata->in_urbs[i]); + portdata->in_urbs[i] = NULL; + } + + return err; } @@ -994,6 +1014,7 @@ static void sierra_release(struct usb_serial *serial) portdata = usb_get_serial_port_data(port); if (!portdata) continue; + usb_set_serial_port_data(port, NULL); kfree(portdata); } kfree(serial->private); @@ -1010,6 +1031,8 @@ static void stop_read_write_urbs(struct usb_serial *serial) for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; portdata = usb_get_serial_port_data(port); + if (!portdata) + continue; sierra_stop_rx_urbs(port); usb_kill_anchored_urbs(&portdata->active); } @@ -1052,6 +1075,9 @@ static int sierra_resume(struct usb_serial *serial) port = serial->port[i]; portdata = usb_get_serial_port_data(port); + if (!portdata) + continue; + while ((urb = usb_get_from_anchor(&portdata->delayed))) { usb_anchor_urb(urb, &portdata->active); intfdata->in_flight++; @@ -1059,8 +1085,12 @@ static int sierra_resume(struct usb_serial *serial) if (err < 0) { intfdata->in_flight--; usb_unanchor_urb(urb); - usb_scuttle_anchored_urbs(&portdata->delayed); - break; + kfree(urb->transfer_buffer); + usb_free_urb(urb); + spin_lock(&portdata->lock); + portdata->outstanding_urbs--; + spin_unlock(&portdata->lock); + continue; } } diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 49f3a85c762b..5eb264a5ebd5 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -236,8 +236,10 @@ int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, usb_pipeendpoint(this_urb->pipe), i); err = usb_autopm_get_interface_async(port->serial->interface); - if (err < 0) + if (err < 0) { + clear_bit(i, &portdata->out_busy); break; + } /* send the data */ memcpy(this_urb->transfer_buffer, buf, todo); @@ -518,6 +520,14 @@ int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port) set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); dbg("%s", __func__); + if (port->interrupt_in_urb) { + err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); + if (err) { + dev_dbg(&port->dev, "%s: submit int urb failed: %d\n", + __func__, err); + } + } + /* Start reading from the IN endpoint */ for (i = 0; i < N_IN_URB; i++) { urb = portdata->in_urbs[i]; @@ -546,12 +556,26 @@ int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port) } EXPORT_SYMBOL(usb_wwan_open); +static void unbusy_queued_urb(struct urb *urb, + struct usb_wwan_port_private *portdata) +{ + int i; + + for (i = 0; i < N_OUT_URB; i++) { + if (urb == portdata->out_urbs[i]) { + clear_bit(i, &portdata->out_busy); + break; + } + } +} + void usb_wwan_close(struct usb_serial_port *port) { int i; struct usb_serial *serial = port->serial; struct usb_wwan_port_private *portdata; struct usb_wwan_intf_private *intfdata = port->serial->private; + struct urb *urb; dbg("%s", __func__); portdata = usb_get_serial_port_data(port); @@ -562,10 +586,19 @@ void usb_wwan_close(struct usb_serial_port *port) portdata->opened = 0; spin_unlock_irq(&intfdata->susp_lock); + for (;;) { + urb = usb_get_from_anchor(&portdata->delayed); + if (!urb) + break; + unbusy_queued_urb(urb, portdata); + usb_autopm_put_interface_async(serial->interface); + } + for (i = 0; i < N_IN_URB; i++) usb_kill_urb(portdata->in_urbs[i]); for (i = 0; i < N_OUT_URB; i++) usb_kill_urb(portdata->out_urbs[i]); + usb_kill_urb(port->interrupt_in_urb); /* balancing - important as an error cannot be handled*/ usb_autopm_get_interface_no_resume(serial->interface); serial->interface->needs_remote_wakeup = 0; @@ -641,7 +674,7 @@ static void usb_wwan_setup_urbs(struct usb_serial *serial) int usb_wwan_startup(struct usb_serial *serial) { - int i, j, err; + int i, j; struct usb_serial_port *port; struct usb_wwan_port_private *portdata; u8 *buffer; @@ -678,12 +711,6 @@ int usb_wwan_startup(struct usb_serial *serial) } usb_set_serial_port_data(port, portdata); - - if (!port->interrupt_in_urb) - continue; - err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); - if (err) - dbg("%s: submit irq_in urb failed %d", __func__, err); } usb_wwan_setup_urbs(serial); return 0; @@ -769,46 +796,32 @@ EXPORT_SYMBOL(usb_wwan_release); int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message) { struct usb_wwan_intf_private *intfdata = serial->private; - int b; dbg("%s entered", __func__); + spin_lock_irq(&intfdata->susp_lock); if (PMSG_IS_AUTO(message)) { - spin_lock_irq(&intfdata->susp_lock); - b = intfdata->in_flight; - spin_unlock_irq(&intfdata->susp_lock); - - if (b || pm_runtime_autosuspend_expiration(&serial->dev->dev)) + if (intfdata->in_flight) { + spin_unlock_irq(&intfdata->susp_lock); return -EBUSY; + } } - spin_lock_irq(&intfdata->susp_lock); intfdata->suspended = 1; spin_unlock_irq(&intfdata->susp_lock); + stop_read_write_urbs(serial); return 0; } EXPORT_SYMBOL(usb_wwan_suspend); -static void unbusy_queued_urb(struct urb *urb, struct usb_wwan_port_private *portdata) -{ - int i; - - for (i = 0; i < N_OUT_URB; i++) { - if (urb == portdata->out_urbs[i]) { - clear_bit(i, &portdata->out_busy); - break; - } - } -} - -static void play_delayed(struct usb_serial_port *port) +static int play_delayed(struct usb_serial_port *port) { struct usb_wwan_intf_private *data; struct usb_wwan_port_private *portdata; struct urb *urb; - int err; + int err = 0; portdata = usb_get_serial_port_data(port); data = port->serial->private; @@ -827,6 +840,8 @@ static void play_delayed(struct usb_serial_port *port) break; } } + + return err; } int usb_wwan_resume(struct usb_serial *serial) @@ -836,36 +851,36 @@ int usb_wwan_resume(struct usb_serial *serial) struct usb_wwan_intf_private *intfdata = serial->private; struct usb_wwan_port_private *portdata; struct urb *urb; - int err = 0; + int err; + int err_count = 0; dbg("%s entered", __func__); - /* get the interrupt URBs resubmitted unconditionally */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - if (!port->interrupt_in_urb) { - dbg("%s: No interrupt URB for port %d", __func__, i); - continue; - } - err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); - dbg("Submitted interrupt URB for port %d (result %d)", i, err); - if (err < 0) { - err("%s: Error %d for interrupt URB of port%d", - __func__, err, i); - goto err_out; - } - } spin_lock_irq(&intfdata->susp_lock); - intfdata->suspended = 0; for (i = 0; i < serial->num_ports; i++) { /* walk all ports */ port = serial->port[i]; portdata = usb_get_serial_port_data(port); /* skip closed ports */ - if (!portdata->opened) + if (!portdata || !portdata->opened) continue; + if (port->interrupt_in_urb) { + err = usb_submit_urb(port->interrupt_in_urb, + GFP_ATOMIC); + if (err) { + dev_err(&port->dev, + "%s: submit int urb failed: %d\n", + __func__, err); + err_count++; + } + } + + err = play_delayed(port); + if (err) + err_count++; + for (j = 0; j < N_IN_URB; j++) { urb = portdata->in_urbs[j]; @@ -877,20 +892,19 @@ int usb_wwan_resume(struct usb_serial *serial) usb_anchor_urb(urb, &portdata->submitted); err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { - err("%s: Error %d for bulk URB[%d]:%p %d", - __func__, err, j, urb, i); - usb_unanchor_urb(urb); - intfdata->suspended = 1; - spin_unlock_irq(&intfdata->susp_lock); - goto err_out; + err("%s: Error %d for bulk URB %d", + __func__, err, i); + err_count++; } } - play_delayed(port); } + intfdata->suspended = 0; spin_unlock_irq(&intfdata->susp_lock); -err_out: - return err; + if (err_count) + return -EIO; + + return 0; } EXPORT_SYMBOL(usb_wwan_resume); #endif diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h index 556d96ce40bf..89a8a89a5eb2 100644 --- a/drivers/video/matrox/matroxfb_base.h +++ b/drivers/video/matrox/matroxfb_base.h @@ -698,7 +698,7 @@ void matroxfb_unregister_driver(struct matroxfb_driver* drv); #define mga_fifo(n) do {} while ((mga_inl(M_FIFOSTATUS) & 0xFF) < (n)) -#define WaitTillIdle() do {} while (mga_inl(M_STATUS) & 0x10000) +#define WaitTillIdle() do { mga_inl(M_STATUS); do {} while (mga_inl(M_STATUS) & 0x10000); } while (0) /* code speedup */ #ifdef CONFIG_FB_MATROX_MILLENIUM diff --git a/drivers/video/msm/mipi_samsung_oled.c b/drivers/video/msm/mipi_samsung_oled.c index 92557c6f682d..03d156dfd4b2 100644 --- a/drivers/video/msm/mipi_samsung_oled.c +++ b/drivers/video/msm/mipi_samsung_oled.c @@ -1354,6 +1354,7 @@ static DEVICE_ATTR(auto_brightness, S_IRUGO | S_IWUSR | S_IWGRP, #endif + #ifdef READ_REGISTER_ESD #define ID_E5H_IDLE 0x80 #define ID_E5H_IDLE_2 0x84 diff --git a/drivers/video/msm/smart_mtp_ea8868.c b/drivers/video/msm/smart_mtp_ea8868.c index 9507ebd00fe5..ae272af32daf 100644 --- a/drivers/video/msm/smart_mtp_ea8868.c +++ b/drivers/video/msm/smart_mtp_ea8868.c @@ -38,14 +38,6 @@ Copyright (C) 2012, Samsung Electronics. All rights reserved. #define SMART_DIMMING_DEBUG */ -int color_mods[5][9] = { - { 0, 0, 5, -18, -16, -10, 0, 0, 3 }, - { 0, 0, 2, -9, -8, -5, 0, 0, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, -2, 9, 8, 5, 0, 0, -1 }, - { 0, 0, -5, 18, 16, 10, 0, 0, -3 } -}; -unsigned int panelval = 2; struct SMART_DIM *gpsmart; static int char_to_int(char data1) @@ -60,9 +52,16 @@ static int char_to_int(char data1) return cal_data; } -void panel_load_colors(unsigned int val) +extern int v255_val[3]; +extern int v1_val[3]; +extern int v171_val[3]; +extern int v87_val[3]; +extern int v59_val[3]; +extern int v35_val[3]; +extern int v15_val[3]; + +void panel_load_colors(void) { - panelval = val; smart_dimming_init(gpsmart); } @@ -76,7 +75,11 @@ static int v255_adjustment(struct SMART_DIM *pSmart) LSB = char_to_int(pSmart->MTP.R_OFFSET.OFFSET_255_LSB); add_mtp = LSB + V255_300CD_R_LSB; - result_1 = result_2 = (v255_coefficient+add_mtp + color_mods[panelval][0]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_1 = result_2 = (v255_coefficient+add_mtp) << BIT_SHIFT; +#else + result_1 = result_2 = (v255_coefficient+add_mtp + v255_val[0]) << BIT_SHIFT; +#endif do_div(result_2, v255_denominator); result_3 = (EA8868_VREG0_REF * result_2) >> BIT_SHIFT; result_4 = EA8868_VREG0_REF - result_3; @@ -85,7 +88,11 @@ static int v255_adjustment(struct SMART_DIM *pSmart) LSB = char_to_int(pSmart->MTP.G_OFFSET.OFFSET_255_LSB); add_mtp = LSB + V255_300CD_G_LSB; - result_1 = result_2 = (v255_coefficient+add_mtp + color_mods[panelval][1]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_1 = result_2 = (v255_coefficient+add_mtp) << BIT_SHIFT; +#else + result_1 = result_2 = (v255_coefficient+add_mtp + v255_val[1]) << BIT_SHIFT; +#endif do_div(result_2, v255_denominator); result_3 = (EA8868_VREG0_REF * result_2) >> BIT_SHIFT; result_4 = EA8868_VREG0_REF - result_3; @@ -94,7 +101,11 @@ static int v255_adjustment(struct SMART_DIM *pSmart) LSB = char_to_int(pSmart->MTP.B_OFFSET.OFFSET_255_LSB); add_mtp = LSB + V255_300CD_B_LSB; - result_1 = result_2 = (v255_coefficient+add_mtp + color_mods[panelval][2]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_1 = result_2 = (v255_coefficient+add_mtp) << BIT_SHIFT; +#else + result_1 = result_2 = (v255_coefficient+add_mtp + v255_val[2]) << BIT_SHIFT; +#endif do_div(result_2, v255_denominator); result_3 = (EA8868_VREG0_REF * result_2) >> BIT_SHIFT; result_4 = EA8868_VREG0_REF - result_3; @@ -152,7 +163,11 @@ static int v1_adjustment(struct SMART_DIM *pSmart) LSB = char_to_int(0); add_mtp = LSB + V1_300CD_R; - result_1 = result_2 = (v1_coefficient + add_mtp + color_mods[panelval][3]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_1 = result_2 = (v1_coefficient + add_mtp) << BIT_SHIFT; +#else + result_1 = result_2 = (v1_coefficient + add_mtp + v1_val[0]) << BIT_SHIFT; +#endif do_div(result_2, v1_denominator); result_3 = (EA8868_VREG0_REF * result_2) >> BIT_SHIFT; result_4 = EA8868_VREG0_REF - result_3; @@ -160,7 +175,11 @@ static int v1_adjustment(struct SMART_DIM *pSmart) LSB = char_to_int(0); add_mtp = LSB + V1_300CD_G; - result_1 = result_2 = (v1_coefficient+add_mtp + color_mods[panelval][4]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_1 = result_2 = (v1_coefficient+add_mtp) << BIT_SHIFT; +#else + result_1 = result_2 = (v1_coefficient+add_mtp + v1_val[1]) << BIT_SHIFT; +#endif do_div(result_2, v1_denominator); result_3 = (EA8868_VREG0_REF * result_2) >> BIT_SHIFT; result_4 = EA8868_VREG0_REF - result_3; @@ -168,7 +187,11 @@ static int v1_adjustment(struct SMART_DIM *pSmart) LSB = char_to_int(0); add_mtp = LSB + V1_300CD_B; - result_1 = result_2 = (v1_coefficient+add_mtp + color_mods[panelval][5]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_1 = result_2 = (v1_coefficient+add_mtp) << BIT_SHIFT; +#else + result_1 = result_2 = (v1_coefficient+add_mtp + v1_val[2]) << BIT_SHIFT; +#endif do_div(result_2, v1_denominator); result_3 = (EA8868_VREG0_REF * result_2) >> BIT_SHIFT; result_4 = EA8868_VREG0_REF - result_3; @@ -204,7 +227,11 @@ static int v171_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V171_300CD_R; result_1 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.R_VOLTAGE.level_255); - result_2 = (v171_coefficient + add_mtp + color_mods[panelval][6]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v171_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v171_coefficient + add_mtp + v171_val[0]) << BIT_SHIFT; +#endif do_div(result_2, v171_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - result_3; @@ -214,7 +241,11 @@ static int v171_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V171_300CD_G; result_1 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.G_VOLTAGE.level_255); - result_2 = (v171_coefficient + add_mtp + color_mods[panelval][7]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v171_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v171_coefficient + add_mtp + v171_val[1]) << BIT_SHIFT; +#endif do_div(result_2, v171_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - result_3; @@ -224,7 +255,11 @@ static int v171_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V171_300CD_B; result_1 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.B_VOLTAGE.level_255); - result_2 = (v171_coefficient+add_mtp + color_mods[panelval][8]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v171_coefficient+add_mtp) << BIT_SHIFT; +#else + result_2 = (v171_coefficient+add_mtp + v171_val[2]) << BIT_SHIFT; +#endif do_div(result_2, v171_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - result_3; @@ -283,7 +318,11 @@ static int v87_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V87_300CD_R; result_1 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.R_VOLTAGE.level_171); - result_2 = (v87_coefficient + add_mtp + color_mods[panelval][6]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v87_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v87_coefficient + add_mtp + v87_val[0]) << BIT_SHIFT; +#endif do_div(result_2, v87_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - result_3; @@ -293,7 +332,11 @@ static int v87_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V87_300CD_G; result_1 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.G_VOLTAGE.level_171); - result_2 = (v87_coefficient + add_mtp + color_mods[panelval][7]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v87_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v87_coefficient + add_mtp + v87_val[1]) << BIT_SHIFT; +#endif do_div(result_2, v87_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - result_3; @@ -303,7 +346,11 @@ static int v87_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V87_300CD_B; result_1 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.B_VOLTAGE.level_171); - result_2 = (v87_coefficient + add_mtp + color_mods[panelval][8]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v87_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v87_coefficient + add_mtp + v87_val[2]) << BIT_SHIFT; +#endif do_div(result_2, v87_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - result_3; @@ -361,7 +408,11 @@ static int v59_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V59_300CD_R; result_1 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.R_VOLTAGE.level_87); - result_2 = (v59_coefficient + add_mtp + color_mods[panelval][6]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v59_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v59_coefficient + add_mtp + v59_val[0]) << BIT_SHIFT; +#endif do_div(result_2, v59_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - result_3; @@ -371,7 +422,11 @@ static int v59_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V59_300CD_G; result_1 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.G_VOLTAGE.level_87); - result_2 = (v59_coefficient + add_mtp + color_mods[panelval][7]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v59_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v59_coefficient + add_mtp + v59_val[1]) << BIT_SHIFT; +#endif do_div(result_2, v59_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - result_3; @@ -381,7 +436,11 @@ static int v59_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V59_300CD_B; result_1 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.B_VOLTAGE.level_87); - result_2 = (v59_coefficient + add_mtp + color_mods[panelval][8]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v59_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v59_coefficient + add_mtp + v59_val[2]) << BIT_SHIFT; +#endif do_div(result_2, v59_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - result_3; @@ -441,7 +500,11 @@ static int v35_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V35_300CD_R; result_1 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.R_VOLTAGE.level_59); - result_2 = (v35_coefficient + add_mtp + color_mods[panelval][6]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v35_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v35_coefficient + add_mtp + v35_val[0]) << BIT_SHIFT; +#endif do_div(result_2, v35_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - result_3; @@ -451,7 +514,11 @@ static int v35_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V35_300CD_G; result_1 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.G_VOLTAGE.level_59); - result_2 = (v35_coefficient + add_mtp + color_mods[panelval][7]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v35_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v35_coefficient + add_mtp + v35_val[1]) << BIT_SHIFT; +#endif do_div(result_2, v35_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - result_3; @@ -461,7 +528,11 @@ static int v35_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V35_300CD_B; result_1 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.B_VOLTAGE.level_59); - result_2 = (v35_coefficient + add_mtp + color_mods[panelval][8]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v35_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v35_coefficient + add_mtp + v35_val[2]) << BIT_SHIFT; +#endif do_div(result_2, v35_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - result_3; @@ -520,7 +591,11 @@ static int v15_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V15_300CD_R; result_1 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.R_VOLTAGE.level_35); - result_2 = (v15_Coefficient+add_mtp + color_mods[panelval][6]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v15_Coefficient+add_mtp) << BIT_SHIFT; +#else + result_2 = (v15_Coefficient+add_mtp + v15_val[0]) << BIT_SHIFT; +#endif do_div(result_2, v15_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - result_3; @@ -530,7 +605,11 @@ static int v15_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V15_300CD_G; result_1 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.G_VOLTAGE.level_35); - result_2 = (v15_Coefficient + add_mtp + color_mods[panelval][7]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v15_Coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v15_Coefficient + add_mtp + v15_val[1]) << BIT_SHIFT; +#endif do_div(result_2, v15_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - result_3; @@ -540,7 +619,11 @@ static int v15_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V15_300CD_B; result_1 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.B_VOLTAGE.level_35); - result_2 = (v15_Coefficient + add_mtp + color_mods[panelval][8]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v15_Coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v15_Coefficient + add_mtp + v15_val[2]) << BIT_SHIFT; +#endif do_div(result_2, v15_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - result_3; diff --git a/drivers/video/msm/smart_mtp_s6e63m0.c b/drivers/video/msm/smart_mtp_s6e63m0.c index 16eb555eeedd..fe129e77972a 100644 --- a/drivers/video/msm/smart_mtp_s6e63m0.c +++ b/drivers/video/msm/smart_mtp_s6e63m0.c @@ -64,14 +64,6 @@ unsigned char V255_300CD_B; #endif /* #define SMART_DIMMING_DEBUG */ -static int color_mods[5][9] = { - { 0, 0, 5, -18, -16, -10, 0, 0, 3 }, - { 0, 0, 2, -9, -8, -5, 0, 0, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, -2, 9, 8, 5, 0, 0, -1 }, - { 0, 0, -5, 18, 16, 10, 0, 0, -3 } -}; -unsigned int panelval = 2; struct SMART_DIM *gpsmart; static int char_to_int(char data1) @@ -86,12 +78,16 @@ static int char_to_int(char data1) return cal_data; } -void panel_load_colors(unsigned int val) +extern int v255_val[3]; +extern int v1_val[3]; +extern int v171_val[3]; +extern int v87_val[3]; +extern int v43_val[3]; +extern int v19_val[3]; + +void panel_load_colors(void) { - if (val < 5) { - panelval = val; - smart_dimming_init(gpsmart); - } + smart_dimming_init(gpsmart); } #define V255_COEFF 120 @@ -104,7 +100,11 @@ static int v255_adjustment(struct SMART_DIM *pSmart) LSB = char_to_int(pSmart->MTP.R_OFFSET.OFFSET_255_LSB); add_mtp = LSB + V255_300CD_R; - result_1 = result_2 = (V255_COEFF+add_mtp + color_mods[panelval][0]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_1 = result_2 = (V255_COEFF+add_mtp) << BIT_SHIFT; +#else + result_1 = result_2 = (V255_COEFF+add_mtp + v255_val[0]) << BIT_SHIFT; +#endif do_div(result_2, V255_DENOMTR); result_3 = (S6E63M0_VREG0_REF * result_2) >> BIT_SHIFT; result_4 = S6E63M0_VREG0_REF - result_3; @@ -113,7 +113,11 @@ static int v255_adjustment(struct SMART_DIM *pSmart) LSB = char_to_int(pSmart->MTP.G_OFFSET.OFFSET_255_LSB); add_mtp = LSB + V255_300CD_G; - result_1 = result_2 = (V255_COEFF+add_mtp + color_mods[panelval][1]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_1 = result_2 = (V255_COEFF+add_mtp) << BIT_SHIFT; +#else + result_1 = result_2 = (V255_COEFF+add_mtp + v255_val[1]) << BIT_SHIFT; +#endif do_div(result_2, V255_DENOMTR); result_3 = (S6E63M0_VREG0_REF * result_2) >> BIT_SHIFT; result_4 = S6E63M0_VREG0_REF - result_3; @@ -122,7 +126,11 @@ static int v255_adjustment(struct SMART_DIM *pSmart) LSB = char_to_int(pSmart->MTP.B_OFFSET.OFFSET_255_LSB); add_mtp = LSB + V255_300CD_B; - result_1 = result_2 = (V255_COEFF+add_mtp + color_mods[panelval][2]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_1 = result_2 = (V255_COEFF+add_mtp) << BIT_SHIFT; +#else + result_1 = result_2 = (V255_COEFF+add_mtp + v255_val[2]) << BIT_SHIFT; +#endif do_div(result_2, V255_DENOMTR); result_3 = (S6E63M0_VREG0_REF * result_2) >> BIT_SHIFT; result_4 = S6E63M0_VREG0_REF - result_3; @@ -179,7 +187,11 @@ static int v1_adjustment(struct SMART_DIM *pSmart) LSB = char_to_int(pSmart->MTP.R_OFFSET.OFFSET_1); add_mtp = LSB + V1_300CD_R; - result_1 = result_2 = (V1_COEFF + add_mtp + color_mods[panelval][3]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_1 = result_2 = (V1_COEFF + add_mtp) << BIT_SHIFT; +#else + result_1 = result_2 = (V1_COEFF + add_mtp + v1_val[0]) << BIT_SHIFT; +#endif do_div(result_2, V1_DENOMTR); result_3 = (S6E63M0_VREG0_REF * result_2) >> BIT_SHIFT; result_4 = S6E63M0_VREG0_REF - result_3; @@ -187,7 +199,11 @@ static int v1_adjustment(struct SMART_DIM *pSmart) LSB = char_to_int(pSmart->MTP.G_OFFSET.OFFSET_1); add_mtp = LSB + V1_300CD_G; - result_1 = result_2 = (V1_COEFF+add_mtp + color_mods[panelval][4]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_1 = result_2 = (V1_COEFF+add_mtp) << BIT_SHIFT; +#else + result_1 = result_2 = (V1_COEFF+add_mtp + v1_val[1]) << BIT_SHIFT; +#endif do_div(result_2, V1_DENOMTR); result_3 = (S6E63M0_VREG0_REF * result_2) >> BIT_SHIFT; result_4 = S6E63M0_VREG0_REF - result_3; @@ -195,7 +211,11 @@ static int v1_adjustment(struct SMART_DIM *pSmart) LSB = char_to_int(pSmart->MTP.B_OFFSET.OFFSET_1); add_mtp = LSB + V1_300CD_B; - result_1 = result_2 = (V1_COEFF+add_mtp + color_mods[panelval][5]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_1 = result_2 = (V1_COEFF+add_mtp) << BIT_SHIFT; +#else + result_1 = result_2 = (V1_COEFF+add_mtp + v1_val[2]) << BIT_SHIFT; +#endif do_div(result_2, V1_DENOMTR); result_3 = (S6E63M0_VREG0_REF * result_2) >> BIT_SHIFT; result_4 = S6E63M0_VREG0_REF - result_3; @@ -232,7 +252,11 @@ static int v171_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V171_300CD_R; result_1 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.R_VOLTAGE.level_255); - result_2 = (V171_COEFF + add_mtp + color_mods[panelval][6]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (V171_COEFF + add_mtp) << BIT_SHIFT; +#else + result_2 = (V171_COEFF + add_mtp + v171_val[0]) << BIT_SHIFT; +#endif do_div(result_2, V171_DENOMTR); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - result_3; @@ -242,7 +266,11 @@ static int v171_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V171_300CD_G; result_1 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.G_VOLTAGE.level_255); - result_2 = (V171_COEFF + add_mtp + color_mods[panelval][7]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (V171_COEFF + add_mtp) << BIT_SHIFT; +#else + result_2 = (V171_COEFF + add_mtp + v171_val[1]) << BIT_SHIFT; +#endif do_div(result_2, V171_DENOMTR); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - result_3; @@ -252,7 +280,11 @@ static int v171_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V171_300CD_B; result_1 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.B_VOLTAGE.level_255); - result_2 = (V171_COEFF+add_mtp + color_mods[panelval][8]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (V171_COEFF+add_mtp) << BIT_SHIFT; +#else + result_2 = (V171_COEFF+add_mtp + v171_val[2]) << BIT_SHIFT; +#endif do_div(result_2, V171_DENOMTR); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - result_3; @@ -312,7 +344,11 @@ static int v87_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V87_300CD_R; result_1 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.R_VOLTAGE.level_171); - result_2 = (V87_COEFF + add_mtp + color_mods[panelval][6]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (V87_COEFF + add_mtp) << BIT_SHIFT; +#else + result_2 = (V87_COEFF + add_mtp + v87_val[0]) << BIT_SHIFT; +#endif do_div(result_2, V87_DENOMTR); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - result_3; @@ -322,7 +358,11 @@ static int v87_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V87_300CD_G; result_1 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.G_VOLTAGE.level_171); - result_2 = (V87_COEFF + add_mtp + color_mods[panelval][7]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (V87_COEFF + add_mtp) << BIT_SHIFT; +#else + result_2 = (V87_COEFF + add_mtp + v87_val[1]) << BIT_SHIFT; +#endif do_div(result_2, V87_DENOMTR); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - result_3; @@ -332,7 +372,11 @@ static int v87_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V87_300CD_B; result_1 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.B_VOLTAGE.level_171); - result_2 = (V87_COEFF + add_mtp + color_mods[panelval][8]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (V87_COEFF + add_mtp) << BIT_SHIFT; +#else + result_2 = (V87_COEFF + add_mtp + v87_val[2]) << BIT_SHIFT; +#endif do_div(result_2, V87_DENOMTR); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - result_3; @@ -390,7 +434,11 @@ static int v43_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V43_300CD_R; result_1 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.R_VOLTAGE.level_87); - result_2 = (V43_COEFF + add_mtp + color_mods[panelval][6]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (V43_COEFF + add_mtp) << BIT_SHIFT; +#else + result_2 = (V43_COEFF + add_mtp + v43_val[0]) << BIT_SHIFT; +#endif do_div(result_2, V43_DENOMTR); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - result_3; @@ -400,7 +448,11 @@ static int v43_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V43_300CD_G; result_1 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.G_VOLTAGE.level_87); - result_2 = (V43_COEFF + add_mtp + color_mods[panelval][7]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (V43_COEFF + add_mtp) << BIT_SHIFT; +#else + result_2 = (V43_COEFF + add_mtp + v43_val[1]) << BIT_SHIFT; +#endif do_div(result_2, V43_DENOMTR); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - result_3; @@ -410,7 +462,11 @@ static int v43_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V43_300CD_B; result_1 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.B_VOLTAGE.level_87); - result_2 = (V43_COEFF + add_mtp + color_mods[panelval][8]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (V43_COEFF + add_mtp) << BIT_SHIFT; +#else + result_2 = (V43_COEFF + add_mtp + v43_val[2]) << BIT_SHIFT; +#endif do_div(result_2, V43_DENOMTR); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - result_3; @@ -471,7 +527,11 @@ static int v19_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V19_300CD_R; result_1 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.R_VOLTAGE.level_43); - result_2 = (V19_COEFF+add_mtp + color_mods[panelval][6]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (V19_COEFF+add_mtp) << BIT_SHIFT; +#else + result_2 = (V19_COEFF+add_mtp + v19_val[0]) << BIT_SHIFT; +#endif do_div(result_2, V19_DENOMTR); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - result_3; @@ -481,7 +541,11 @@ static int v19_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V19_300CD_G; result_1 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.G_VOLTAGE.level_43); - result_2 = (V19_COEFF + add_mtp + color_mods[panelval][7]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (V19_COEFF + add_mtp) << BIT_SHIFT; +#else + result_2 = (V19_COEFF + add_mtp + v19_val[1]) << BIT_SHIFT; +#endif do_div(result_2, V19_DENOMTR); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - result_3; @@ -491,7 +555,11 @@ static int v19_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V19_300CD_B; result_1 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.B_VOLTAGE.level_43); - result_2 = (V19_COEFF + add_mtp + color_mods[panelval][8]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (V19_COEFF + add_mtp) << BIT_SHIFT; +#else + result_2 = (V19_COEFF + add_mtp + v19_val[2]) << BIT_SHIFT; +#endif do_div(result_2, V19_DENOMTR); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - result_3; diff --git a/drivers/video/msm/smart_mtp_s6e8aa0x01.c b/drivers/video/msm/smart_mtp_s6e8aa0x01.c index 4c1503d2c9c2..68499e7ac2db 100644 --- a/drivers/video/msm/smart_mtp_s6e8aa0x01.c +++ b/drivers/video/msm/smart_mtp_s6e8aa0x01.c @@ -76,14 +76,7 @@ static char V255_300CD_G_LSB; static char V255_300CD_B_MSB; static char V255_300CD_B_LSB; -int color_mods[5][21] = { - { 0, 0, 5, -18, -16, -10, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0, 3 }, - { 0, 0, 2, -9, -8, -5, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, -2, 9, 8, 5, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1 }, - { 0, 0, -5, 18, 16, 10, 0, 0, -3, 0, 0, -3, 0, 0, -3, 0, 0, -3, 0, 0, -3 } -}; -unsigned int panelval = 2; + struct SMART_DIM *gpsmart; static int char_to_int(char data1) @@ -98,9 +91,16 @@ static int char_to_int(char data1) return cal_data; } -void panel_load_colors(unsigned int val) +extern int v255_val[3]; +extern int v1_val[3]; +extern int v171_val[3]; +extern int v87_val[3]; +extern int v59_val[3]; +extern int v35_val[3]; +extern int v15_val[3]; + +void panel_load_colors(void) { - panelval = val; smart_dimming_init(gpsmart); } #define v255_coefficient 100 @@ -115,7 +115,11 @@ static int v255_adjustment(struct SMART_DIM *pSmart) v255_value = (V255_300CD_R_MSB << 8) | (V255_300CD_R_LSB); LSB = char_to_int(pSmart->MTP.R_OFFSET.OFFSET_255_LSB); add_mtp = LSB + v255_value; - result_1 = result_2 = (v255_coefficient+add_mtp + color_mods[panelval][0]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_1 = result_2 = (v255_coefficient+add_mtp) << BIT_SHIFT; +#else + result_1 = result_2 = (v255_coefficient+add_mtp + v255_val[0]) << BIT_SHIFT; +#endif do_div(result_2, v255_denominator); result_3 = (S6E8AA0X01_VREG0_REF * result_2) >> BIT_SHIFT; result_4 = S6E8AA0X01_VREG0_REF - result_3; @@ -125,7 +129,11 @@ static int v255_adjustment(struct SMART_DIM *pSmart) v255_value = (V255_300CD_G_MSB << 8) | (V255_300CD_G_LSB); LSB = char_to_int(pSmart->MTP.G_OFFSET.OFFSET_255_LSB); add_mtp = LSB + v255_value; - result_1 = result_2 = (v255_coefficient+add_mtp + color_mods[panelval][1]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_1 = result_2 = (v255_coefficient+add_mtp) << BIT_SHIFT; +#else + result_1 = result_2 = (v255_coefficient+add_mtp + v255_val[1]) << BIT_SHIFT; +#endif do_div(result_2, v255_denominator); result_3 = (S6E8AA0X01_VREG0_REF * result_2) >> BIT_SHIFT; result_4 = S6E8AA0X01_VREG0_REF - result_3; @@ -135,7 +143,11 @@ static int v255_adjustment(struct SMART_DIM *pSmart) v255_value = (V255_300CD_B_MSB << 8) | (V255_300CD_B_LSB); LSB = char_to_int(pSmart->MTP.B_OFFSET.OFFSET_255_LSB); add_mtp = LSB + v255_value; - result_1 = result_2 = (v255_coefficient+add_mtp + color_mods[panelval][2]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_1 = result_2 = (v255_coefficient+add_mtp) << BIT_SHIFT; +#else + result_1 = result_2 = (v255_coefficient+add_mtp + v255_val[2]) << BIT_SHIFT; +#endif do_div(result_2, v255_denominator); result_3 = (S6E8AA0X01_VREG0_REF * result_2) >> BIT_SHIFT; result_4 = S6E8AA0X01_VREG0_REF - result_3; @@ -193,7 +205,11 @@ static int v1_adjustment(struct SMART_DIM *pSmart) LSB = char_to_int(pSmart->MTP.R_OFFSET.OFFSET_1); add_mtp = LSB + V1_300CD_R; - result_1 = result_2 = (v1_coefficient + add_mtp + color_mods[panelval][3]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_1 = result_2 = (v1_coefficient + add_mtp) << BIT_SHIFT; +#else + result_1 = result_2 = (v1_coefficient + add_mtp + v1_val[0]) << BIT_SHIFT; +#endif do_div(result_2, v1_denominator); result_3 = (S6E8AA0X01_VREG0_REF * result_2) >> BIT_SHIFT; result_4 = S6E8AA0X01_VREG0_REF - result_3; @@ -201,7 +217,11 @@ static int v1_adjustment(struct SMART_DIM *pSmart) LSB = char_to_int(pSmart->MTP.G_OFFSET.OFFSET_1); add_mtp = LSB + V1_300CD_G; - result_1 = result_2 = (v1_coefficient+add_mtp + color_mods[panelval][4]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_1 = result_2 = (v1_coefficient+add_mtp) << BIT_SHIFT; +#else + result_1 = result_2 = (v1_coefficient+add_mtp + v1_val[1]) << BIT_SHIFT; +#endif do_div(result_2, v1_denominator); result_3 = (S6E8AA0X01_VREG0_REF * result_2) >> BIT_SHIFT; result_4 = S6E8AA0X01_VREG0_REF - result_3; @@ -209,7 +229,11 @@ static int v1_adjustment(struct SMART_DIM *pSmart) LSB = char_to_int(pSmart->MTP.B_OFFSET.OFFSET_1); add_mtp = LSB + V1_300CD_B; - result_1 = result_2 = (v1_coefficient+add_mtp + color_mods[panelval][5]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_1 = result_2 = (v1_coefficient+add_mtp) << BIT_SHIFT; +#else + result_1 = result_2 = (v1_coefficient+add_mtp + v1_val[2]) << BIT_SHIFT; +#endif do_div(result_2, v1_denominator); result_3 = (S6E8AA0X01_VREG0_REF * result_2) >> BIT_SHIFT; result_4 = S6E8AA0X01_VREG0_REF - result_3; @@ -246,7 +270,11 @@ static int v171_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V171_300CD_R; result_1 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.R_VOLTAGE.level_255); - result_2 = (v171_coefficient + add_mtp + color_mods[panelval][6]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v171_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v171_coefficient + add_mtp + v171_val[0]) << BIT_SHIFT; +#endif do_div(result_2, v171_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - result_3; @@ -256,7 +284,11 @@ static int v171_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V171_300CD_G; result_1 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.G_VOLTAGE.level_255); - result_2 = (v171_coefficient + add_mtp + color_mods[panelval][7]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v171_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v171_coefficient + add_mtp + v171_val[1]) << BIT_SHIFT; +#endif do_div(result_2, v171_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - result_3; @@ -266,7 +298,11 @@ static int v171_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V171_300CD_B; result_1 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.B_VOLTAGE.level_255); - result_2 = (v171_coefficient+add_mtp + color_mods[panelval][8]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v171_coefficient+add_mtp) << BIT_SHIFT; +#else + result_2 = (v171_coefficient+add_mtp + v171_val[2]) << BIT_SHIFT; +#endif do_div(result_2, v171_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - result_3; @@ -326,7 +362,11 @@ static int v87_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V87_300CD_R; result_1 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.R_VOLTAGE.level_171); - result_2 = (v87_coefficient + add_mtp + color_mods[panelval][9]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v87_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v87_coefficient + add_mtp + v87_val[0]) << BIT_SHIFT; +#endif do_div(result_2, v87_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - result_3; @@ -336,7 +376,11 @@ static int v87_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V87_300CD_G; result_1 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.G_VOLTAGE.level_171); - result_2 = (v87_coefficient + add_mtp + color_mods[panelval][10]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v87_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v87_coefficient + add_mtp + v87_val[1]) << BIT_SHIFT; +#endif do_div(result_2, v87_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - result_3; @@ -346,7 +390,11 @@ static int v87_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V87_300CD_B; result_1 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.B_VOLTAGE.level_171); - result_2 = (v87_coefficient + add_mtp + color_mods[panelval][11]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v87_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v87_coefficient + add_mtp + v87_val[2]) << BIT_SHIFT; +#endif do_div(result_2, v87_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - result_3; @@ -405,7 +453,11 @@ static int v59_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V59_300CD_R; result_1 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.R_VOLTAGE.level_87); - result_2 = (v59_coefficient + add_mtp + color_mods[panelval][12]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v59_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v59_coefficient + add_mtp + v59_val[0]) << BIT_SHIFT; +#endif do_div(result_2, v59_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - result_3; @@ -415,7 +467,11 @@ static int v59_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V59_300CD_G; result_1 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.G_VOLTAGE.level_87); - result_2 = (v59_coefficient + add_mtp + color_mods[panelval][13]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v59_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v59_coefficient + add_mtp + v59_val[1]) << BIT_SHIFT; +#endif do_div(result_2, v59_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - result_3; @@ -425,7 +481,11 @@ static int v59_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V59_300CD_B; result_1 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.B_VOLTAGE.level_87); - result_2 = (v59_coefficient + add_mtp + color_mods[panelval][14]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v59_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v59_coefficient + add_mtp + v59_val[2]) << BIT_SHIFT; +#endif do_div(result_2, v59_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - result_3; @@ -486,7 +546,11 @@ static int v35_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V35_300CD_R; result_1 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.R_VOLTAGE.level_59); - result_2 = (v35_coefficient + add_mtp + color_mods[panelval][15]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v35_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v35_coefficient + add_mtp + v35_val[0]) << BIT_SHIFT; +#endif do_div(result_2, v35_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - result_3; @@ -496,7 +560,11 @@ static int v35_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V35_300CD_G; result_1 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.G_VOLTAGE.level_59); - result_2 = (v35_coefficient + add_mtp + color_mods[panelval][16]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v35_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v35_coefficient + add_mtp + v35_val[1]) << BIT_SHIFT; +#endif do_div(result_2, v35_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - result_3; @@ -506,7 +574,11 @@ static int v35_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V35_300CD_B; result_1 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.B_VOLTAGE.level_59); - result_2 = (v35_coefficient + add_mtp + color_mods[panelval][17]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v35_coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v35_coefficient + add_mtp + v35_val[2]) << BIT_SHIFT; +#endif do_div(result_2, v35_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - result_3; @@ -565,7 +637,11 @@ static int v15_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V15_300CD_R; result_1 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.R_VOLTAGE.level_35); - result_2 = (v15_Coefficient+add_mtp + color_mods[panelval][18]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v15_Coefficient+add_mtp) << BIT_SHIFT; +#else + result_2 = (v15_Coefficient+add_mtp + v15_val[0]) << BIT_SHIFT; +#endif do_div(result_2, v15_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.R_VOLTAGE.level_1) - result_3; @@ -575,7 +651,11 @@ static int v15_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V15_300CD_G; result_1 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.G_VOLTAGE.level_35); - result_2 = (v15_Coefficient + add_mtp + color_mods[panelval][19]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v15_Coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v15_Coefficient + add_mtp + v15_val[1]) << BIT_SHIFT; +#endif do_div(result_2, v15_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.G_VOLTAGE.level_1) - result_3; @@ -585,7 +665,11 @@ static int v15_adjustment(struct SMART_DIM *pSmart) add_mtp = LSB + V15_300CD_B; result_1 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - (pSmart->RGB_OUTPUT.B_VOLTAGE.level_35); - result_2 = (v15_Coefficient + add_mtp + color_mods[panelval][20]) << BIT_SHIFT; +#ifndef CONFIG_GAMMA_CONTROL + result_2 = (v15_Coefficient + add_mtp) << BIT_SHIFT; +#else + result_2 = (v15_Coefficient + add_mtp + v15_val[2]) << BIT_SHIFT; +#endif do_div(result_2, v15_denominator); result_3 = (result_1 * result_2) >> BIT_SHIFT; result_4 = (pSmart->RGB_OUTPUT.B_VOLTAGE.level_1) - result_3; diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index bcec06750232..9a6b24a73aae 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -1033,7 +1033,7 @@ static int __get_extent_inline_ref(unsigned long *ptr, struct extent_buffer *eb, *out_eiref = (struct btrfs_extent_inline_ref *)(ei + 1); } *ptr = (unsigned long)*out_eiref; - if ((void *)*ptr >= (void *)ei + item_size) + if ((unsigned long)(*ptr) >= (unsigned long)ei + item_size) return -ENOENT; } diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index d64fda541483..24b58c7f01ef 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -1551,6 +1551,7 @@ static noinline u64 find_lock_delalloc_range(struct inode *inode, * shortening the size of the delalloc range we're searching */ free_extent_state(cached_state); + cached_state = NULL; if (!loops) { unsigned long offset = (*start) & (PAGE_CACHE_SIZE - 1); max_bytes = PAGE_CACHE_SIZE - offset; @@ -2244,7 +2245,7 @@ int end_extent_writepage(struct page *page, int err, u64 start, u64 end) { int uptodate = (err == 0); struct extent_io_tree *tree; - int ret; + int ret = 0; tree = &BTRFS_I(page->mapping->host)->io_tree; diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 06744f1e91f4..d5dc63c6bb75 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1446,11 +1446,12 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) struct btrfs_fs_devices *fs_devices; fs_devices = root->fs_info->fs_devices; while (fs_devices) { - if (fs_devices->seed == cur_devices) + if (fs_devices->seed == cur_devices) { + fs_devices->seed = cur_devices->seed; break; + } fs_devices = fs_devices->seed; } - fs_devices->seed = cur_devices->seed; cur_devices->seed = NULL; lock_chunks(root); __btrfs_close_devices(cur_devices); diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 2941ee6ef24f..cdfc763b313f 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -3015,7 +3015,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, } BUG_ON(start + size <= ac->ac_o_ex.fe_logical && start > ac->ac_o_ex.fe_logical); - BUG_ON(size <= 0 || size > EXT4_CLUSTERS_PER_GROUP(ac->ac_sb)); + BUG_ON(size <= 0 || size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); /* now prepare goal request */ diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index 4d22be25b48f..9e6e97015f42 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h @@ -27,6 +27,8 @@ struct module; * @irq_count: stats field to detect stalled irqs * @last_unhandled: aging timer for unhandled count * @irqs_unhandled: stats field for spurious unhandled interrupts + * @threads_handled: stats field for deferred spurious detection of threaded handlers + * @threads_handled_last: comparator field for deferred spurious detection of theraded handlers * @lock: locking for SMP * @affinity_hint: hint to user space for preferred irq affinity * @affinity_notify: context for notification of affinity changes @@ -52,6 +54,8 @@ struct irq_desc { unsigned int irq_count; /* For detecting broken IRQs */ unsigned long last_unhandled; /* Aging timer for unhandled count */ unsigned int irqs_unhandled; + atomic_t threads_handled; + int threads_handled_last; raw_spinlock_t lock; struct cpumask *percpu_enabled; #ifdef CONFIG_SMP diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 0884db3d315e..e22df7a4f1ab 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1673,6 +1673,22 @@ static inline void skb_orphan(struct sk_buff *skb) skb->sk = NULL; } +/** + * skb_orphan_frags - orphan the frags contained in a buffer + * @skb: buffer to orphan frags from + * @gfp_mask: allocation mask for replacement pages + * + * For each frag in the SKB which needs a destructor (i.e. has an + * owner) create a copy of that frag and release the original + * page by calling the destructor. + */ +static inline int skb_orphan_frags(struct sk_buff *skb, gfp_t gfp_mask) +{ + if (likely(!(skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY))) + return 0; + return skb_copy_ubufs(skb, gfp_mask); +} + /** * __skb_queue_purge - empty a list * @list: list to empty diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 7c5ba68c2ae3..790c0755cd23 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -835,8 +835,8 @@ static int irq_thread(void *data) irq_thread_check_affinity(desc, action); action_ret = handler_fn(desc, action); - if (!noirqdebug) - note_interrupt(action->irq, desc, action_ret); + if (action_ret == IRQ_HANDLED) + atomic_inc(&desc->threads_handled); wake_threads_waitq(desc); } diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index 7b5f012bde9d..febcee3c2aa9 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -265,21 +265,119 @@ try_misrouted_irq(unsigned int irq, struct irq_desc *desc, return action && (action->flags & IRQF_IRQPOLL); } +#define SPURIOUS_DEFERRED 0x80000000 + void note_interrupt(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret) { if (desc->istate & IRQS_POLL_INPROGRESS) return; - /* we get here again via the threaded handler */ - if (action_ret == IRQ_WAKE_THREAD) - return; - if (bad_action_ret(action_ret)) { report_bad_irq(irq, desc, action_ret); return; } + /* + * We cannot call note_interrupt from the threaded handler + * because we need to look at the compound of all handlers + * (primary and threaded). Aside of that in the threaded + * shared case we have no serialization against an incoming + * hardware interrupt while we are dealing with a threaded + * result. + * + * So in case a thread is woken, we just note the fact and + * defer the analysis to the next hardware interrupt. + * + * The threaded handlers store whether they sucessfully + * handled an interrupt and we check whether that number + * changed versus the last invocation. + * + * We could handle all interrupts with the delayed by one + * mechanism, but for the non forced threaded case we'd just + * add pointless overhead to the straight hardirq interrupts + * for the sake of a few lines less code. + */ + if (action_ret & IRQ_WAKE_THREAD) { + /* + * There is a thread woken. Check whether one of the + * shared primary handlers returned IRQ_HANDLED. If + * not we defer the spurious detection to the next + * interrupt. + */ + if (action_ret == IRQ_WAKE_THREAD) { + int handled; + /* + * We use bit 31 of thread_handled_last to + * denote the deferred spurious detection + * active. No locking necessary as + * thread_handled_last is only accessed here + * and we have the guarantee that hard + * interrupts are not reentrant. + */ + if (!(desc->threads_handled_last & SPURIOUS_DEFERRED)) { + desc->threads_handled_last |= SPURIOUS_DEFERRED; + return; + } + /* + * Check whether one of the threaded handlers + * returned IRQ_HANDLED since the last + * interrupt happened. + * + * For simplicity we just set bit 31, as it is + * set in threads_handled_last as well. So we + * avoid extra masking. And we really do not + * care about the high bits of the handled + * count. We just care about the count being + * different than the one we saw before. + */ + handled = atomic_read(&desc->threads_handled); + handled |= SPURIOUS_DEFERRED; + if (handled != desc->threads_handled_last) { + action_ret = IRQ_HANDLED; + /* + * Note: We keep the SPURIOUS_DEFERRED + * bit set. We are handling the + * previous invocation right now. + * Keep it for the current one, so the + * next hardware interrupt will + * account for it. + */ + desc->threads_handled_last = handled; + } else { + /* + * None of the threaded handlers felt + * responsible for the last interrupt + * + * We keep the SPURIOUS_DEFERRED bit + * set in threads_handled_last as we + * need to account for the current + * interrupt as well. + */ + action_ret = IRQ_NONE; + } + } else { + /* + * One of the primary handlers returned + * IRQ_HANDLED. So we don't care about the + * threaded handlers on the same line. Clear + * the deferred detection bit. + * + * In theory we could/should check whether the + * deferred bit is set and take the result of + * the previous run into account here as + * well. But it's really not worth the + * trouble. If every other interrupt is + * handled we never trigger the spurious + * detector. And if this is just the one out + * of 100k unhandled ones which is handled + * then we merily delay the spurious detection + * by one hard interrupt. Not a real problem. + */ + desc->threads_handled_last &= ~SPURIOUS_DEFERRED; + } + } + if (unlikely(action_ret == IRQ_NONE)) { /* * If we are seeing only the odd spurious IRQ caused by diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 7b376f63f8fd..7205016b7ba7 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -208,9 +208,9 @@ static int kill_proc(struct task_struct *t, unsigned long addr, int trapno, #endif si.si_addr_lsb = compound_trans_order(compound_head(page)) + PAGE_SHIFT; - if ((flags & MF_ACTION_REQUIRED) && t == current) { + if ((flags & MF_ACTION_REQUIRED) && t->mm == current->mm) { si.si_code = BUS_MCEERR_AR; - ret = force_sig_info(SIGBUS, &si, t); + ret = force_sig_info(SIGBUS, &si, current); } else { /* * Don't use force here, it's convenient if the signal @@ -382,10 +382,12 @@ static void kill_procs(struct list_head *to_kill, int forcekill, int trapno, } } -static int task_early_kill(struct task_struct *tsk) +static int task_early_kill(struct task_struct *tsk, int force_early) { if (!tsk->mm) return 0; + if (force_early) + return 1; if (tsk->flags & PF_MCE_PROCESS) return !!(tsk->flags & PF_MCE_EARLY); return sysctl_memory_failure_early_kill; @@ -395,7 +397,7 @@ static int task_early_kill(struct task_struct *tsk) * Collect processes when the error hit an anonymous page. */ static void collect_procs_anon(struct page *page, struct list_head *to_kill, - struct to_kill **tkc) + struct to_kill **tkc, int force_early) { struct vm_area_struct *vma; struct task_struct *tsk; @@ -409,7 +411,7 @@ static void collect_procs_anon(struct page *page, struct list_head *to_kill, for_each_process (tsk) { struct anon_vma_chain *vmac; - if (!task_early_kill(tsk)) + if (!task_early_kill(tsk, force_early)) continue; list_for_each_entry(vmac, &av->head, same_anon_vma) { vma = vmac->vma; @@ -427,7 +429,7 @@ static void collect_procs_anon(struct page *page, struct list_head *to_kill, * Collect processes when the error hit a file mapped page. */ static void collect_procs_file(struct page *page, struct list_head *to_kill, - struct to_kill **tkc) + struct to_kill **tkc, int force_early) { struct vm_area_struct *vma; struct task_struct *tsk; @@ -439,7 +441,7 @@ static void collect_procs_file(struct page *page, struct list_head *to_kill, for_each_process(tsk) { pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); - if (!task_early_kill(tsk)) + if (!task_early_kill(tsk, force_early)) continue; vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, @@ -465,7 +467,8 @@ static void collect_procs_file(struct page *page, struct list_head *to_kill, * First preallocate one tokill structure outside the spin locks, * so that we can kill at least one process reasonably reliable. */ -static void collect_procs(struct page *page, struct list_head *tokill) +static void collect_procs(struct page *page, struct list_head *tokill, + int force_early) { struct to_kill *tk; @@ -476,9 +479,9 @@ static void collect_procs(struct page *page, struct list_head *tokill) if (!tk) return; if (PageAnon(page)) - collect_procs_anon(page, tokill, &tk); + collect_procs_anon(page, tokill, &tk, force_early); else - collect_procs_file(page, tokill, &tk); + collect_procs_file(page, tokill, &tk, force_early); kfree(tk); } @@ -948,7 +951,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, * there's nothing that can be done. */ if (kill) - collect_procs(ppage, &tokill); + collect_procs(ppage, &tokill, flags & MF_ACTION_REQUIRED); if (hpage != ppage) lock_page(ppage); diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 46cb63b956fb..d9a5ae3d2a68 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -675,7 +675,7 @@ static int mbind_range(struct mm_struct *mm, unsigned long start, ((vmstart - vma->vm_start) >> PAGE_SHIFT); prev = vma_merge(mm, prev, vmstart, vmend, vma->vm_flags, vma->anon_vma, vma->vm_file, pgoff, - new_pol, vma_get_anon_name(name)); + new_pol, vma_get_anon_name(vma)); if (prev) { vma = prev; next = vma->vm_next; diff --git a/mm/rmap.c b/mm/rmap.c index 2b03b317ee21..f6c1194ee845 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -103,6 +103,7 @@ static inline void anon_vma_free(struct anon_vma *anon_vma) * LOCK should suffice since the actual taking of the lock must * happen _before_ what follows. */ + might_sleep(); if (mutex_is_locked(&anon_vma->root->mutex)) { anon_vma_lock(anon_vma); anon_vma_unlock(anon_vma); @@ -476,8 +477,9 @@ struct anon_vma *page_get_anon_vma(struct page *page) * above cannot corrupt). */ if (!page_mapped(page)) { + rcu_read_unlock(); put_anon_vma(anon_vma); - anon_vma = NULL; + return NULL; } out: rcu_read_unlock(); @@ -527,9 +529,9 @@ struct anon_vma *page_lock_anon_vma(struct page *page) } if (!page_mapped(page)) { + rcu_read_unlock(); put_anon_vma(anon_vma); - anon_vma = NULL; - goto out; + return NULL; } /* we pinned the anon_vma, its safe to sleep */ diff --git a/mm/vmscan.c b/mm/vmscan.c index 716ff6c5caee..81c1030670a6 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -3165,7 +3165,10 @@ static int kswapd(void *p) } } + tsk->flags &= ~(PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD); current->reclaim_state = NULL; + lockdep_clear_current_reclaim_state(); + return 0; } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index fe42834df408..8de819475378 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -733,7 +733,7 @@ int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask) skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY; return 0; } - +EXPORT_SYMBOL_GPL(skb_copy_ubufs); /** * skb_clone - duplicate an sk_buff @@ -2777,6 +2777,9 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) skb_put(nskb, hsize), hsize); while (pos < offset + len && i < nfrags) { + if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC))) + goto err; + *frag = skb_shinfo(skb)->frags[i]; __skb_frag_ref(frag); size = skb_frag_size(frag);