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/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c index 14ac52c5ae86..884de3433ad7 100644 --- a/arch/mips/kernel/irq-msc01.c +++ b/arch/mips/kernel/irq-msc01.c @@ -131,7 +131,7 @@ void __init init_msc_irqs(unsigned long icubase, unsigned int irqbase, msc_irqma board_bind_eic_interrupt = &msc_bind_eic_interrupt; - for (; nirq >= 0; nirq--, imp++) { + for (; nirq > 0; nirq--, imp++) { int n = imp->im_irq; switch (imp->im_type) { diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index e7dba0b2a170..eb6b72faec0d 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -496,7 +496,7 @@ void timer_interrupt(struct pt_regs * regs) __get_cpu_var(irq_stat).timer_irqs++; -#if defined(CONFIG_PPC32) && defined(CONFIG_PMAC) +#if defined(CONFIG_PPC32) && defined(CONFIG_PPC_PMAC) if (atomic_read(&ppc_n_lost_interrupts) != 0) do_IRQ(regs); #endif diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 9a52349874ee..e3b28e34bd78 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -1395,7 +1395,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) regs->gpr[rd] = byterev_4(val); goto ldst_done; -#ifdef CONFIG_PPC_CPU +#ifdef CONFIG_PPC_FPU case 535: /* lfsx */ case 567: /* lfsux */ if (!(regs->msr & MSR_FP)) diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index 8a811d98a795..9c9e24512f28 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c @@ -319,6 +319,7 @@ static int pseries_eeh_get_state(struct device_node *dn, int *state) } else { result = EEH_STATE_NOT_SUPPORT; } + break; default: result = EEH_STATE_NOT_SUPPORT; } 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/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index 19f16ebaf4fa..0b60cd9dcf16 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h @@ -286,6 +286,22 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, #define ARCH_HAS_USER_SINGLE_STEP_INFO +/* + * When hitting ptrace_stop(), we cannot return using SYSRET because + * that does not restore the full CPU state, only a minimal set. The + * ptracer can change arbitrary register values, which is usually okay + * because the usual ptrace stops run off the signal delivery path which + * forces IRET; however, ptrace_event() stops happen in arbitrary places + * in the kernel and don't force IRET path. + * + * So force IRET path after a ptrace stop. + */ +#define arch_ptrace_stop_needed(code, info) \ +({ \ + set_thread_flag(TIF_NOTIFY_RESUME); \ + false; \ +}) + struct user_desc; extern int do_get_thread_area(struct task_struct *p, int idx, struct user_desc __user *info); 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/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index f0d588f8859e..1acb99100556 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -98,7 +98,7 @@ struct ib_umad_port { struct ib_umad_device { int start_port, end_port; - struct kref ref; + struct kobject kobj; struct ib_umad_port port[0]; }; @@ -134,14 +134,18 @@ static DECLARE_BITMAP(dev_map, IB_UMAD_MAX_PORTS); static void ib_umad_add_one(struct ib_device *device); static void ib_umad_remove_one(struct ib_device *device); -static void ib_umad_release_dev(struct kref *ref) +static void ib_umad_release_dev(struct kobject *kobj) { struct ib_umad_device *dev = - container_of(ref, struct ib_umad_device, ref); + container_of(kobj, struct ib_umad_device, kobj); kfree(dev); } +static struct kobj_type ib_umad_dev_ktype = { + .release = ib_umad_release_dev, +}; + static int hdr_size(struct ib_umad_file *file) { return file->use_pkey_index ? sizeof (struct ib_user_mad_hdr) : @@ -780,27 +784,19 @@ static int ib_umad_open(struct inode *inode, struct file *filp) { struct ib_umad_port *port; struct ib_umad_file *file; - int ret; + int ret = -ENXIO; port = container_of(inode->i_cdev, struct ib_umad_port, cdev); - if (port) - kref_get(&port->umad_dev->ref); - else - return -ENXIO; mutex_lock(&port->file_mutex); - if (!port->ib_dev) { - ret = -ENXIO; + if (!port->ib_dev) goto out; - } + ret = -ENOMEM; file = kzalloc(sizeof *file, GFP_KERNEL); - if (!file) { - kref_put(&port->umad_dev->ref, ib_umad_release_dev); - ret = -ENOMEM; + if (!file) goto out; - } mutex_init(&file->mutex); spin_lock_init(&file->send_lock); @@ -814,6 +810,13 @@ static int ib_umad_open(struct inode *inode, struct file *filp) list_add_tail(&file->port_list, &port->file_list); ret = nonseekable_open(inode, filp); + if (ret) { + list_del(&file->port_list); + kfree(file); + goto out; + } + + kobject_get(&port->umad_dev->kobj); out: mutex_unlock(&port->file_mutex); @@ -852,7 +855,7 @@ static int ib_umad_close(struct inode *inode, struct file *filp) mutex_unlock(&file->port->file_mutex); kfree(file); - kref_put(&dev->ref, ib_umad_release_dev); + kobject_put(&dev->kobj); return 0; } @@ -880,10 +883,6 @@ static int ib_umad_sm_open(struct inode *inode, struct file *filp) int ret; port = container_of(inode->i_cdev, struct ib_umad_port, sm_cdev); - if (port) - kref_get(&port->umad_dev->ref); - else - return -ENXIO; if (filp->f_flags & O_NONBLOCK) { if (down_trylock(&port->sm_sem)) { @@ -898,17 +897,27 @@ static int ib_umad_sm_open(struct inode *inode, struct file *filp) } ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props); - if (ret) { - up(&port->sm_sem); - goto fail; - } + if (ret) + goto err_up_sem; filp->private_data = port; - return nonseekable_open(inode, filp); + ret = nonseekable_open(inode, filp); + if (ret) + goto err_clr_sm_cap; + + kobject_get(&port->umad_dev->kobj); + + return 0; + +err_clr_sm_cap: + swap(props.set_port_cap_mask, props.clr_port_cap_mask); + ib_modify_port(port->ib_dev, port->port_num, 0, &props); + +err_up_sem: + up(&port->sm_sem); fail: - kref_put(&port->umad_dev->ref, ib_umad_release_dev); return ret; } @@ -927,7 +936,7 @@ static int ib_umad_sm_close(struct inode *inode, struct file *filp) up(&port->sm_sem); - kref_put(&port->umad_dev->ref, ib_umad_release_dev); + kobject_put(&port->umad_dev->kobj); return ret; } @@ -995,6 +1004,7 @@ static int find_overflow_devnum(void) } static int ib_umad_init_port(struct ib_device *device, int port_num, + struct ib_umad_device *umad_dev, struct ib_umad_port *port) { int devnum; @@ -1027,6 +1037,7 @@ static int ib_umad_init_port(struct ib_device *device, int port_num, cdev_init(&port->cdev, &umad_fops); port->cdev.owner = THIS_MODULE; + port->cdev.kobj.parent = &umad_dev->kobj; kobject_set_name(&port->cdev.kobj, "umad%d", port->dev_num); if (cdev_add(&port->cdev, base, 1)) goto err_cdev; @@ -1045,6 +1056,7 @@ static int ib_umad_init_port(struct ib_device *device, int port_num, base += IB_UMAD_MAX_PORTS; cdev_init(&port->sm_cdev, &umad_sm_fops); port->sm_cdev.owner = THIS_MODULE; + port->sm_cdev.kobj.parent = &umad_dev->kobj; kobject_set_name(&port->sm_cdev.kobj, "issm%d", port->dev_num); if (cdev_add(&port->sm_cdev, base, 1)) goto err_sm_cdev; @@ -1138,7 +1150,7 @@ static void ib_umad_add_one(struct ib_device *device) if (!umad_dev) return; - kref_init(&umad_dev->ref); + kobject_init(&umad_dev->kobj, &ib_umad_dev_ktype); umad_dev->start_port = s; umad_dev->end_port = e; @@ -1146,7 +1158,8 @@ static void ib_umad_add_one(struct ib_device *device) for (i = s; i <= e; ++i) { umad_dev->port[i - s].umad_dev = umad_dev; - if (ib_umad_init_port(device, i, &umad_dev->port[i - s])) + if (ib_umad_init_port(device, i, umad_dev, + &umad_dev->port[i - s])) goto err; } @@ -1158,7 +1171,7 @@ static void ib_umad_add_one(struct ib_device *device) while (--i >= s) ib_umad_kill_port(&umad_dev->port[i - s]); - kref_put(&umad_dev->ref, ib_umad_release_dev); + kobject_put(&umad_dev->kobj); } static void ib_umad_remove_one(struct ib_device *device) @@ -1172,7 +1185,7 @@ static void ib_umad_remove_one(struct ib_device *device) for (i = 0; i <= umad_dev->end_port - umad_dev->start_port; ++i) ib_umad_kill_port(&umad_dev->port[i]); - kref_put(&umad_dev->ref, ib_umad_release_dev); + kobject_put(&umad_dev->kobj); } static char *umad_devnode(struct device *dev, umode_t *mode) diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c index e2f9a51f4a38..45802e97332e 100644 --- a/drivers/infiniband/hw/ipath/ipath_diag.c +++ b/drivers/infiniband/hw/ipath/ipath_diag.c @@ -346,6 +346,10 @@ static ssize_t ipath_diagpkt_write(struct file *fp, ret = -EFAULT; goto bail; } + dp.len = odp.len; + dp.unit = odp.unit; + dp.data = odp.data; + dp.pbc_wd = 0; } else { ret = -EINVAL; goto bail; diff --git a/drivers/infiniband/hw/qib/qib_mad.c b/drivers/infiniband/hw/qib/qib_mad.c index c4ff788823b5..14f39298cb97 100644 --- a/drivers/infiniband/hw/qib/qib_mad.c +++ b/drivers/infiniband/hw/qib/qib_mad.c @@ -1005,7 +1005,7 @@ static int set_pkeys(struct qib_devdata *dd, u8 port, u16 *pkeys) event.event = IB_EVENT_PKEY_CHANGE; event.device = &dd->verbs_dev.ibdev; - event.element.port_num = 1; + event.element.port_num = port; ib_dispatch_event(&event); } return 0; diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 922d845f76b0..7fa948d7a867 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -1371,6 +1371,12 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd) err_iu: srp_put_tx_iu(target, iu, SRP_IU_CMD); + /* + * Avoid that the loops that iterate over the request ring can + * encounter a dangling SCSI command pointer. + */ + req->scmnd = NULL; + spin_lock_irqsave(&target->lock, flags); list_add(&req->list, &target->free_reqs); diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 9bdc3b8597a4..d93ea6417d15 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -472,8 +472,15 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse, input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); - input_report_key(dev, BTN_LEFT, packet[0] & 0x01); - input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); + + /* For clickpads map both buttons to BTN_LEFT */ + if (etd->fw_version & 0x001000) { + input_report_key(dev, BTN_LEFT, packet[0] & 0x03); + } else { + input_report_key(dev, BTN_LEFT, packet[0] & 0x01); + input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); + } + input_report_abs(dev, ABS_PRESSURE, pres); input_report_abs(dev, ABS_TOOL_WIDTH, width); @@ -483,10 +490,17 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse, static void elantech_input_sync_v4(struct psmouse *psmouse) { struct input_dev *dev = psmouse->dev; + struct elantech_data *etd = psmouse->private; unsigned char *packet = psmouse->packet; - input_report_key(dev, BTN_LEFT, packet[0] & 0x01); - input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); + /* For clickpads map both buttons to BTN_LEFT */ + if (etd->fw_version & 0x001000) { + input_report_key(dev, BTN_LEFT, packet[0] & 0x03); + } else { + input_report_key(dev, BTN_LEFT, packet[0] & 0x01); + input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); + } + input_mt_report_pointer_emulation(dev, true); input_sync(dev); } 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..7801ebbf4b0a --- /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) +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] = { + { -5, -3, -5, -6, 10, 18, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3 }, + { -2, -1, -2, -3, 5, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 2, 1, 2, 3, -5, -9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 5, 3, 5, 6, -10, -18, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 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) +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][1]; + v255_val[2] = color_mods[new_b][2]; + v1_val[0] = color_mods[new_r][3]; + v1_val[1] = color_mods[new_g][4]; + v1_val[2] = color_mods[new_b][5]; + v171_val[0] = color_mods[new_r][6]; + v171_val[1] = color_mods[new_g][7]; + v171_val[2] = color_mods[new_b][8]; + v87_val[0] = color_mods[new_r][9]; + v87_val[1] = color_mods[new_g][10]; + v87_val[2] = color_mods[new_b][11]; +#if !defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_WVGA_PT) + v59_val[0] = color_mods[new_r][12]; + v59_val[1] = color_mods[new_g][13]; + v59_val[2] = color_mods[new_b][14]; + v35_val[0] = color_mods[new_r][15]; + v35_val[1] = color_mods[new_g][16]; + v35_val[2] = color_mods[new_b][17]; + v15_val[0] = color_mods[new_r][18]; + v15_val[1] = color_mods[new_g][19]; + v15_val[2] = color_mods[new_b][20]; +#else + v43_val[0] = color_mods[new_r][12]; + v43_val[1] = color_mods[new_g][13]; + v43_val[2] = color_mods[new_b][14]; + v19_val[0] = color_mods[new_r][15]; + v19_val[1] = color_mods[new_g][16]; + v19_val[2] = color_mods[new_b][17]; +#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) +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) + &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/pci/pci.c b/drivers/pci/pci.c index a7f6dcea0d76..4cdd2bc21403 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3610,7 +3610,7 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode, u16 cmd; int rc; - WARN_ON((flags & PCI_VGA_STATE_CHANGE_DECODES) & (command_bits & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY))); + WARN_ON((flags & PCI_VGA_STATE_CHANGE_DECODES) && (command_bits & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY))); /* ARCH specific VGA enables */ rc = pci_set_vga_state_arch(dev, decode, command_bits, flags); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 103c95e300fd..61bc33ed1116 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2921,6 +2921,7 @@ static void __devinit disable_igfx_irq(struct pci_dev *dev) } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0152, disable_igfx_irq); static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) 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_magna_oled_video_wvga_pt.c b/drivers/video/msm/mipi_magna_oled_video_wvga_pt.c index 00923e67e4c6..67b4b819a62e 100644 --- a/drivers/video/msm/mipi_magna_oled_video_wvga_pt.c +++ b/drivers/video/msm/mipi_magna_oled_video_wvga_pt.c @@ -530,7 +530,7 @@ static int set_elvss_level(int bl_level) void reset_gamma_level(void) { - pr_info("reset_gamma_level\n"); + pr_debug("reset_gamma_level\n"); mipi_pd.lcd_current_cd_idx = -1; } @@ -596,6 +596,11 @@ static int set_gamma_level(int bl_level, enum gamma_mode_list gamma_mode) return 0; } +int get_lcd_current_cd_index(void) +{ + return mipi_pd.lcd_current_cd_idx; +} + static struct mipi_panel_data mipi_pd = { .panel_name = "SMD_AMS452GP32\n", .ready_to_on = {samsung_display_on_cmds diff --git a/drivers/video/msm/mipi_samsung_oled.c b/drivers/video/msm/mipi_samsung_oled.c index 92557c6f682d..1c443efea099 100644 --- a/drivers/video/msm/mipi_samsung_oled.c +++ b/drivers/video/msm/mipi_samsung_oled.c @@ -1010,6 +1010,13 @@ if (msd.mpd->set_acl && msd.dstat.acl_on && !msd.mpd->set_acl(mfd->bl_level)) { return; } +void mipi_samsung_bump_backlight(int bl_level) { + struct msm_fb_data_type *mfd; + mfd = platform_get_drvdata(msd.msm_pdev); + mfd->bl_level = bl_level; + mipi_samsung_disp_backlight(mfd); +} + #if defined(CONFIG_HAS_EARLYSUSPEND) static void mipi_samsung_disp_early_suspend(struct early_suspend *h) { @@ -1354,6 +1361,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/mipi_samsung_oled_video_hd_pt.c b/drivers/video/msm/mipi_samsung_oled_video_hd_pt.c index f068b3cc0aad..3970491f7732 100644 --- a/drivers/video/msm/mipi_samsung_oled_video_hd_pt.c +++ b/drivers/video/msm/mipi_samsung_oled_video_hd_pt.c @@ -1234,7 +1234,7 @@ static int set_elvss_level_4_8(int bl_level) void reset_gamma_level(void) { - pr_info("reset_gamma_level\n"); + pr_debug("reset_gamma_level\n"); mipi_pd.lcd_current_cd_idx = -1; mipi_pd.ldi_acl_stat = false; @@ -1395,6 +1395,11 @@ static int set_gamma_level(int bl_level, enum gamma_mode_list gamma_mode) return aid_change; } +int get_lcd_current_cd_index(void) +{ + return mipi_pd.lcd_current_cd_idx; +} + static void prepare_fast_init_cmd_array(int lcd_type) { diff --git a/drivers/video/msm/mipi_samsung_oled_video_wvga_pt.c b/drivers/video/msm/mipi_samsung_oled_video_wvga_pt.c index 3b24c52b7866..9466d2f0794f 100755 --- a/drivers/video/msm/mipi_samsung_oled_video_wvga_pt.c +++ b/drivers/video/msm/mipi_samsung_oled_video_wvga_pt.c @@ -731,7 +731,7 @@ static int set_elvss_level(int bl_level) void reset_gamma_level(void) { - pr_info("reset_gamma_level\n"); + pr_debug("reset_gamma_level\n"); mipi_pd.lcd_current_cd_idx = -1; mipi_pd.ldi_acl_stat = false; elvss_cond_set[2] = 0x00; @@ -790,6 +790,11 @@ static int set_gamma_level(int bl_level, enum gamma_mode_list gamma_mode) return 0; } +int get_lcd_current_cd_index(void) +{ + return mipi_pd.lcd_current_cd_idx; +} + static int is_acl_para_change(int bl_level) { int cd = get_candela_index(bl_level); diff --git a/drivers/video/msm/smart_mtp_ea8868.c b/drivers/video/msm/smart_mtp_ea8868.c index 9507ebd00fe5..917762ccdc07 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,10 +52,24 @@ 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]; + +extern int get_lcd_current_cd_index(void); +extern void mipi_samsung_bump_backlight(int bl_level); +extern void reset_gamma_level(void); +void panel_load_colors(void) { - panelval = val; + int old; smart_dimming_init(gpsmart); + old = get_lcd_current_cd_index(); + reset_gamma_level(); + mipi_samsung_bump_backlight((old + 2) * 10); } #define v255_coefficient 100 @@ -76,7 +82,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 +95,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 +108,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 +170,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 +182,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 +194,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 +234,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 +248,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 +262,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 +325,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 +339,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 +353,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 +415,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 +429,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 +443,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 +507,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 +521,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 +535,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 +598,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 +612,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 +626,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..55790dda8a76 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,14 +78,26 @@ 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]; + +extern int get_lcd_current_cd_index(void); +extern void mipi_samsung_bump_backlight(int bl_level); +extern void reset_gamma_level(void); +void panel_load_colors(void) { - if (val < 5) { - panelval = val; - smart_dimming_init(gpsmart); - } + int old; + smart_dimming_init(gpsmart); + old = get_lcd_current_cd_index(); + reset_gamma_level(); + mipi_samsung_bump_backlight((old + 2) * 10); } + #define V255_COEFF 120 #define V255_DENOMTR 600 static int v255_adjustment(struct SMART_DIM *pSmart) @@ -104,7 +108,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 +121,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 +134,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 +195,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 +207,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 +219,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 +260,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 +274,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 +288,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 +352,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 +366,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 +380,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 +442,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 +456,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 +470,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 +535,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 +549,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 +563,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; @@ -794,7 +870,7 @@ static int generate_gray_scale(struct SMART_DIM *pSmart) cal_cnt++; } else { if (cnt == S6E63M0_ARRAY[6]) { - pr_info("%s end\n", __func__); + pr_debug("%s end\n", __func__); } else { pr_info(KERN_ERR "%s fail cnt:%d\n", __func__, cnt); @@ -899,7 +975,7 @@ static void gamma_cell_determine(int hw_revision) #elif defined(CONFIG_MACH_APEXQ) static void gamma_cell_determine(int ldi_id) { - pr_info("%s Panel type : %s", __func__, + pr_debug("%s Panel type : %s", __func__, (((ldi_id & 0x0000FF00) >> 8) == 0xB4) ? "SM2" : "M2"); if (((ldi_id & 0x0000FF00) >> 8) == 0xB4 || \ diff --git a/drivers/video/msm/smart_mtp_s6e8aa0x01.c b/drivers/video/msm/smart_mtp_s6e8aa0x01.c index 4c1503d2c9c2..f50f96bffabf 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,10 +91,24 @@ 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]; + +extern int get_lcd_current_cd_index(void); +extern void mipi_samsung_bump_backlight(int bl_level); +extern void reset_gamma_level(void); +void panel_load_colors(void) { - panelval = val; + int old; smart_dimming_init(gpsmart); + old = get_lcd_current_cd_index(); + reset_gamma_level(); + mipi_samsung_bump_backlight((old + 2) * 10); } #define v255_coefficient 100 #define v255_denominator 600 @@ -115,7 +122,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 +136,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 +150,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 +212,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 +224,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 +236,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 +277,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 +291,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 +305,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 +369,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 +383,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 +397,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 +460,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 +474,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 +488,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 +553,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 +567,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 +581,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 +644,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 +658,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 +672,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; @@ -888,7 +979,7 @@ static int generate_gray_scale(struct SMART_DIM *pSmart) cal_cnt++; } else { if (cnt == S6E8AA0X01_ARRAY[7]) { - pr_info("%s end\n", __func__); + pr_debug("%s end\n", __func__); } else { pr_err("%s fail cnt:%d\n", __func__, cnt); return -1; @@ -1388,7 +1479,7 @@ void generate_gamma(struct SMART_DIM *psmart, char *str, int size) static void gamma_cell_determine(int ldi_revision) { - pr_info("%s ldi_revision:%d", __func__, ldi_revision); + pr_debug("%s ldi_revision:%d", __func__, ldi_revision); #if defined(CONFIG_MACH_STRETTO) || defined(CONFIG_MACH_SUPERIORLTE_SKT) if (ldi_revision == 0xAE) { diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index bbb170e50055..a3b97e0c98df 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -62,7 +62,6 @@ * @adev: amba device structure of wdt * @status: current status of wdt * @load_val: load value to be set for current timeout - * @timeout: current programmed timeout */ struct sp805_wdt { spinlock_t lock; @@ -73,7 +72,6 @@ struct sp805_wdt { #define WDT_BUSY 0 #define WDT_CAN_BE_CLOSED 1 unsigned int load_val; - unsigned int timeout; }; /* local variables */ @@ -101,7 +99,7 @@ static void wdt_setload(unsigned int timeout) spin_lock(&wdt->lock); wdt->load_val = load; /* roundup timeout to closest positive integer value */ - wdt->timeout = div_u64((load + 1) * 2 + (rate / 2), rate); + wdd->timeout = div_u64((load + 1) * 2 + (rate / 2), rate); spin_unlock(&wdt->lock); } 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/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 28e5648c9cc4..a4b87c69fbbb 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3485,7 +3485,7 @@ nfsd4_free_lock_stateid(struct nfs4_ol_stateid *stp) * correspondance, and we have to delete the lockowner when we * delete the lock stateid: */ - unhash_lockowner(lo); + release_lockowner(lo); return nfs_ok; } diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 6eaa2e2335dc..ba7bf4a11855 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -2032,8 +2032,8 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, err = vfs_getattr(exp->ex_path.mnt, dentry, &stat); if (err) goto out_nfserr; - if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL | - FATTR4_WORD0_MAXNAME)) || + if ((bmval0 & (FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE | + FATTR4_WORD0_FILES_TOTAL | FATTR4_WORD0_MAXNAME)) || (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL))) { err = vfs_statfs(&path, &statfs); diff --git a/fs/ubifs/shrinker.c b/fs/ubifs/shrinker.c index 9e1d05666fed..e0a7a764a903 100644 --- a/fs/ubifs/shrinker.c +++ b/fs/ubifs/shrinker.c @@ -128,7 +128,6 @@ static int shrink_tnc(struct ubifs_info *c, int nr, int age, int *contention) freed = ubifs_destroy_tnc_subtree(znode); atomic_long_sub(freed, &ubifs_clean_zn_cnt); atomic_long_sub(freed, &c->clean_zn_cnt); - ubifs_assert(atomic_long_read(&c->clean_zn_cnt) >= 0); total_freed += freed; znode = zprev; } 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/ptrace.h b/include/linux/ptrace.h index 5c719627c2aa..ed12724901bc 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -379,6 +379,9 @@ static inline void user_single_step_siginfo(struct task_struct *tsk, * calling arch_ptrace_stop() when it would be superfluous. For example, * if the thread has not been back to user mode since the last stop, the * thread state might indicate that nothing needs to be done. + * + * This is guaranteed to be invoked once before a task stops for ptrace and + * may include arch-specific operations necessary prior to a ptrace stop. */ #define arch_ptrace_stop_needed(code, info) (0) #endif 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/include/trace/syscall.h b/include/trace/syscall.h index 31966a4fb8cc..51b72d8a8498 100644 --- a/include/trace/syscall.h +++ b/include/trace/syscall.h @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -54,4 +55,18 @@ int perf_sysexit_enable(struct ftrace_event_call *call); void perf_sysexit_disable(struct ftrace_event_call *call); #endif +#if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_HAVE_SYSCALL_TRACEPOINTS) +static inline void syscall_tracepoint_update(struct task_struct *p) +{ + if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) + set_tsk_thread_flag(p, TIF_SYSCALL_TRACEPOINT); + else + clear_tsk_thread_flag(p, TIF_SYSCALL_TRACEPOINT); +} +#else +static inline void syscall_tracepoint_update(struct task_struct *p) +{ +} +#endif + #endif /* _TRACE_SYSCALL_H */ diff --git a/kernel/fork.c b/kernel/fork.c index 5fe019baf272..84f3f2a7aa85 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1452,7 +1452,9 @@ static struct task_struct *copy_process(unsigned long clone_flags, total_forks++; spin_unlock(¤t->sighand->siglock); + syscall_tracepoint_update(p); write_unlock_irq(&tasklist_lock); + proc_fork_connector(p); cgroup_post_fork(p); if (clone_flags & CLONE_THREAD) 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); diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h index 54e35c1e5948..5e29610303b0 100644 --- a/scripts/recordmcount.h +++ b/scripts/recordmcount.h @@ -163,11 +163,11 @@ static int mcount_adjust = 0; static int MIPS_is_fake_mcount(Elf_Rel const *rp) { - static Elf_Addr old_r_offset; + static Elf_Addr old_r_offset = ~(Elf_Addr)0; Elf_Addr current_r_offset = _w(rp->r_offset); int is_fake; - is_fake = old_r_offset && + is_fake = (old_r_offset != ~(Elf_Addr)0) && (current_r_offset - old_r_offset == MIPS_FAKEMCOUNT_OFFSET); old_r_offset = current_r_offset;