From 050c06eed4b2ffaaf064992615507e520808ec46 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Tue, 8 Nov 2011 13:03:11 -0800 Subject: [PATCH 01/18] input: gpio_input: don't print debounce message unless flag is set Change-Id: I29ccb32e795c5c3e4c51c3d3a209f5b55dfd7d94 Signed-off-by: Dima Zavin --- drivers/input/misc/gpio_input.c | 9 +++++---- include/linux/gpio_event.h | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) 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/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 { From 2665c4135723dd7b15e8a5541956024b9ca138fa Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Thu, 3 Nov 2011 21:05:41 -0700 Subject: [PATCH 02/18] ARM: idle: update idle ticks before call idle end notifier Such that interactive cpufreq governor uses up-to-date idle time information. Reported by Colin Cross Change-Id: I06425444f800f803afc9dc7a6ad0fdb46c918bb6 Signed-off-by: Todd Poynor --- arch/arm/kernel/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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(); From a610c81ee00468c769e883845a68e688b01a7ca0 Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Thu, 27 Oct 2011 18:25:59 -0700 Subject: [PATCH 03/18] cpufreq: interactive governor: apply intermediate load on current speed Calculate intermediate speed by applyng CPU load to current speed, not max speed. Change-Id: Idecf598b9a203b07c989c5d9e9c6efc67a1afc2e Signed-off-by: Todd Poynor --- drivers/cpufreq/cpufreq_interactive.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c index e1d5015f1f5e..a085fc86733b 100644 --- a/drivers/cpufreq/cpufreq_interactive.c +++ b/drivers/cpufreq/cpufreq_interactive.c @@ -162,7 +162,7 @@ static void cpufreq_interactive_timer(unsigned long data) if (cpu_load >= go_maxspeed_load) new_freq = pcpu->policy->max; else - new_freq = pcpu->policy->max * cpu_load / 100; + new_freq = pcpu->policy->cur * cpu_load / 100; if (cpufreq_frequency_table_target(pcpu->policy, pcpu->freq_table, new_freq, CPUFREQ_RELATION_H, From eb5a34275e731c26cd15570f73796a0dc05c584a Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Thu, 3 Nov 2011 21:22:54 -0700 Subject: [PATCH 04/18] cpufreq: interactive governor: scale to max only if at min speed Change-Id: Ieffb2aa56b5290036285c948718be7be0d3af9e8 Signed-off-by: Todd Poynor --- drivers/cpufreq/cpufreq_interactive.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c index a085fc86733b..72ae6533a2d4 100644 --- a/drivers/cpufreq/cpufreq_interactive.c +++ b/drivers/cpufreq/cpufreq_interactive.c @@ -159,10 +159,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 + if (cpu_load >= go_maxspeed_load) { + if (pcpu->policy->cur == pcpu->policy->min) + new_freq = pcpu->policy->max; + 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, From 96cd2509c44a74039022ce6de382bcec5267331d Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Tue, 8 Nov 2011 19:54:07 -0800 Subject: [PATCH 05/18] cpufreq: interactive governor: go to intermediate hi speed before max * Add attribute hispeed_freq, which defaults to max. * Rename go_maxspeed_load to go_hispeed_load. * If hit go_hispeed_load and at min speed, go to hispeed_freq; if hit go_hispeed_load and already above min speed go to max speed. Change-Id: I1050dec5f013fc1177387352ba787a7e1c68703e Signed-off-by: Todd Poynor --- drivers/cpufreq/cpufreq_interactive.c | 59 ++++++++++++++++++++------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c index 72ae6533a2d4..859fdc14166f 100644 --- a/drivers/cpufreq/cpufreq_interactive.c +++ b/drivers/cpufreq/cpufreq_interactive.c @@ -58,9 +58,12 @@ 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. @@ -159,9 +162,9 @@ 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) { + if (cpu_load >= go_hispeed_load) { if (pcpu->policy->cur == pcpu->policy->min) - new_freq = pcpu->policy->max; + new_freq = hispeed_freq; else new_freq = pcpu->policy->max * cpu_load / 100; } else { @@ -427,13 +430,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; @@ -442,12 +469,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) @@ -494,7 +521,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, @@ -533,6 +561,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. @@ -610,7 +641,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; From 5113cb1203f6f463557d45baa17a6e826adc48aa Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Wed, 9 Nov 2011 16:56:18 -0800 Subject: [PATCH 06/18] cpufreq: interactive governor: default 20ms timer Change-Id: Ie9952f07b38667f2932474090044195c57976faa Signed-off-by: Todd Poynor --- drivers/cpufreq/cpufreq_interactive.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c index 859fdc14166f..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 @@ -68,13 +69,13 @@ 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, From 766aaa604cda5d23a88eb0f8495b49ec59ca6db7 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Fri, 4 Nov 2011 13:56:28 -0700 Subject: [PATCH 07/18] net: wireless: bcmdhd: Fix possible memory leak in escan/iscan Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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; } From 1720a91d03e84daa68e5c121b59e24dbdde40d9e Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Wed, 9 Nov 2011 13:00:24 -0800 Subject: [PATCH 08/18] net: wireless: bcmdhd: Call init_ioctl() only if was started properly Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/wl_android.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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; From 0d8f32b7e8e99f593d7d7ff1afac4e6320e1d5ab Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Wed, 9 Nov 2011 13:06:25 -0800 Subject: [PATCH 09/18] net: wireless: bcmdhd: Call init_ioctl() only if was started properly for WEXT Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/wl_iw.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) 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)) { From b11ab5b32976e504e3291d89435f06dbc79f5883 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Wed, 9 Nov 2011 16:10:57 -0800 Subject: [PATCH 10/18] ARM: common: fiq_debugger: add irq context debug functions This code is moved here from the drivers/misc/kernel_debugger. Change-Id: Iccf21c4313a8516a917125ca93f64baa5f354228 Signed-off-by: Dima Zavin --- arch/arm/common/Kconfig | 3 +- arch/arm/common/fiq_debugger.c | 80 ++++++++++++++++++++++++++-------- 2 files changed, 62 insertions(+), 21 deletions(-) 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..68e7265cc68d 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 @@ -474,7 +473,59 @@ 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); +} + +extern int do_syslog(int type, char __user *bug, int count); +static void do_sysrq(struct fiq_debugger_state *state, 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; + debug_printf(state, "%s", buf); + idx += ret; + } +} + +/* 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 +541,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 +564,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 +697,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 +774,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); } From 1e78d52ab825e2672bc8b552bdea582860f7b830 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Wed, 9 Nov 2011 16:48:00 -0800 Subject: [PATCH 11/18] ARM: common: fiq_debugger: dump sysrq directly to console if enabled If the fiq console is enabled, then don't filter the console output while sysrq command is in progress. Change-Id: I9389d757373a5fdca5cbf61f0723667510d3ae88 --- arch/arm/common/fiq_debugger.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/arch/arm/common/fiq_debugger.c b/arch/arm/common/fiq_debugger.c index 68e7265cc68d..3ed18ae2ed80 100644 --- a/arch/arm/common/fiq_debugger.c +++ b/arch/arm/common/fiq_debugger.c @@ -86,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]; @@ -496,14 +497,29 @@ static void do_ps(struct fiq_debugger_state *state) 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 do_sysrq(struct fiq_debugger_state *state, char rq) +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; - do_syslog(5 /* clear */, NULL, 0); - handle_sysrq(rq); + while (1) { ret = log_buf_copy(buf, idx, sizeof(buf) - 1); if (ret <= 0) @@ -513,6 +529,14 @@ static void do_sysrq(struct fiq_debugger_state *state, char rq) 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) @@ -871,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); From 9ab6a29787b1221a697f85835645549668258bdc Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Wed, 9 Nov 2011 16:07:17 -0800 Subject: [PATCH 12/18] misc: remove kernel debugger core The current split between this and the fiq debugger is awkward and does not have any benefit (the interface between the two is also too simplistic). The fiq debugger code itself needs a lot of refactoring, part of which would be to split out some components that are arch indpendent. So, for now, move this very small piece back into the fiq_debugger. Change-Id: Ie4ec2a2f5d907be1691a0eb6ae9304aad29ecd14 Signed-off-by: Dima Zavin --- drivers/misc/Kconfig | 7 --- drivers/misc/Makefile | 1 - drivers/misc/kernel_debugger.c | 89 --------------------------------- include/linux/kernel_debugger.h | 41 --------------- 4 files changed, 138 deletions(-) delete mode 100644 drivers/misc/kernel_debugger.c delete mode 100644 include/linux/kernel_debugger.h diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 68f367184ab5..961b5295074e 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 2d430484519c..5d8045878732 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/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 From 340ede367101d47c8fd69e83e5e6db9077f4caad Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 27 May 2011 11:33:18 -0700 Subject: [PATCH 13/18] rtc: Avoid accumulating time drift in suspend/resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Because the RTC interface is only a second granular interface, each time we read from the RTC for suspend/resume, we introduce a half second (on average) of error. In order to avoid this error accumulating as the system is suspended over and over, this patch measures the time delta between the RTC and the system CLOCK_REALTIME. If the delta is less then 2 seconds from the last suspend, we compensate by using the previous time delta (keeping it close). If it is larger then 2 seconds, we assume the clock was set or has been changed, so we do no correction and update the delta. Note: If NTP is running, ths could seem to "fight" with the NTP corrected time, where as if the system time was off by 1 second, and NTP slewed the value in, a suspend/resume cycle could undo this correction, by trying to restore the previous offset from the RTC. However, without this patch, since each read could cause almost a full second worth of error, its possible to get almost 2 seconds of error just from the suspend/resume cycle alone, so this about equal to any offset added by the compensation. Further on systems that suspend/resume frequently, this should keep time closer then NTP could compensate for if the errors were allowed to accumulate. Credits to Arve Hjønnevåg for suggesting this solution. This patch also improves some of the variable names and adds more clear comments. CC: Arve Hjønnevåg CC: Thomas Gleixner Signed-off-by: John Stultz --- drivers/rtc/class.c | 65 +++++++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 17 deletions(-) diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 4194e59e14cd..01a7df5317c1 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 (abs(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) + rtc_tm_to_time(&tm, &new_rtc.tv_sec); + new_rtc.tv_nsec = 0; + + if (new_rtc.tv_sec <= old_rtc.tv_sec) { + 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)); + + timekeeping_inject_sleeptime(&sleep_time); return 0; } From cf70c6a40073530c9e23fb373a541c09996429c7 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Wed, 1 Jun 2011 18:18:09 -0700 Subject: [PATCH 14/18] time: Catch invalid timespec sleep values in __timekeeping_inject_sleeptime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Arve suggested making sure we catch possible negative sleep time intervals that could be passed into timekeeping_inject_sleeptime. CC: Arve Hjønnevåg CC: Thomas Gleixner Signed-off-by: John Stultz --- kernel/time/timekeeping.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 342408cf68dd..9d09777a213f 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_WARN "__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); From 452d440ab295475afb04dee90879f5fb70254659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Tue, 22 Nov 2011 15:28:27 -0800 Subject: [PATCH 15/18] Fix "time: Catch invalid timespec sleep values in __timekeeping_inject_sleeptime" to compile on 3.0 Change-Id: I1225f279cda04dedbfb7f853f6b58f1032bd6d2b --- kernel/time/timekeeping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 9d09777a213f..fa58ec6d3bc3 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -605,7 +605,7 @@ static struct timespec timekeeping_suspend_time; static void __timekeeping_inject_sleeptime(struct timespec *delta) { if (!timespec_valid(delta)) { - printk(KERN_WARN "__timekeeping_inject_sleeptime: Invalid " + printk(KERN_WARNING "__timekeeping_inject_sleeptime: Invalid " "sleep delta value!\n"); return; } From 9d187300dfeb825b3c851458427a7046d9302c06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Tue, 22 Nov 2011 14:56:50 -0800 Subject: [PATCH 16/18] rtc: Fix some bugs that allowed accumulating time drift in suspend/resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current code checks if abs(delta_delta.tv_sec) is greater or equal to two before it discards the old delta value, but this can trigger at close to -1 seconds since -1.000000001 seconds is stored as tv_sec -2 and tv_nsec 999999999 in a normalized timespec. rtc_resume had an early return check if the rtc value had not changed since rtc_suspend. This effectivly stops time for the duration of the short sleep. Check if sleep_time is positive after all the adjustments have been applied instead since this allows the old_system adjustment in rtc_suspend to have an effect even for short sleep cycles. Change-Id: I00b45c0349ec91a4bab9b41a126b377515427898 Signed-off-by: Arve Hjønnevåg --- drivers/rtc/class.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 01a7df5317c1..b82a1554cdc1 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -66,7 +66,7 @@ static int rtc_suspend(struct device *dev, pm_message_t mesg) */ delta = timespec_sub(old_system, old_rtc); delta_delta = timespec_sub(delta, old_delta); - if (abs(delta_delta.tv_sec) >= 2) { + 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. @@ -100,9 +100,8 @@ static int rtc_resume(struct device *dev) rtc_tm_to_time(&tm, &new_rtc.tv_sec); new_rtc.tv_nsec = 0; - if (new_rtc.tv_sec <= old_rtc.tv_sec) { - if (new_rtc.tv_sec < old_rtc.tv_sec) - pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); + if (new_rtc.tv_sec < old_rtc.tv_sec) { + pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); return 0; } @@ -119,7 +118,8 @@ static int rtc_resume(struct device *dev) sleep_time = timespec_sub(sleep_time, timespec_sub(new_system, old_system)); - timekeeping_inject_sleeptime(&sleep_time); + if (sleep_time.tv_sec >= 0) + timekeeping_inject_sleeptime(&sleep_time); return 0; } From dbb18fb2c1519b7810018580ee5123f9be73f213 Mon Sep 17 00:00:00 2001 From: "hyungseoung.yoo" Date: Fri, 18 Nov 2011 13:57:01 +0900 Subject: [PATCH 17/18] Bluetooth: Keep master role when SCO or eSCO is active This improves compatbility with a lot of headset / chipset combinations. Ideally this should not be needed. Change-Id: I8b676701e12e416aa7d60801b9d353b15d102709 Signed-off-by: hyungseoung.yoo Signed-off-by: Jaikumar Ganesh --- net/bluetooth/hci_event.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) mode change 100644 => 100755 net/bluetooth/hci_event.c 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 */ From 6a4a38525d60db7e915d559273d8c89db5a98edf Mon Sep 17 00:00:00 2001 From: Benoit Goby Date: Mon, 28 Nov 2011 18:01:03 -0800 Subject: [PATCH 18/18] usb: gadget: android: Reset next_string_id before enable Reset next_string_id to 0 before enabling the gadget driver. Otherwise, after a large number of enable/disable cycles, bind will fail because we cannot allocate new string ids. String ids cannot be larger than 254 per USB spec. Change-Id: I44f5fece45008b7a0a18c025d4eb5ce842585c28 Signed-off-by: Benoit Goby --- drivers/usb/gadget/android.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c index d109bfb02f38..5d77899678f9 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;