Merge remote-tracking branch 'aosp/android-3.0' into develop-3.0

This commit is contained in:
黄涛
2011-11-30 10:36:13 +08:00
17 changed files with 230 additions and 214 deletions

View File

@@ -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

View File

@@ -22,7 +22,6 @@
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/kernel_debugger.h>
#include <linux/kernel_stat.h>
#include <linux/irq.h>
#include <linux/delay.h>
@@ -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 <number> Switch to CPU<number>\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 <param> Execute sysrq with <param>\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);

View File

@@ -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();

View File

@@ -22,6 +22,7 @@
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/tick.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <linux/kthread.h>
@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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/

View File

@@ -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 <linux/ctype.h>
#include <linux/device.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/sysrq.h>
#include <linux/kernel_debugger.h>
#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 <param> Execute sysrq with <param>\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;
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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))
{

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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

View File

@@ -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);

12
net/bluetooth/hci_event.c Normal file → Executable file
View File

@@ -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 */