diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig index cf82a884a5c5..638256600ffe 100644 --- a/arch/arm/common/Kconfig +++ b/arch/arm/common/Kconfig @@ -48,12 +48,11 @@ config FIQ_DEBUGGER bool "FIQ Mode Serial Debugger" select FIQ select FIQ_GLUE - select KERNEL_DEBUGGER_CORE default n help The FIQ serial debugger can accept commands even when the kernel is unresponsive due to being stuck with interrupts - disabled. Depends on the kernel debugger core in drivers/misc. + disabled. config FIQ_DEBUGGER_NO_SLEEP diff --git a/arch/arm/common/fiq_debugger.c b/arch/arm/common/fiq_debugger.c index b9b53c9994ab..3ed18ae2ed80 100644 --- a/arch/arm/common/fiq_debugger.c +++ b/arch/arm/common/fiq_debugger.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -87,6 +86,7 @@ struct fiq_debugger_state { struct tty_struct *tty; int tty_open_count; struct fiq_debugger_ringbuf *tty_rbuf; + bool syslog_dumping; #endif unsigned int last_irqs[NR_IRQS]; @@ -474,7 +474,82 @@ void dump_stacktrace(struct fiq_debugger_state *state, tail = user_backtrace(state, tail); } -static bool debug_help(struct fiq_debugger_state *state) +static void do_ps(struct fiq_debugger_state *state) +{ + struct task_struct *g; + struct task_struct *p; + unsigned task_state; + static const char stat_nam[] = "RSDTtZX"; + + debug_printf(state, "pid ppid prio task pc\n"); + read_lock(&tasklist_lock); + do_each_thread(g, p) { + task_state = p->state ? __ffs(p->state) + 1 : 0; + debug_printf(state, + "%5d %5d %4d ", p->pid, p->parent->pid, p->prio); + debug_printf(state, "%-13.13s %c", p->comm, + task_state >= sizeof(stat_nam) ? '?' : stat_nam[task_state]); + if (task_state == TASK_RUNNING) + debug_printf(state, " running\n"); + else + debug_printf(state, " %08lx\n", thread_saved_pc(p)); + } while_each_thread(g, p); + read_unlock(&tasklist_lock); +} + +#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE +static void begin_syslog_dump(struct fiq_debugger_state *state) +{ + state->syslog_dumping = true; +} + +static void end_syslog_dump(struct fiq_debugger_state *state) +{ + state->syslog_dumping = false; +} +#else +extern int do_syslog(int type, char __user *bug, int count); +static void begin_syslog_dump(struct fiq_debugger_state *state) +{ + do_syslog(5 /* clear */, NULL, 0); +} + +static void end_syslog_dump(struct fiq_debugger_state *state) +{ + char buf[128]; + int ret; + int idx = 0; + + while (1) { + ret = log_buf_copy(buf, idx, sizeof(buf) - 1); + if (ret <= 0) + break; + buf[ret] = 0; + debug_printf(state, "%s", buf); + idx += ret; + } +} +#endif + +static void do_sysrq(struct fiq_debugger_state *state, char rq) +{ + begin_syslog_dump(state); + handle_sysrq(rq); + end_syslog_dump(state); +} + +/* This function CANNOT be called in FIQ context */ +static void debug_irq_exec(struct fiq_debugger_state *state, char *cmd) +{ + if (!strcmp(cmd, "ps")) + do_ps(state); + if (!strcmp(cmd, "sysrq")) + do_sysrq(state, 'h'); + if (!strncmp(cmd, "sysrq ", 6)) + do_sysrq(state, cmd[6]); +} + +static void debug_help(struct fiq_debugger_state *state) { debug_printf(state, "FIQ Debugger commands:\n" " pc PC status\n" @@ -490,13 +565,9 @@ static bool debug_help(struct fiq_debugger_state *state) " console Switch terminal to console\n" " cpu Current CPU\n" " cpu Switch to CPU\n"); - if (!state->debug_busy) { - strcpy(state->debug_cmd, "help"); - state->debug_busy = 1; - return true; - } - - return false; + debug_printf(state, " ps Process list\n" + " sysrq sysrq options\n" + " sysrq Execute sysrq with \n"); } static void take_affinity(void *info) @@ -517,13 +588,13 @@ static void switch_cpu(struct fiq_debugger_state *state, int cpu) state->current_cpu = cpu; } -static bool debug_exec(struct fiq_debugger_state *state, +static bool debug_fiq_exec(struct fiq_debugger_state *state, const char *cmd, unsigned *regs, void *svc_sp) { bool signal_helper = false; if (!strcmp(cmd, "help") || !strcmp(cmd, "?")) { - signal_helper |= debug_help(state); + debug_help(state); } else if (!strcmp(cmd, "pc")) { debug_printf(state, " pc %08x cpsr %08x mode %s\n", regs[15], regs[16], mode_name(regs[16])); @@ -650,13 +721,8 @@ static void debug_handle_irq_context(struct fiq_debugger_state *state) } #endif if (state->debug_busy) { - struct kdbg_ctxt ctxt; - - ctxt.printf = debug_printf_nfiq; - ctxt.cookie = state; - kernel_debugger(&ctxt, state->debug_cmd); + debug_irq_exec(state, state->debug_cmd); debug_prompt(state); - state->debug_busy = 0; } } @@ -732,8 +798,8 @@ static bool debug_handle_uart_interrupt(struct fiq_debugger_state *state, state->debug_buf[state->debug_count] = 0; state->debug_count = 0; signal_helper |= - debug_exec(state, state->debug_buf, - regs, svc_sp); + debug_fiq_exec(state, state->debug_buf, + regs, svc_sp); } else { debug_prompt(state); } @@ -829,7 +895,7 @@ static void debug_console_write(struct console *co, state = container_of(co, struct fiq_debugger_state, console); - if (!state->console_enable) + if (!state->console_enable && !state->syslog_dumping) return; debug_uart_enable(state); diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 6810cc1b7c42..54c97eee6173 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -248,8 +248,8 @@ void cpu_idle(void) local_irq_enable(); } } - idle_notifier_call_chain(IDLE_END); tick_nohz_restart_sched_tick(); + idle_notifier_call_chain(IDLE_END); preempt_enable_no_resched(); schedule(); preempt_disable(); diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c index e1d5015f1f5e..45266d5b6cd5 100644 --- a/drivers/cpufreq/cpufreq_interactive.c +++ b/drivers/cpufreq/cpufreq_interactive.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -58,20 +59,23 @@ static cpumask_t down_cpumask; static spinlock_t down_cpumask_lock; static struct mutex set_speed_lock; -/* Go to max speed when CPU load at or above this value. */ -#define DEFAULT_GO_MAXSPEED_LOAD 95 -static unsigned long go_maxspeed_load; +/* Hi speed to bump to from lo speed when load burst (default max) */ +static u64 hispeed_freq; + +/* Go to hi speed when CPU load at or above this value. */ +#define DEFAULT_GO_HISPEED_LOAD 95 +static unsigned long go_hispeed_load; /* * The minimum amount of time to spend at a frequency before we can ramp down. */ -#define DEFAULT_MIN_SAMPLE_TIME 20000; +#define DEFAULT_MIN_SAMPLE_TIME 20 * USEC_PER_MSEC static unsigned long min_sample_time; /* * The sample rate of the timer used to increase frequency */ -#define DEFAULT_TIMER_RATE 10000; +#define DEFAULT_TIMER_RATE 20 * USEC_PER_MSEC static unsigned long timer_rate; static int cpufreq_governor_interactive(struct cpufreq_policy *policy, @@ -159,10 +163,14 @@ static void cpufreq_interactive_timer(unsigned long data) if (load_since_change > cpu_load) cpu_load = load_since_change; - if (cpu_load >= go_maxspeed_load) - new_freq = pcpu->policy->max; - else - new_freq = pcpu->policy->max * cpu_load / 100; + if (cpu_load >= go_hispeed_load) { + if (pcpu->policy->cur == pcpu->policy->min) + new_freq = hispeed_freq; + else + new_freq = pcpu->policy->max * cpu_load / 100; + } else { + new_freq = pcpu->policy->cur * cpu_load / 100; + } if (cpufreq_frequency_table_target(pcpu->policy, pcpu->freq_table, new_freq, CPUFREQ_RELATION_H, @@ -423,13 +431,37 @@ static void cpufreq_interactive_freq_down(struct work_struct *work) } } -static ssize_t show_go_maxspeed_load(struct kobject *kobj, - struct attribute *attr, char *buf) +static ssize_t show_hispeed_freq(struct kobject *kobj, + struct attribute *attr, char *buf) { - return sprintf(buf, "%lu\n", go_maxspeed_load); + return sprintf(buf, "%llu\n", hispeed_freq); } -static ssize_t store_go_maxspeed_load(struct kobject *kobj, +static ssize_t store_hispeed_freq(struct kobject *kobj, + struct attribute *attr, const char *buf, + size_t count) +{ + int ret; + u64 val; + + ret = strict_strtoull(buf, 0, &val); + if (ret < 0) + return ret; + hispeed_freq = val; + return count; +} + +static struct global_attr hispeed_freq_attr = __ATTR(hispeed_freq, 0644, + show_hispeed_freq, store_hispeed_freq); + + +static ssize_t show_go_hispeed_load(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + return sprintf(buf, "%lu\n", go_hispeed_load); +} + +static ssize_t store_go_hispeed_load(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) { int ret; @@ -438,12 +470,12 @@ static ssize_t store_go_maxspeed_load(struct kobject *kobj, ret = strict_strtoul(buf, 0, &val); if (ret < 0) return ret; - go_maxspeed_load = val; + go_hispeed_load = val; return count; } -static struct global_attr go_maxspeed_load_attr = __ATTR(go_maxspeed_load, 0644, - show_go_maxspeed_load, store_go_maxspeed_load); +static struct global_attr go_hispeed_load_attr = __ATTR(go_hispeed_load, 0644, + show_go_hispeed_load, store_go_hispeed_load); static ssize_t show_min_sample_time(struct kobject *kobj, struct attribute *attr, char *buf) @@ -490,7 +522,8 @@ static struct global_attr timer_rate_attr = __ATTR(timer_rate, 0644, show_timer_rate, store_timer_rate); static struct attribute *interactive_attributes[] = { - &go_maxspeed_load_attr.attr, + &hispeed_freq_attr.attr, + &go_hispeed_load_attr.attr, &min_sample_time_attr.attr, &timer_rate_attr.attr, NULL, @@ -529,6 +562,9 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, smp_wmb(); } + if (!hispeed_freq) + hispeed_freq = policy->max; + /* * Do not register the idle hook and create sysfs * entries if we have already done so. @@ -606,7 +642,7 @@ static int __init cpufreq_interactive_init(void) struct cpufreq_interactive_cpuinfo *pcpu; struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; - go_maxspeed_load = DEFAULT_GO_MAXSPEED_LOAD; + go_hispeed_load = DEFAULT_GO_HISPEED_LOAD; min_sample_time = DEFAULT_MIN_SAMPLE_TIME; timer_rate = DEFAULT_TIMER_RATE; diff --git a/drivers/input/misc/gpio_input.c b/drivers/input/misc/gpio_input.c index 904bd684449b..6a0c31510968 100644 --- a/drivers/input/misc/gpio_input.c +++ b/drivers/input/misc/gpio_input.c @@ -82,10 +82,11 @@ static enum hrtimer_restart gpio_event_input_timer_func(struct hrtimer *timer) if (key_state->debounce & DEBOUNCE_UNSTABLE) { debounce = key_state->debounce = DEBOUNCE_UNKNOWN; enable_irq(gpio_to_irq(key_entry->gpio)); - pr_info("gpio_keys_scan_keys: key %x-%x, %d " - "(%d) continue debounce\n", - ds->info->type, key_entry->code, - i, key_entry->gpio); + if (gpio_flags & GPIOEDF_PRINT_KEY_UNSTABLE) + pr_info("gpio_keys_scan_keys: key %x-%x, %d " + "(%d) continue debounce\n", + ds->info->type, key_entry->code, + i, key_entry->gpio); } npolarity = !(gpio_flags & GPIOEDF_ACTIVE_HIGH); pressed = gpio_get_value(key_entry->gpio) ^ npolarity; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 710153c51556..7b48ab90e592 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -233,13 +233,6 @@ config ENCLOSURE_SERVICES driver (SCSI/ATA) which supports enclosures or a SCSI enclosure device (SES) to use these services. -config KERNEL_DEBUGGER_CORE - bool "Kernel Debugger Core" - default n - ---help--- - Generic kernel debugging command processor used by low level - (interrupt context) platform-specific debuggers. - config SGI_XP tristate "Support communication between SGI SSIs" depends on NET diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 3a67414ad023..410e64d7103d 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -22,7 +22,6 @@ obj-$(CONFIG_SENSORS_APDS990X) += apds990x.o obj-$(CONFIG_ANDROID_PMEM) += pmem.o obj-$(CONFIG_SGI_IOC4) += ioc4.o obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o -obj-$(CONFIG_KERNEL_DEBUGGER_CORE) += kernel_debugger.o obj-$(CONFIG_KGDB_TESTS) += kgdbts.o obj-$(CONFIG_SGI_XP) += sgi-xp/ obj-$(CONFIG_SGI_GRU) += sgi-gru/ diff --git a/drivers/misc/kernel_debugger.c b/drivers/misc/kernel_debugger.c deleted file mode 100644 index 4a9fef6244ed..000000000000 --- a/drivers/misc/kernel_debugger.c +++ /dev/null @@ -1,89 +0,0 @@ -/* drivers/android/kernel_debugger.c - * - * Guts of the kernel debugger. - * Needs something to actually push commands to it. - * - * Copyright (C) 2007-2008 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include -#include -#include - -#define dprintf(fmt...) (ctxt->printf(ctxt->cookie, fmt)) - -static void do_ps(struct kdbg_ctxt *ctxt) -{ - struct task_struct *g, *p; - unsigned state; - static const char stat_nam[] = "RSDTtZX"; - - dprintf("pid ppid prio task pc\n"); - read_lock(&tasklist_lock); - do_each_thread(g, p) { - state = p->state ? __ffs(p->state) + 1 : 0; - dprintf("%5d %5d %4d ", p->pid, p->parent->pid, p->prio); - dprintf("%-13.13s %c", p->comm, - state >= sizeof(stat_nam) ? '?' : stat_nam[state]); - if (state == TASK_RUNNING) - dprintf(" running\n"); - else - dprintf(" %08lx\n", thread_saved_pc(p)); - } while_each_thread(g, p); - read_unlock(&tasklist_lock); -} - -int log_buf_copy(char *dest, int idx, int len); -extern int do_syslog(int type, char __user *bug, int count); -static void do_sysrq(struct kdbg_ctxt *ctxt, char rq) -{ - char buf[128]; - int ret; - int idx = 0; - do_syslog(5 /* clear */, NULL, 0); - handle_sysrq(rq); - while (1) { - ret = log_buf_copy(buf, idx, sizeof(buf) - 1); - if (ret <= 0) - break; - buf[ret] = 0; - dprintf("%s", buf); - idx += ret; - } -} - -static void do_help(struct kdbg_ctxt *ctxt) -{ - dprintf("Kernel Debugger commands:\n"); - dprintf(" ps Process list\n"); - dprintf(" sysrq sysrq options\n"); - dprintf(" sysrq Execute sysrq with \n"); -} - -int kernel_debugger(struct kdbg_ctxt *ctxt, char *cmd) -{ - if (!strcmp(cmd, "ps")) - do_ps(ctxt); - if (!strcmp(cmd, "sysrq")) - do_sysrq(ctxt, 'h'); - if (!strncmp(cmd, "sysrq ", 6)) - do_sysrq(ctxt, cmd[6]); - if (!strcmp(cmd, "help")) - do_help(ctxt); - - return 0; -} - diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index 7c6ab2fb2821..9ca3d6020239 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -364,7 +364,8 @@ int wl_android_wifi_on(struct net_device *dev) sdioh_start(NULL, 0); ret = dhd_dev_reset(dev, FALSE); sdioh_start(NULL, 1); - dhd_dev_init_ioctl(dev); + if (!ret) + dhd_dev_init_ioctl(dev); g_wifi_on = 1; } dhd_net_if_unlock(dev); @@ -384,7 +385,7 @@ int wl_android_wifi_off(struct net_device *dev) dhd_net_if_lock(dev); if (g_wifi_on) { - dhd_dev_reset(dev, 1); + ret = dhd_dev_reset(dev, TRUE); sdioh_stop(NULL); dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); g_wifi_on = 0; diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 526ba47895bc..daa7d2605aaf 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -1245,8 +1245,7 @@ wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request, } params = (struct wl_iscan_params *)kzalloc(params_size, GFP_KERNEL); if (!params) { - err = -ENOMEM; - goto done; + return -ENOMEM; } if (request != NULL) @@ -1270,8 +1269,8 @@ wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request, WL_ERR(("error (%d)\n", err)); } } - kfree(params); done: + kfree(params); return err; } @@ -1348,6 +1347,7 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, params->sync_id = htod16(0x1234); if (params_size + sizeof("escan") >= WLC_IOCTL_MEDLEN) { WL_ERR(("ioctl buffer length not sufficient\n")); + kfree(params); err = -ENOMEM; goto exit; } diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c index 3acdea19cb4f..ba3cc6c876ca 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.c +++ b/drivers/net/wireless/bcmdhd/wl_iw.c @@ -1667,8 +1667,8 @@ wl_control_wl_start(struct net_device *dev) #if defined(BCMLXSDMMC) sdioh_start(NULL, 1); #endif - - dhd_dev_init_ioctl(dev); + if (!ret) + dhd_dev_init_ioctl(dev); g_onoff = G_WLAN_SET_ON; } @@ -1715,7 +1715,7 @@ wl_iw_control_wl_off( g_iscan->iscan_state = ISCAN_STATE_IDLE; #endif - dhd_dev_reset(dev, 1); + ret = dhd_dev_reset(dev, 1); #if defined(WL_IW_USE_ISCAN) #if !defined(CSCAN) @@ -1738,9 +1738,6 @@ wl_iw_control_wl_off( sdioh_stop(NULL); #endif - - net_os_set_dtim_skip(dev, 0); - dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); wl_iw_send_priv_event(dev, "STOP"); @@ -8147,7 +8144,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) case WLC_E_ROAM: if (status == WLC_E_STATUS_SUCCESS) { WL_ASSOC((" WLC_E_ROAM : success \n")); - return; + goto wl_iw_event_end; } break; @@ -8285,6 +8282,11 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) case WLC_E_SCAN_COMPLETE: #if defined(WL_IW_USE_ISCAN) + if (!g_iscan) { + WL_ERROR(("Event WLC_E_SCAN_COMPLETE on g_iscan NULL!")); + goto wl_iw_event_end; + } + if ((g_iscan) && (g_iscan->tsk_ctl.thr_pid >= 0) && (g_iscan->iscan_state != ISCAN_STATE_IDLE)) { diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 4194e59e14cd..b82a1554cdc1 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -41,20 +41,41 @@ static void rtc_device_release(struct device *dev) * system's wall clock; restore it on resume(). */ -static time_t oldtime; -static struct timespec oldts; +static struct timespec old_rtc, old_system, old_delta; + static int rtc_suspend(struct device *dev, pm_message_t mesg) { struct rtc_device *rtc = to_rtc_device(dev); struct rtc_time tm; - + struct timespec delta, delta_delta; if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) return 0; + /* snapshot the current RTC and system time at suspend*/ rtc_read_time(rtc, &tm); - ktime_get_ts(&oldts); - rtc_tm_to_time(&tm, &oldtime); + getnstimeofday(&old_system); + rtc_tm_to_time(&tm, &old_rtc.tv_sec); + + + /* + * To avoid drift caused by repeated suspend/resumes, + * which each can add ~1 second drift error, + * try to compensate so the difference in system time + * and rtc time stays close to constant. + */ + delta = timespec_sub(old_system, old_rtc); + delta_delta = timespec_sub(delta, old_delta); + if (delta_delta.tv_sec < -2 || delta_delta.tv_sec >= 2) { + /* + * if delta_delta is too large, assume time correction + * has occured and set old_delta to the current delta. + */ + old_delta = delta; + } else { + /* Otherwise try to adjust old_system to compensate */ + old_system = timespec_sub(old_system, delta_delta); + } return 0; } @@ -63,32 +84,42 @@ static int rtc_resume(struct device *dev) { struct rtc_device *rtc = to_rtc_device(dev); struct rtc_time tm; - time_t newtime; - struct timespec time; - struct timespec newts; + struct timespec new_system, new_rtc; + struct timespec sleep_time; if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) return 0; - ktime_get_ts(&newts); + /* snapshot the current rtc and system time at resume */ + getnstimeofday(&new_system); rtc_read_time(rtc, &tm); if (rtc_valid_tm(&tm) != 0) { pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev)); return 0; } - rtc_tm_to_time(&tm, &newtime); - if (newtime <= oldtime) { - if (newtime < oldtime) - pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); + rtc_tm_to_time(&tm, &new_rtc.tv_sec); + new_rtc.tv_nsec = 0; + + if (new_rtc.tv_sec < old_rtc.tv_sec) { + pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); return 0; } - /* calculate the RTC time delta */ - set_normalized_timespec(&time, newtime - oldtime, 0); - /* subtract kernel time between rtc_suspend to rtc_resume */ - time = timespec_sub(time, timespec_sub(newts, oldts)); + /* calculate the RTC time delta (sleep time)*/ + sleep_time = timespec_sub(new_rtc, old_rtc); - timekeeping_inject_sleeptime(&time); + /* + * Since these RTC suspend/resume handlers are not called + * at the very end of suspend or the start of resume, + * some run-time may pass on either sides of the sleep time + * so subtract kernel run-time between rtc_suspend to rtc_resume + * to keep things accurate. + */ + sleep_time = timespec_sub(sleep_time, + timespec_sub(new_system, old_system)); + + if (sleep_time.tv_sec >= 0) + timekeeping_inject_sleeptime(&sleep_time); return 0; } diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c index 0736d704bddb..eda640e70623 100644 --- a/drivers/usb/gadget/android.c +++ b/drivers/usb/gadget/android.c @@ -823,6 +823,7 @@ static ssize_t enable_store(struct device *pdev, struct device_attribute *attr, sscanf(buff, "%d", &enabled); if (enabled && !dev->enabled) { + cdev->next_string_id = 0; /* update values in composite driver's copy of device descriptor */ cdev->desc.idVendor = device_desc.idVendor; cdev->desc.idProduct = device_desc.idProduct; diff --git a/include/linux/gpio_event.h b/include/linux/gpio_event.h index 360b4ddb46a6..2613fc5e4a93 100644 --- a/include/linux/gpio_event.h +++ b/include/linux/gpio_event.h @@ -98,6 +98,7 @@ enum gpio_event_direct_flags { /* GPIOEDF_USE_IRQ = (1U << 2) | GPIOIDF_USE_DOWN_IRQ, */ GPIOEDF_PRINT_KEYS = 1U << 8, GPIOEDF_PRINT_KEY_DEBOUNCE = 1U << 9, + GPIOEDF_PRINT_KEY_UNSTABLE = 1U << 10, }; struct gpio_event_direct_entry { diff --git a/include/linux/kernel_debugger.h b/include/linux/kernel_debugger.h deleted file mode 100644 index b4dbfe99d79e..000000000000 --- a/include/linux/kernel_debugger.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * include/linux/kernel_debugger.h - * - * Copyright (C) 2008 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _LINUX_KERNEL_DEBUGGER_H_ -#define _LINUX_KERNEL_DEBUGGER_H_ - -struct kdbg_ctxt { - int (*printf)(void *cookie, const char *fmt, ...); - void *cookie; -}; - -/* kernel_debugger() is called from IRQ context and should - * use the kdbg_ctxt.printf to write output (do NOT call - * printk, do operations not safe from IRQ context, etc). - * - * kdbg_ctxt.printf will return -1 if there is not enough - * buffer space or if you are being aborted. In this case - * you must return as soon as possible. - * - * Return non-zero if more data is available -- if buffer - * space ran and you had to stop, but could print more, - * for example. - * - * Additional calls where cmd is "more" will be made if - * the additional data is desired. - */ -int kernel_debugger(struct kdbg_ctxt *ctxt, char *cmd); - -#endif diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 342408cf68dd..fa58ec6d3bc3 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -604,6 +604,12 @@ static struct timespec timekeeping_suspend_time; */ static void __timekeeping_inject_sleeptime(struct timespec *delta) { + if (!timespec_valid(delta)) { + printk(KERN_WARNING "__timekeeping_inject_sleeptime: Invalid " + "sleep delta value!\n"); + return; + } + xtime = timespec_add(xtime, *delta); wall_to_monotonic = timespec_sub(wall_to_monotonic, *delta); total_sleep_time = timespec_add(total_sleep_time, *delta); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c old mode 100644 new mode 100755 index a32571a22bb4..5a7074a7b5b8 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1462,6 +1462,15 @@ unlock: hci_conn_check_pending(hdev); } +static inline bool is_sco_active(struct hci_dev *hdev) +{ + if (hci_conn_hash_lookup_state(hdev, SCO_LINK, BT_CONNECTED) || + (hci_conn_hash_lookup_state(hdev, ESCO_LINK, + BT_CONNECTED))) + return true; + return false; +} + static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_conn_request *ev = (void *) skb->data; @@ -1505,7 +1514,8 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk bacpy(&cp.bdaddr, &ev->bdaddr); - if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) + if (lmp_rswitch_capable(hdev) && ((mask & HCI_LM_MASTER) + || is_sco_active(hdev))) cp.role = 0x00; /* Become master */ else cp.role = 0x01; /* Remain slave */