mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 14:42:37 +02:00
Merge branch 'linaro-fixes/android-3.10' into linaro-android-3.10-lsk
This commit is contained in:
commit
ff22184ab6
|
|
@ -21,49 +21,3 @@ config SHARP_SCOOP
|
|||
config FIQ_GLUE
|
||||
bool
|
||||
select FIQ
|
||||
|
||||
config FIQ_DEBUGGER
|
||||
bool "FIQ Mode Serial Debugger"
|
||||
select FIQ
|
||||
select FIQ_GLUE
|
||||
default n
|
||||
help
|
||||
The FIQ serial debugger can accept commands even when the
|
||||
kernel is unresponsive due to being stuck with interrupts
|
||||
disabled.
|
||||
|
||||
|
||||
config FIQ_DEBUGGER_NO_SLEEP
|
||||
bool "Keep serial debugger active"
|
||||
depends on FIQ_DEBUGGER
|
||||
default n
|
||||
help
|
||||
Enables the serial debugger at boot. Passing
|
||||
fiq_debugger.no_sleep on the kernel commandline will
|
||||
override this config option.
|
||||
|
||||
config FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON
|
||||
bool "Don't disable wakeup IRQ when debugger is active"
|
||||
depends on FIQ_DEBUGGER
|
||||
default n
|
||||
help
|
||||
Don't disable the wakeup irq when enabling the uart clock. This will
|
||||
cause extra interrupts, but it makes the serial debugger usable with
|
||||
on some MSM radio builds that ignore the uart clock request in power
|
||||
collapse.
|
||||
|
||||
config FIQ_DEBUGGER_CONSOLE
|
||||
bool "Console on FIQ Serial Debugger port"
|
||||
depends on FIQ_DEBUGGER
|
||||
default n
|
||||
help
|
||||
Enables a console so that printk messages are displayed on
|
||||
the debugger serial port as the occur.
|
||||
|
||||
config FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE
|
||||
bool "Put the FIQ debugger into console mode by default"
|
||||
depends on FIQ_DEBUGGER_CONSOLE
|
||||
default n
|
||||
help
|
||||
If enabled, this puts the fiq debugger into console mode by default.
|
||||
Otherwise, the fiq debugger will start out in debug mode.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
obj-y += firmware.o
|
||||
|
||||
obj-$(CONFIG_FIQ_DEBUGGER) += fiq_debugger.o
|
||||
obj-$(CONFIG_FIQ_GLUE) += fiq_glue.o fiq_glue_setup.o
|
||||
obj-$(CONFIG_ICST) += icst.o
|
||||
obj-$(CONFIG_SA1111) += sa1111.o
|
||||
|
|
|
|||
|
|
@ -768,6 +768,8 @@ static const char *keys[KEY_MAX + 1] = {
|
|||
[KEY_ALTERASE] = "AlternateErase", [KEY_CANCEL] = "Cancel",
|
||||
[KEY_BRIGHTNESSDOWN] = "BrightnessDown", [KEY_BRIGHTNESSUP] = "BrightnessUp",
|
||||
[KEY_MEDIA] = "Media", [KEY_UNKNOWN] = "Unknown",
|
||||
[BTN_DPAD_UP] = "BtnDPadUp", [BTN_DPAD_DOWN] = "BtnDPadDown",
|
||||
[BTN_DPAD_LEFT] = "BtnDPadLeft", [BTN_DPAD_RIGHT] = "BtnDPadRight",
|
||||
[BTN_0] = "Btn0", [BTN_1] = "Btn1",
|
||||
[BTN_2] = "Btn2", [BTN_3] = "Btn3",
|
||||
[BTN_4] = "Btn4", [BTN_5] = "Btn5",
|
||||
|
|
@ -797,7 +799,8 @@ static const char *keys[KEY_MAX + 1] = {
|
|||
[BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens",
|
||||
[BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus",
|
||||
[BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "ToolDoubleTap",
|
||||
[BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_GEAR_DOWN] = "WheelBtn",
|
||||
[BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_TOOL_QUADTAP] = "ToolQuadrupleTap",
|
||||
[BTN_GEAR_DOWN] = "WheelBtn",
|
||||
[BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok",
|
||||
[KEY_SELECT] = "Select", [KEY_GOTO] = "Goto",
|
||||
[KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2",
|
||||
|
|
@ -852,6 +855,16 @@ static const char *keys[KEY_MAX + 1] = {
|
|||
[KEY_KBDILLUMDOWN] = "KbdIlluminationDown",
|
||||
[KEY_KBDILLUMUP] = "KbdIlluminationUp",
|
||||
[KEY_SWITCHVIDEOMODE] = "SwitchVideoMode",
|
||||
[KEY_BUTTONCONFIG] = "ButtonConfig",
|
||||
[KEY_TASKMANAGER] = "TaskManager",
|
||||
[KEY_JOURNAL] = "Journal",
|
||||
[KEY_CONTROLPANEL] = "ControlPanel",
|
||||
[KEY_APPSELECT] = "AppSelect",
|
||||
[KEY_SCREENSAVER] = "ScreenSaver",
|
||||
[KEY_VOICECOMMAND] = "VoiceCommand",
|
||||
[KEY_BRIGHTNESS_MIN] = "BrightnessMin",
|
||||
[KEY_BRIGHTNESS_MAX] = "BrightnessMax",
|
||||
[KEY_BRIGHTNESS_AUTO] = "BrightnessAuto",
|
||||
};
|
||||
|
||||
static const char *relatives[REL_MAX + 1] = {
|
||||
|
|
|
|||
|
|
@ -714,6 +714,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||
case 0x06c: map_key_clear(KEY_YELLOW); break;
|
||||
case 0x06d: map_key_clear(KEY_ZOOM); break;
|
||||
|
||||
case 0x06f: map_key_clear(KEY_BRIGHTNESSUP); break;
|
||||
case 0x070: map_key_clear(KEY_BRIGHTNESSDOWN); break;
|
||||
case 0x072: map_key_clear(KEY_BRIGHTNESS_TOGGLE); break;
|
||||
case 0x073: map_key_clear(KEY_BRIGHTNESS_MIN); break;
|
||||
case 0x074: map_key_clear(KEY_BRIGHTNESS_MAX); break;
|
||||
case 0x075: map_key_clear(KEY_BRIGHTNESS_AUTO); break;
|
||||
|
||||
case 0x082: map_key_clear(KEY_VIDEO_NEXT); break;
|
||||
case 0x083: map_key_clear(KEY_LAST); break;
|
||||
case 0x084: map_key_clear(KEY_ENTER); break;
|
||||
|
|
@ -754,6 +761,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||
case 0x0bf: map_key_clear(KEY_SLOW); break;
|
||||
|
||||
case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break;
|
||||
case 0x0cf: map_key_clear(KEY_VOICECOMMAND); break;
|
||||
case 0x0e0: map_abs_clear(ABS_VOLUME); break;
|
||||
case 0x0e2: map_key_clear(KEY_MUTE); break;
|
||||
case 0x0e5: map_key_clear(KEY_BASSBOOST); break;
|
||||
|
|
@ -761,6 +769,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||
case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break;
|
||||
case 0x0f5: map_key_clear(KEY_SLOW); break;
|
||||
|
||||
case 0x181: map_key_clear(KEY_BUTTONCONFIG); break;
|
||||
case 0x182: map_key_clear(KEY_BOOKMARKS); break;
|
||||
case 0x183: map_key_clear(KEY_CONFIG); break;
|
||||
case 0x184: map_key_clear(KEY_WORDPROCESSOR); break;
|
||||
|
|
@ -774,6 +783,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||
case 0x18c: map_key_clear(KEY_VOICEMAIL); break;
|
||||
case 0x18d: map_key_clear(KEY_ADDRESSBOOK); break;
|
||||
case 0x18e: map_key_clear(KEY_CALENDAR); break;
|
||||
case 0x18f: map_key_clear(KEY_TASKMANAGER); break;
|
||||
case 0x190: map_key_clear(KEY_JOURNAL); break;
|
||||
case 0x191: map_key_clear(KEY_FINANCE); break;
|
||||
case 0x192: map_key_clear(KEY_CALC); break;
|
||||
case 0x193: map_key_clear(KEY_PLAYER); break;
|
||||
|
|
@ -782,10 +793,16 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||
case 0x199: map_key_clear(KEY_CHAT); break;
|
||||
case 0x19c: map_key_clear(KEY_LOGOFF); break;
|
||||
case 0x19e: map_key_clear(KEY_COFFEE); break;
|
||||
case 0x19f: map_key_clear(KEY_CONTROLPANEL); break;
|
||||
case 0x1a2: map_key_clear(KEY_APPSELECT); break;
|
||||
case 0x1a3: map_key_clear(KEY_NEXT); break;
|
||||
case 0x1a4: map_key_clear(KEY_PREVIOUS); break;
|
||||
case 0x1a6: map_key_clear(KEY_HELP); break;
|
||||
case 0x1a7: map_key_clear(KEY_DOCUMENTS); break;
|
||||
case 0x1ab: map_key_clear(KEY_SPELLCHECK); break;
|
||||
case 0x1ae: map_key_clear(KEY_KEYBOARD); break;
|
||||
case 0x1b1: map_key_clear(KEY_SCREENSAVER); break;
|
||||
case 0x1b4: map_key_clear(KEY_FILE); break;
|
||||
case 0x1b6: map_key_clear(KEY_IMAGES); break;
|
||||
case 0x1b7: map_key_clear(KEY_AUDIO); break;
|
||||
case 0x1b8: map_key_clear(KEY_VIDEO); break;
|
||||
|
|
|
|||
|
|
@ -685,32 +685,38 @@ static const char *config_cmdline = "";
|
|||
int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
|
||||
int depth, void *data)
|
||||
{
|
||||
unsigned long l;
|
||||
char *p;
|
||||
unsigned long l = 0;
|
||||
char *p = NULL;
|
||||
char *cmdline = data;
|
||||
|
||||
pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
|
||||
|
||||
if (depth != 1 || !data ||
|
||||
if (depth != 1 || !cmdline ||
|
||||
(strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
|
||||
return 0;
|
||||
|
||||
early_init_dt_check_for_initrd(node);
|
||||
|
||||
/* Put CONFIG_CMDLINE in if forced or if data had nothing in it to start */
|
||||
if (overwrite_incoming_cmdline || !((char *)data)[0])
|
||||
strlcpy(data, config_cmdline, COMMAND_LINE_SIZE);
|
||||
if (overwrite_incoming_cmdline || !cmdline[0])
|
||||
strlcpy(cmdline, config_cmdline, COMMAND_LINE_SIZE);
|
||||
|
||||
/* Retrieve command line unless forcing */
|
||||
if (read_dt_cmdline) {
|
||||
if (read_dt_cmdline)
|
||||
p = of_get_flat_dt_prop(node, "bootargs", &l);
|
||||
if (p != NULL && l > 0) {
|
||||
if (concat_cmdline) {
|
||||
strlcat(data, " ", COMMAND_LINE_SIZE);
|
||||
strlcat(data, p, min_t(int, (int)l,
|
||||
COMMAND_LINE_SIZE));
|
||||
} else
|
||||
strlcpy(data, p, min_t(int, (int)l,
|
||||
COMMAND_LINE_SIZE));
|
||||
|
||||
if (p != NULL && l > 0) {
|
||||
if (concat_cmdline) {
|
||||
int cmdline_len;
|
||||
int copy_len;
|
||||
strlcat(cmdline, " ", COMMAND_LINE_SIZE);
|
||||
cmdline_len = strlen(cmdline);
|
||||
copy_len = COMMAND_LINE_SIZE - cmdline_len - 1;
|
||||
copy_len = min((int)l, copy_len);
|
||||
strncpy(cmdline + cmdline_len, p, copy_len);
|
||||
cmdline[cmdline_len + copy_len] = '\0';
|
||||
} else {
|
||||
strlcpy(cmdline, p, min((int)l, COMMAND_LINE_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -118,6 +118,8 @@ config SW_SYNC_USER
|
|||
|
||||
source "drivers/staging/android/ion/Kconfig"
|
||||
|
||||
source "drivers/staging/android/fiq_debugger/Kconfig"
|
||||
|
||||
endif # if ANDROID
|
||||
|
||||
endmenu
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
ccflags-y += -I$(src) # needed for trace events
|
||||
|
||||
obj-y += ion/
|
||||
obj-$(CONFIG_FIQ_DEBUGGER) += fiq_debugger/
|
||||
|
||||
obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o
|
||||
obj-$(CONFIG_ASHMEM) += ashmem.o
|
||||
|
|
|
|||
49
drivers/staging/android/fiq_debugger/Kconfig
Normal file
49
drivers/staging/android/fiq_debugger/Kconfig
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
config FIQ_DEBUGGER
|
||||
bool "FIQ Mode Serial Debugger"
|
||||
default n
|
||||
depends on ARM || ARM64
|
||||
help
|
||||
The FIQ serial debugger can accept commands even when the
|
||||
kernel is unresponsive due to being stuck with interrupts
|
||||
disabled.
|
||||
|
||||
config FIQ_DEBUGGER_NO_SLEEP
|
||||
bool "Keep serial debugger active"
|
||||
depends on FIQ_DEBUGGER
|
||||
default n
|
||||
help
|
||||
Enables the serial debugger at boot. Passing
|
||||
fiq_debugger.no_sleep on the kernel commandline will
|
||||
override this config option.
|
||||
|
||||
config FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON
|
||||
bool "Don't disable wakeup IRQ when debugger is active"
|
||||
depends on FIQ_DEBUGGER
|
||||
default n
|
||||
help
|
||||
Don't disable the wakeup irq when enabling the uart clock. This will
|
||||
cause extra interrupts, but it makes the serial debugger usable with
|
||||
on some MSM radio builds that ignore the uart clock request in power
|
||||
collapse.
|
||||
|
||||
config FIQ_DEBUGGER_CONSOLE
|
||||
bool "Console on FIQ Serial Debugger port"
|
||||
depends on FIQ_DEBUGGER
|
||||
default n
|
||||
help
|
||||
Enables a console so that printk messages are displayed on
|
||||
the debugger serial port as the occur.
|
||||
|
||||
config FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE
|
||||
bool "Put the FIQ debugger into console mode by default"
|
||||
depends on FIQ_DEBUGGER_CONSOLE
|
||||
default n
|
||||
help
|
||||
If enabled, this puts the fiq debugger into console mode by default.
|
||||
Otherwise, the fiq debugger will start out in debug mode.
|
||||
|
||||
config FIQ_WATCHDOG
|
||||
bool
|
||||
select FIQ_DEBUGGER
|
||||
select PSTORE_RAM
|
||||
default n
|
||||
4
drivers/staging/android/fiq_debugger/Makefile
Normal file
4
drivers/staging/android/fiq_debugger/Makefile
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
obj-y += fiq_debugger.o
|
||||
obj-$(CONFIG_ARM) += fiq_debugger_arm.o
|
||||
obj-$(CONFIG_ARM64) += fiq_debugger_arm64.o
|
||||
obj-$(CONFIG_FIQ_WATCHDOG) += fiq_watchdog.o
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* arch/arm/include/asm/fiq_debugger.h
|
||||
* drivers/staging/android/fiq_debugger/fiq_debugger.h
|
||||
*
|
||||
* Copyright (C) 2010 Google, Inc.
|
||||
* Author: Colin Cross <ccross@android.com>
|
||||
240
drivers/staging/android/fiq_debugger/fiq_debugger_arm.c
Normal file
240
drivers/staging/android/fiq_debugger/fiq_debugger_arm.c
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Google, Inc.
|
||||
* Author: Colin Cross <ccross@android.com>
|
||||
*
|
||||
* 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/ptrace.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <asm/stacktrace.h>
|
||||
|
||||
#include "fiq_debugger_priv.h"
|
||||
|
||||
static char *mode_name(unsigned cpsr)
|
||||
{
|
||||
switch (cpsr & MODE_MASK) {
|
||||
case USR_MODE: return "USR";
|
||||
case FIQ_MODE: return "FIQ";
|
||||
case IRQ_MODE: return "IRQ";
|
||||
case SVC_MODE: return "SVC";
|
||||
case ABT_MODE: return "ABT";
|
||||
case UND_MODE: return "UND";
|
||||
case SYSTEM_MODE: return "SYS";
|
||||
default: return "???";
|
||||
}
|
||||
}
|
||||
|
||||
void fiq_debugger_dump_pc(struct fiq_debugger_output *output,
|
||||
const struct pt_regs *regs)
|
||||
{
|
||||
output->printf(output, " pc %08x cpsr %08x mode %s\n",
|
||||
regs->ARM_pc, regs->ARM_cpsr, mode_name(regs->ARM_cpsr));
|
||||
}
|
||||
|
||||
void fiq_debugger_dump_regs(struct fiq_debugger_output *output,
|
||||
const struct pt_regs *regs)
|
||||
{
|
||||
output->printf(output,
|
||||
" r0 %08x r1 %08x r2 %08x r3 %08x\n",
|
||||
regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
|
||||
output->printf(output,
|
||||
" r4 %08x r5 %08x r6 %08x r7 %08x\n",
|
||||
regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7);
|
||||
output->printf(output,
|
||||
" r8 %08x r9 %08x r10 %08x r11 %08x mode %s\n",
|
||||
regs->ARM_r8, regs->ARM_r9, regs->ARM_r10, regs->ARM_fp,
|
||||
mode_name(regs->ARM_cpsr));
|
||||
output->printf(output,
|
||||
" ip %08x sp %08x lr %08x pc %08x cpsr %08x\n",
|
||||
regs->ARM_ip, regs->ARM_sp, regs->ARM_lr, regs->ARM_pc,
|
||||
regs->ARM_cpsr);
|
||||
}
|
||||
|
||||
struct mode_regs {
|
||||
unsigned long sp_svc;
|
||||
unsigned long lr_svc;
|
||||
unsigned long spsr_svc;
|
||||
|
||||
unsigned long sp_abt;
|
||||
unsigned long lr_abt;
|
||||
unsigned long spsr_abt;
|
||||
|
||||
unsigned long sp_und;
|
||||
unsigned long lr_und;
|
||||
unsigned long spsr_und;
|
||||
|
||||
unsigned long sp_irq;
|
||||
unsigned long lr_irq;
|
||||
unsigned long spsr_irq;
|
||||
|
||||
unsigned long r8_fiq;
|
||||
unsigned long r9_fiq;
|
||||
unsigned long r10_fiq;
|
||||
unsigned long r11_fiq;
|
||||
unsigned long r12_fiq;
|
||||
unsigned long sp_fiq;
|
||||
unsigned long lr_fiq;
|
||||
unsigned long spsr_fiq;
|
||||
};
|
||||
|
||||
static void __naked get_mode_regs(struct mode_regs *regs)
|
||||
{
|
||||
asm volatile (
|
||||
"mrs r1, cpsr\n"
|
||||
"msr cpsr_c, #0xd3 @(SVC_MODE | PSR_I_BIT | PSR_F_BIT)\n"
|
||||
"stmia r0!, {r13 - r14}\n"
|
||||
"mrs r2, spsr\n"
|
||||
"msr cpsr_c, #0xd7 @(ABT_MODE | PSR_I_BIT | PSR_F_BIT)\n"
|
||||
"stmia r0!, {r2, r13 - r14}\n"
|
||||
"mrs r2, spsr\n"
|
||||
"msr cpsr_c, #0xdb @(UND_MODE | PSR_I_BIT | PSR_F_BIT)\n"
|
||||
"stmia r0!, {r2, r13 - r14}\n"
|
||||
"mrs r2, spsr\n"
|
||||
"msr cpsr_c, #0xd2 @(IRQ_MODE | PSR_I_BIT | PSR_F_BIT)\n"
|
||||
"stmia r0!, {r2, r13 - r14}\n"
|
||||
"mrs r2, spsr\n"
|
||||
"msr cpsr_c, #0xd1 @(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)\n"
|
||||
"stmia r0!, {r2, r8 - r14}\n"
|
||||
"mrs r2, spsr\n"
|
||||
"stmia r0!, {r2}\n"
|
||||
"msr cpsr_c, r1\n"
|
||||
"bx lr\n");
|
||||
}
|
||||
|
||||
|
||||
void fiq_debugger_dump_allregs(struct fiq_debugger_output *output,
|
||||
const struct pt_regs *regs)
|
||||
{
|
||||
struct mode_regs mode_regs;
|
||||
unsigned long mode = regs->ARM_cpsr & MODE_MASK;
|
||||
|
||||
fiq_debugger_dump_regs(output, regs);
|
||||
get_mode_regs(&mode_regs);
|
||||
|
||||
output->printf(output,
|
||||
"%csvc: sp %08x lr %08x spsr %08x\n",
|
||||
mode == SVC_MODE ? '*' : ' ',
|
||||
mode_regs.sp_svc, mode_regs.lr_svc, mode_regs.spsr_svc);
|
||||
output->printf(output,
|
||||
"%cabt: sp %08x lr %08x spsr %08x\n",
|
||||
mode == ABT_MODE ? '*' : ' ',
|
||||
mode_regs.sp_abt, mode_regs.lr_abt, mode_regs.spsr_abt);
|
||||
output->printf(output,
|
||||
"%cund: sp %08x lr %08x spsr %08x\n",
|
||||
mode == UND_MODE ? '*' : ' ',
|
||||
mode_regs.sp_und, mode_regs.lr_und, mode_regs.spsr_und);
|
||||
output->printf(output,
|
||||
"%cirq: sp %08x lr %08x spsr %08x\n",
|
||||
mode == IRQ_MODE ? '*' : ' ',
|
||||
mode_regs.sp_irq, mode_regs.lr_irq, mode_regs.spsr_irq);
|
||||
output->printf(output,
|
||||
"%cfiq: r8 %08x r9 %08x r10 %08x r11 %08x r12 %08x\n",
|
||||
mode == FIQ_MODE ? '*' : ' ',
|
||||
mode_regs.r8_fiq, mode_regs.r9_fiq, mode_regs.r10_fiq,
|
||||
mode_regs.r11_fiq, mode_regs.r12_fiq);
|
||||
output->printf(output,
|
||||
" fiq: sp %08x lr %08x spsr %08x\n",
|
||||
mode_regs.sp_fiq, mode_regs.lr_fiq, mode_regs.spsr_fiq);
|
||||
}
|
||||
|
||||
struct stacktrace_state {
|
||||
struct fiq_debugger_output *output;
|
||||
unsigned int depth;
|
||||
};
|
||||
|
||||
static int report_trace(struct stackframe *frame, void *d)
|
||||
{
|
||||
struct stacktrace_state *sts = d;
|
||||
|
||||
if (sts->depth) {
|
||||
sts->output->printf(sts->output,
|
||||
" pc: %p (%pF), lr %p (%pF), sp %p, fp %p\n",
|
||||
frame->pc, frame->pc, frame->lr, frame->lr,
|
||||
frame->sp, frame->fp);
|
||||
sts->depth--;
|
||||
return 0;
|
||||
}
|
||||
sts->output->printf(sts->output, " ...\n");
|
||||
|
||||
return sts->depth == 0;
|
||||
}
|
||||
|
||||
struct frame_tail {
|
||||
struct frame_tail *fp;
|
||||
unsigned long sp;
|
||||
unsigned long lr;
|
||||
} __attribute__((packed));
|
||||
|
||||
static struct frame_tail *user_backtrace(struct fiq_debugger_output *output,
|
||||
struct frame_tail *tail)
|
||||
{
|
||||
struct frame_tail buftail[2];
|
||||
|
||||
/* Also check accessibility of one struct frame_tail beyond */
|
||||
if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) {
|
||||
output->printf(output, " invalid frame pointer %p\n",
|
||||
tail);
|
||||
return NULL;
|
||||
}
|
||||
if (__copy_from_user_inatomic(buftail, tail, sizeof(buftail))) {
|
||||
output->printf(output,
|
||||
" failed to copy frame pointer %p\n", tail);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
output->printf(output, " %p\n", buftail[0].lr);
|
||||
|
||||
/* frame pointers should strictly progress back up the stack
|
||||
* (towards higher addresses) */
|
||||
if (tail >= buftail[0].fp)
|
||||
return NULL;
|
||||
|
||||
return buftail[0].fp-1;
|
||||
}
|
||||
|
||||
void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output,
|
||||
const struct pt_regs *regs, unsigned int depth, void *ssp)
|
||||
{
|
||||
struct frame_tail *tail;
|
||||
struct thread_info *real_thread_info = THREAD_INFO(ssp);
|
||||
struct stacktrace_state sts;
|
||||
|
||||
sts.depth = depth;
|
||||
sts.output = output;
|
||||
*current_thread_info() = *real_thread_info;
|
||||
|
||||
if (!current)
|
||||
output->printf(output, "current NULL\n");
|
||||
else
|
||||
output->printf(output, "pid: %d comm: %s\n",
|
||||
current->pid, current->comm);
|
||||
fiq_debugger_dump_regs(output, regs);
|
||||
|
||||
if (!user_mode(regs)) {
|
||||
struct stackframe frame;
|
||||
frame.fp = regs->ARM_fp;
|
||||
frame.sp = regs->ARM_sp;
|
||||
frame.lr = regs->ARM_lr;
|
||||
frame.pc = regs->ARM_pc;
|
||||
output->printf(output,
|
||||
" pc: %p (%pF), lr %p (%pF), sp %p, fp %p\n",
|
||||
regs->ARM_pc, regs->ARM_pc, regs->ARM_lr, regs->ARM_lr,
|
||||
regs->ARM_sp, regs->ARM_fp);
|
||||
walk_stackframe(&frame, report_trace, &sts);
|
||||
return;
|
||||
}
|
||||
|
||||
tail = ((struct frame_tail *) regs->ARM_fp) - 1;
|
||||
while (depth-- && tail && !((unsigned long) tail & 3))
|
||||
tail = user_backtrace(output, tail);
|
||||
}
|
||||
202
drivers/staging/android/fiq_debugger/fiq_debugger_arm64.c
Normal file
202
drivers/staging/android/fiq_debugger/fiq_debugger_arm64.c
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Google, Inc.
|
||||
* Author: Colin Cross <ccross@android.com>
|
||||
*
|
||||
* 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/ptrace.h>
|
||||
#include <asm/stacktrace.h>
|
||||
|
||||
#include "fiq_debugger_priv.h"
|
||||
|
||||
static char *mode_name(const struct pt_regs *regs)
|
||||
{
|
||||
if (compat_user_mode(regs)) {
|
||||
return "USR";
|
||||
} else {
|
||||
switch (processor_mode(regs)) {
|
||||
case PSR_MODE_EL0t: return "EL0t";
|
||||
case PSR_MODE_EL1t: return "EL1t";
|
||||
case PSR_MODE_EL1h: return "EL1h";
|
||||
case PSR_MODE_EL2t: return "EL2t";
|
||||
case PSR_MODE_EL2h: return "EL2h";
|
||||
default: return "???";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fiq_debugger_dump_pc(struct fiq_debugger_output *output,
|
||||
const struct pt_regs *regs)
|
||||
{
|
||||
output->printf(output, " pc %016lx cpsr %08lx mode %s\n",
|
||||
regs->pc, regs->pstate, mode_name(regs));
|
||||
}
|
||||
|
||||
void fiq_debugger_dump_regs_aarch32(struct fiq_debugger_output *output,
|
||||
const struct pt_regs *regs)
|
||||
{
|
||||
output->printf(output, " r0 %08x r1 %08x r2 %08x r3 %08x\n",
|
||||
regs->compat_usr(0), regs->compat_usr(1),
|
||||
regs->compat_usr(2), regs->compat_usr(3));
|
||||
output->printf(output, " r4 %08x r5 %08x r6 %08x r7 %08x\n",
|
||||
regs->compat_usr(4), regs->compat_usr(5),
|
||||
regs->compat_usr(6), regs->compat_usr(7));
|
||||
output->printf(output, " r8 %08x r9 %08x r10 %08x r11 %08x\n",
|
||||
regs->compat_usr(8), regs->compat_usr(9),
|
||||
regs->compat_usr(10), regs->compat_usr(11));
|
||||
output->printf(output, " ip %08x sp %08x lr %08x pc %08x\n",
|
||||
regs->compat_usr(12), regs->compat_sp,
|
||||
regs->compat_lr, regs->pc);
|
||||
output->printf(output, " cpsr %08x (%s)\n",
|
||||
regs->pstate, mode_name(regs));
|
||||
}
|
||||
|
||||
void fiq_debugger_dump_regs_aarch64(struct fiq_debugger_output *output,
|
||||
const struct pt_regs *regs)
|
||||
{
|
||||
|
||||
output->printf(output, " x0 %016lx x1 %016lx\n",
|
||||
regs->regs[0], regs->regs[1]);
|
||||
output->printf(output, " x2 %016lx x3 %016lx\n",
|
||||
regs->regs[2], regs->regs[3]);
|
||||
output->printf(output, " x4 %016lx x5 %016lx\n",
|
||||
regs->regs[4], regs->regs[5]);
|
||||
output->printf(output, " x6 %016lx x7 %016lx\n",
|
||||
regs->regs[6], regs->regs[7]);
|
||||
output->printf(output, " x8 %016lx x9 %016lx\n",
|
||||
regs->regs[8], regs->regs[9]);
|
||||
output->printf(output, " x10 %016lx x11 %016lx\n",
|
||||
regs->regs[10], regs->regs[11]);
|
||||
output->printf(output, " x12 %016lx x13 %016lx\n",
|
||||
regs->regs[12], regs->regs[13]);
|
||||
output->printf(output, " x14 %016lx x15 %016lx\n",
|
||||
regs->regs[14], regs->regs[15]);
|
||||
output->printf(output, " x16 %016lx x17 %016lx\n",
|
||||
regs->regs[16], regs->regs[17]);
|
||||
output->printf(output, " x18 %016lx x19 %016lx\n",
|
||||
regs->regs[18], regs->regs[19]);
|
||||
output->printf(output, " x20 %016lx x21 %016lx\n",
|
||||
regs->regs[20], regs->regs[21]);
|
||||
output->printf(output, " x22 %016lx x23 %016lx\n",
|
||||
regs->regs[22], regs->regs[23]);
|
||||
output->printf(output, " x24 %016lx x25 %016lx\n",
|
||||
regs->regs[24], regs->regs[25]);
|
||||
output->printf(output, " x26 %016lx x27 %016lx\n",
|
||||
regs->regs[26], regs->regs[27]);
|
||||
output->printf(output, " x28 %016lx x29 %016lx\n",
|
||||
regs->regs[28], regs->regs[29]);
|
||||
output->printf(output, " x30 %016lx sp %016lx\n",
|
||||
regs->regs[30], regs->sp);
|
||||
output->printf(output, " pc %016lx cpsr %08x (%s)\n",
|
||||
regs->pc, regs->pstate, mode_name(regs));
|
||||
}
|
||||
|
||||
void fiq_debugger_dump_regs(struct fiq_debugger_output *output,
|
||||
const struct pt_regs *regs)
|
||||
{
|
||||
if (compat_user_mode(regs))
|
||||
fiq_debugger_dump_regs_aarch32(output, regs);
|
||||
else
|
||||
fiq_debugger_dump_regs_aarch64(output, regs);
|
||||
}
|
||||
|
||||
#define READ_SPECIAL_REG(x) ({ \
|
||||
u64 val; \
|
||||
asm volatile ("mrs %0, " # x : "=r"(val)); \
|
||||
val; \
|
||||
})
|
||||
|
||||
void fiq_debugger_dump_allregs(struct fiq_debugger_output *output,
|
||||
const struct pt_regs *regs)
|
||||
{
|
||||
u32 pstate = READ_SPECIAL_REG(CurrentEl);
|
||||
bool in_el2 = (pstate & PSR_MODE_MASK) >= PSR_MODE_EL2t;
|
||||
|
||||
fiq_debugger_dump_regs(output, regs);
|
||||
|
||||
output->printf(output, " sp_el0 %016lx\n",
|
||||
READ_SPECIAL_REG(sp_el0));
|
||||
|
||||
if (in_el2)
|
||||
output->printf(output, " sp_el1 %016lx\n",
|
||||
READ_SPECIAL_REG(sp_el1));
|
||||
|
||||
output->printf(output, " elr_el1 %016lx\n",
|
||||
READ_SPECIAL_REG(elr_el1));
|
||||
|
||||
output->printf(output, " spsr_el1 %08lx\n",
|
||||
READ_SPECIAL_REG(spsr_el1));
|
||||
|
||||
if (in_el2) {
|
||||
output->printf(output, " spsr_irq %08lx\n",
|
||||
READ_SPECIAL_REG(spsr_irq));
|
||||
output->printf(output, " spsr_abt %08lx\n",
|
||||
READ_SPECIAL_REG(spsr_abt));
|
||||
output->printf(output, " spsr_und %08lx\n",
|
||||
READ_SPECIAL_REG(spsr_und));
|
||||
output->printf(output, " spsr_fiq %08lx\n",
|
||||
READ_SPECIAL_REG(spsr_fiq));
|
||||
output->printf(output, " spsr_el2 %08lx\n",
|
||||
READ_SPECIAL_REG(elr_el2));
|
||||
output->printf(output, " spsr_el2 %08lx\n",
|
||||
READ_SPECIAL_REG(spsr_el2));
|
||||
}
|
||||
}
|
||||
|
||||
struct stacktrace_state {
|
||||
struct fiq_debugger_output *output;
|
||||
unsigned int depth;
|
||||
};
|
||||
|
||||
static int report_trace(struct stackframe *frame, void *d)
|
||||
{
|
||||
struct stacktrace_state *sts = d;
|
||||
|
||||
if (sts->depth) {
|
||||
sts->output->printf(sts->output, "%pF:\n", frame->pc);
|
||||
sts->output->printf(sts->output,
|
||||
" pc %016lx sp %016lx fp %016lx\n",
|
||||
frame->pc, frame->sp, frame->fp);
|
||||
sts->depth--;
|
||||
return 0;
|
||||
}
|
||||
sts->output->printf(sts->output, " ...\n");
|
||||
|
||||
return sts->depth == 0;
|
||||
}
|
||||
|
||||
void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output,
|
||||
const struct pt_regs *regs, unsigned int depth, void *ssp)
|
||||
{
|
||||
struct thread_info *real_thread_info = THREAD_INFO(ssp);
|
||||
struct stacktrace_state sts;
|
||||
|
||||
sts.depth = depth;
|
||||
sts.output = output;
|
||||
*current_thread_info() = *real_thread_info;
|
||||
|
||||
if (!current)
|
||||
output->printf(output, "current NULL\n");
|
||||
else
|
||||
output->printf(output, "pid: %d comm: %s\n",
|
||||
current->pid, current->comm);
|
||||
fiq_debugger_dump_regs(output, regs);
|
||||
|
||||
if (!user_mode(regs)) {
|
||||
struct stackframe frame;
|
||||
frame.fp = regs->regs[29];
|
||||
frame.sp = regs->sp;
|
||||
frame.pc = regs->pc;
|
||||
output->printf(output, "\n");
|
||||
walk_stackframe(&frame, report_trace, &sts);
|
||||
}
|
||||
}
|
||||
37
drivers/staging/android/fiq_debugger/fiq_debugger_priv.h
Normal file
37
drivers/staging/android/fiq_debugger/fiq_debugger_priv.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Google, Inc.
|
||||
* Author: Colin Cross <ccross@android.com>
|
||||
*
|
||||
* 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 _FIQ_DEBUGGER_PRIV_H_
|
||||
#define _FIQ_DEBUGGER_PRIV_H_
|
||||
|
||||
#define THREAD_INFO(sp) ((struct thread_info *) \
|
||||
((unsigned long)(sp) & ~(THREAD_SIZE - 1)))
|
||||
|
||||
struct fiq_debugger_output {
|
||||
void (*printf)(struct fiq_debugger_output *output, const char *fmt, ...);
|
||||
};
|
||||
|
||||
struct pt_regs;
|
||||
|
||||
void fiq_debugger_dump_pc(struct fiq_debugger_output *output,
|
||||
const struct pt_regs *regs);
|
||||
void fiq_debugger_dump_regs(struct fiq_debugger_output *output,
|
||||
const struct pt_regs *regs);
|
||||
void fiq_debugger_dump_allregs(struct fiq_debugger_output *output,
|
||||
const struct pt_regs *regs);
|
||||
void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output,
|
||||
const struct pt_regs *regs, unsigned int depth, void *ssp);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* arch/arm/common/fiq_debugger_ringbuf.c
|
||||
* drivers/staging/android/fiq_debugger/fiq_debugger_ringbuf.h
|
||||
*
|
||||
* simple lockless ringbuffer
|
||||
*
|
||||
56
drivers/staging/android/fiq_debugger/fiq_watchdog.c
Normal file
56
drivers/staging/android/fiq_debugger/fiq_watchdog.c
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (C) 2014 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/kernel.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/pstore_ram.h>
|
||||
|
||||
#include "fiq_watchdog.h"
|
||||
#include "fiq_debugger_priv.h"
|
||||
|
||||
static DEFINE_RAW_SPINLOCK(fiq_watchdog_lock);
|
||||
|
||||
static void fiq_watchdog_printf(struct fiq_debugger_output *output,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
char buf[256];
|
||||
va_list ap;
|
||||
int len;
|
||||
|
||||
va_start(ap, fmt);
|
||||
len = vscnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
ramoops_console_write_buf(buf, len);
|
||||
}
|
||||
|
||||
struct fiq_debugger_output fiq_watchdog_output = {
|
||||
.printf = fiq_watchdog_printf,
|
||||
};
|
||||
|
||||
void fiq_watchdog_triggered(const struct pt_regs *regs, void *svc_sp)
|
||||
{
|
||||
char msg[24];
|
||||
int len;
|
||||
|
||||
raw_spin_lock(&fiq_watchdog_lock);
|
||||
|
||||
len = scnprintf(msg, sizeof(msg), "watchdog fiq cpu %d\n",
|
||||
THREAD_INFO(svc_sp)->cpu);
|
||||
ramoops_console_write_buf(msg, len);
|
||||
|
||||
fiq_debugger_dump_stacktrace(&fiq_watchdog_output, regs, 100, svc_sp);
|
||||
|
||||
raw_spin_unlock(&fiq_watchdog_lock);
|
||||
}
|
||||
20
drivers/staging/android/fiq_debugger/fiq_watchdog.h
Normal file
20
drivers/staging/android/fiq_debugger/fiq_watchdog.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright (C) 2014 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 _FIQ_WATCHDOG_H_
|
||||
#define _FIQ_WATCHDOG_H_
|
||||
|
||||
void fiq_watchdog_triggered(const struct pt_regs *regs, void *svc_sp);
|
||||
|
||||
#endif
|
||||
|
|
@ -494,6 +494,7 @@ static void adf_obj_destroy(struct adf_obj *obj, struct idr *idr)
|
|||
struct adf_event_refcount *refcount =
|
||||
container_of(node, struct adf_event_refcount,
|
||||
node);
|
||||
rb_erase(&refcount->node, &obj->event_refcount);
|
||||
kfree(refcount);
|
||||
node = rb_first(&obj->event_refcount);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ static struct sg_table *adf_memblock_map(struct dma_buf_attachment *attach,
|
|||
unsigned long pfn = PFN_DOWN(pdata->base);
|
||||
struct page *page = pfn_to_page(pfn);
|
||||
struct sg_table *table;
|
||||
int ret;
|
||||
int nents, ret;
|
||||
|
||||
table = kzalloc(sizeof(*table), GFP_KERNEL);
|
||||
if (!table)
|
||||
|
|
@ -36,12 +36,21 @@ static struct sg_table *adf_memblock_map(struct dma_buf_attachment *attach,
|
|||
|
||||
ret = sg_alloc_table(table, 1, GFP_KERNEL);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
goto err_alloc;
|
||||
|
||||
sg_set_page(table->sgl, page, attach->dmabuf->size, 0);
|
||||
|
||||
nents = dma_map_sg(attach->dev, table->sgl, 1, direction);
|
||||
if (!nents) {
|
||||
ret = -EINVAL;
|
||||
goto err_map;
|
||||
}
|
||||
|
||||
return table;
|
||||
|
||||
err:
|
||||
err_map:
|
||||
sg_free_table(table);
|
||||
err_alloc:
|
||||
kfree(table);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
|
@ -49,6 +58,7 @@ static struct sg_table *adf_memblock_map(struct dma_buf_attachment *attach,
|
|||
static void adf_memblock_unmap(struct dma_buf_attachment *attach,
|
||||
struct sg_table *table, enum dma_data_direction direction)
|
||||
{
|
||||
dma_unmap_sg(attach->dev, table->sgl, 1, direction);
|
||||
sg_free_table(table);
|
||||
}
|
||||
|
||||
|
|
|
|||
11
fs/dcache.c
11
fs/dcache.c
|
|
@ -2724,6 +2724,17 @@ char *dynamic_dname(struct dentry *dentry, char *buffer, int buflen,
|
|||
return memcpy(buffer, temp, sz);
|
||||
}
|
||||
|
||||
char *simple_dname(struct dentry *dentry, char *buffer, int buflen)
|
||||
{
|
||||
char *end = buffer + buflen;
|
||||
/* these dentries are never renamed, so d_lock is not needed */
|
||||
if (prepend(&end, &buflen, " (deleted)", 11) ||
|
||||
prepend_name(&end, &buflen, &dentry->d_name) ||
|
||||
prepend(&end, &buflen, "/", 1))
|
||||
end = ERR_PTR(-ENAMETOOLONG);
|
||||
return end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write full pathname from the root of the filesystem into the buffer.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -916,14 +916,8 @@ static int get_hstate_idx(int page_size_log)
|
|||
return h - hstates;
|
||||
}
|
||||
|
||||
static char *hugetlb_dname(struct dentry *dentry, char *buffer, int buflen)
|
||||
{
|
||||
return dynamic_dname(dentry, buffer, buflen, "/%s (deleted)",
|
||||
dentry->d_name.name);
|
||||
}
|
||||
|
||||
static struct dentry_operations anon_ops = {
|
||||
.d_dname = hugetlb_dname
|
||||
.d_dname = simple_dname
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -377,6 +377,12 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void notrace ramoops_console_write_buf(const char *buf, size_t size)
|
||||
{
|
||||
struct ramoops_context *cxt = &oops_cxt;
|
||||
persistent_ram_write(cxt->cprz, buf, size);
|
||||
}
|
||||
|
||||
static int ramoops_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
|
|
|
|||
|
|
@ -332,6 +332,7 @@ extern int d_validate(struct dentry *, struct dentry *);
|
|||
* helper function for dentry_operations.d_dname() members
|
||||
*/
|
||||
extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
|
||||
extern char *simple_dname(struct dentry *, char *, int);
|
||||
|
||||
extern char *__d_path(const struct path *, const struct path *, char *, int);
|
||||
extern char *d_absolute_path(const struct path *, char *, int);
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ void persistent_ram_free_old(struct persistent_ram_zone *prz);
|
|||
ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz,
|
||||
char *str, size_t len);
|
||||
|
||||
void ramoops_console_write_buf(const char *buf, size_t size);
|
||||
|
||||
/*
|
||||
* Ramoops platform data
|
||||
* @mem_size memory size for ramoops
|
||||
|
|
|
|||
|
|
@ -461,10 +461,14 @@ struct input_keymap_entry {
|
|||
#define KEY_VIDEO_NEXT 241 /* drive next video source */
|
||||
#define KEY_VIDEO_PREV 242 /* drive previous video source */
|
||||
#define KEY_BRIGHTNESS_CYCLE 243 /* brightness up, after max is min */
|
||||
#define KEY_BRIGHTNESS_ZERO 244 /* brightness off, use ambient */
|
||||
#define KEY_BRIGHTNESS_AUTO 244 /* Set Auto Brightness: manual
|
||||
brightness control is off,
|
||||
rely on ambient */
|
||||
#define KEY_BRIGHTNESS_ZERO KEY_BRIGHTNESS_AUTO
|
||||
#define KEY_DISPLAY_OFF 245 /* display device to off state */
|
||||
|
||||
#define KEY_WIMAX 246
|
||||
#define KEY_WWAN 246 /* Wireless WAN (LTE, UMTS, GSM, etc.) */
|
||||
#define KEY_WIMAX KEY_WWAN
|
||||
#define KEY_RFKILL 247 /* Key that controls all radios */
|
||||
|
||||
#define KEY_MICMUTE 248 /* Mute / unmute the microphone */
|
||||
|
|
@ -509,11 +513,15 @@ struct input_keymap_entry {
|
|||
#define BTN_DEAD 0x12f
|
||||
|
||||
#define BTN_GAMEPAD 0x130
|
||||
#define BTN_A 0x130
|
||||
#define BTN_B 0x131
|
||||
#define BTN_SOUTH 0x130
|
||||
#define BTN_A BTN_SOUTH
|
||||
#define BTN_EAST 0x131
|
||||
#define BTN_B BTN_EAST
|
||||
#define BTN_C 0x132
|
||||
#define BTN_X 0x133
|
||||
#define BTN_Y 0x134
|
||||
#define BTN_NORTH 0x133
|
||||
#define BTN_X BTN_NORTH
|
||||
#define BTN_WEST 0x134
|
||||
#define BTN_Y BTN_WEST
|
||||
#define BTN_Z 0x135
|
||||
#define BTN_TL 0x136
|
||||
#define BTN_TR 0x137
|
||||
|
|
@ -626,6 +634,7 @@ struct input_keymap_entry {
|
|||
#define KEY_ADDRESSBOOK 0x1ad /* AL Contacts/Address Book */
|
||||
#define KEY_MESSENGER 0x1ae /* AL Instant Messaging */
|
||||
#define KEY_DISPLAYTOGGLE 0x1af /* Turn display (LCD) on and off */
|
||||
#define KEY_BRIGHTNESS_TOGGLE KEY_DISPLAYTOGGLE
|
||||
#define KEY_SPELLCHECK 0x1b0 /* AL Spell Check */
|
||||
#define KEY_LOGOFF 0x1b1 /* AL Logoff */
|
||||
|
||||
|
|
@ -710,6 +719,24 @@ struct input_keymap_entry {
|
|||
#define KEY_ATTENDANT_TOGGLE 0x21d /* Attendant call on or off */
|
||||
#define KEY_LIGHTS_TOGGLE 0x21e /* Reading light on or off */
|
||||
|
||||
#define BTN_DPAD_UP 0x220
|
||||
#define BTN_DPAD_DOWN 0x221
|
||||
#define BTN_DPAD_LEFT 0x222
|
||||
#define BTN_DPAD_RIGHT 0x223
|
||||
|
||||
#define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */
|
||||
|
||||
#define KEY_BUTTONCONFIG 0x240 /* AL Button Configuration */
|
||||
#define KEY_TASKMANAGER 0x241 /* AL Task/Project Manager */
|
||||
#define KEY_JOURNAL 0x242 /* AL Log/Journal/Timecard */
|
||||
#define KEY_CONTROLPANEL 0x243 /* AL Control Panel */
|
||||
#define KEY_APPSELECT 0x244 /* AL Select Task/Application */
|
||||
#define KEY_SCREENSAVER 0x245 /* AL Screen Saver */
|
||||
#define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */
|
||||
|
||||
#define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */
|
||||
#define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */
|
||||
|
||||
#define BTN_TRIGGER_HAPPY 0x2c0
|
||||
#define BTN_TRIGGER_HAPPY1 0x2c0
|
||||
#define BTN_TRIGGER_HAPPY2 0x2c1
|
||||
|
|
@ -847,6 +874,7 @@ struct input_keymap_entry {
|
|||
#define SW_FRONT_PROXIMITY 0x0b /* set = front proximity sensor active */
|
||||
#define SW_ROTATE_LOCK 0x0c /* set = rotate locked/disabled */
|
||||
#define SW_LINEIN_INSERT 0x0d /* set = inserted */
|
||||
#define SW_MUTE_DEVICE 0x0e /* set = device disabled */
|
||||
#define SW_MAX 0x0f
|
||||
#define SW_CNT (SW_MAX+1)
|
||||
|
||||
|
|
|
|||
|
|
@ -149,6 +149,12 @@
|
|||
|
||||
#define PR_GET_TID_ADDRESS 40
|
||||
|
||||
/* Sets the timerslack for arbitrary threads
|
||||
* arg2 slack value, 0 means "use default"
|
||||
* arg3 pid of the thread whose timer slack needs to be set
|
||||
*/
|
||||
#define PR_SET_TIMERSLACK_PID 41
|
||||
|
||||
#define PR_SET_VMA 0x53564d41
|
||||
# define PR_SET_VMA_ANON_NAME 0
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ struct adf_fbdev {
|
|||
u32 default_format;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_ADF_FBDEV)
|
||||
void adf_modeinfo_to_fb_videomode(const struct drm_mode_modeinfo *mode,
|
||||
struct fb_videomode *vmode);
|
||||
void adf_modeinfo_from_fb_videomode(const struct fb_videomode *vmode,
|
||||
|
|
@ -57,5 +58,67 @@ int adf_fbdev_set_par(struct fb_info *info);
|
|||
int adf_fbdev_blank(int blank, struct fb_info *info);
|
||||
int adf_fbdev_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
|
||||
int adf_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma);
|
||||
#else
|
||||
static inline void adf_modeinfo_to_fb_videomode(const struct drm_mode_modeinfo *mode,
|
||||
struct fb_videomode *vmode)
|
||||
{
|
||||
WARN_ONCE(1, "%s: CONFIG_ADF_FBDEV is disabled\n", __func__);
|
||||
}
|
||||
|
||||
static inline void adf_modeinfo_from_fb_videomode(const struct fb_videomode *vmode,
|
||||
struct drm_mode_modeinfo *mode)
|
||||
{
|
||||
WARN_ONCE(1, "%s: CONFIG_ADF_FBDEV is disabled\n", __func__);
|
||||
}
|
||||
|
||||
static inline int adf_fbdev_init(struct adf_fbdev *fbdev,
|
||||
struct adf_interface *interface,
|
||||
struct adf_overlay_engine *eng,
|
||||
u16 xres_virtual, u16 yres_virtual, u32 format,
|
||||
struct fb_ops *fbops, const char *fmt, ...)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline void adf_fbdev_destroy(struct adf_fbdev *fbdev) { }
|
||||
|
||||
static inline int adf_fbdev_open(struct fb_info *info, int user)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int adf_fbdev_release(struct fb_info *info, int user)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int adf_fbdev_check_var(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int adf_fbdev_set_par(struct fb_info *info)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int adf_fbdev_blank(int blank, struct fb_info *info)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int adf_fbdev_pan_display(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int adf_fbdev_mmap(struct fb_info *info,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _VIDEO_ADF_FBDEV_H_ */
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ static int irqcount;
|
|||
static struct kobject *wakeup_reason;
|
||||
static spinlock_t resume_reason_lock;
|
||||
|
||||
static ssize_t reason_show(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
static ssize_t last_resume_reason_show(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int irq_no, buf_offset = 0;
|
||||
|
|
@ -53,8 +53,7 @@ static ssize_t reason_show(struct kobject *kobj, struct kobj_attribute *attr,
|
|||
return buf_offset;
|
||||
}
|
||||
|
||||
static struct kobj_attribute resume_reason = __ATTR(last_resume_reason, 0666,
|
||||
reason_show, NULL);
|
||||
static struct kobj_attribute resume_reason = __ATTR_RO(last_resume_reason);
|
||||
|
||||
static struct attribute *attrs[] = {
|
||||
&resume_reason.attr,
|
||||
|
|
|
|||
19
kernel/sys.c
19
kernel/sys.c
|
|
@ -44,6 +44,7 @@
|
|||
#include <linux/ctype.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mempolicy.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <linux/compat.h>
|
||||
#include <linux/syscalls.h>
|
||||
|
|
@ -2252,6 +2253,7 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
|
|||
unsigned long, arg4, unsigned long, arg5)
|
||||
{
|
||||
struct task_struct *me = current;
|
||||
struct task_struct *tsk;
|
||||
unsigned char comm[sizeof(me->comm)];
|
||||
long error;
|
||||
|
||||
|
|
@ -2375,6 +2377,23 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
|
|||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
case PR_SET_TIMERSLACK_PID:
|
||||
rcu_read_lock();
|
||||
tsk = find_task_by_pid_ns((pid_t)arg3, &init_pid_ns);
|
||||
if (tsk == NULL) {
|
||||
rcu_read_unlock();
|
||||
return -EINVAL;
|
||||
}
|
||||
get_task_struct(tsk);
|
||||
rcu_read_unlock();
|
||||
if (arg2 <= 0)
|
||||
tsk->timer_slack_ns =
|
||||
tsk->default_timer_slack_ns;
|
||||
else
|
||||
tsk->timer_slack_ns = arg2;
|
||||
put_task_struct(tsk);
|
||||
error = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2879,14 +2879,8 @@ EXPORT_SYMBOL_GPL(shmem_truncate_range);
|
|||
|
||||
/* common code */
|
||||
|
||||
static char *shmem_dname(struct dentry *dentry, char *buffer, int buflen)
|
||||
{
|
||||
return dynamic_dname(dentry, buffer, buflen, "/%s (deleted)",
|
||||
dentry->d_name.name);
|
||||
}
|
||||
|
||||
static struct dentry_operations anon_ops = {
|
||||
.d_dname = shmem_dname
|
||||
.d_dname = simple_dname
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -249,26 +249,33 @@ int ping_init_sock(struct sock *sk)
|
|||
{
|
||||
struct net *net = sock_net(sk);
|
||||
kgid_t group = current_egid();
|
||||
struct group_info *group_info = get_current_groups();
|
||||
int i, j, count = group_info->ngroups;
|
||||
struct group_info *group_info;
|
||||
int i, j, count;
|
||||
kgid_t low, high;
|
||||
int ret = 0;
|
||||
|
||||
inet_get_ping_group_range_net(net, &low, &high);
|
||||
if (gid_lte(low, group) && gid_lte(group, high))
|
||||
return 0;
|
||||
|
||||
group_info = get_current_groups();
|
||||
count = group_info->ngroups;
|
||||
for (i = 0; i < group_info->nblocks; i++) {
|
||||
int cp_count = min_t(int, NGROUPS_PER_BLOCK, count);
|
||||
for (j = 0; j < cp_count; j++) {
|
||||
kgid_t gid = group_info->blocks[i][j];
|
||||
if (gid_lte(low, gid) && gid_lte(gid, high))
|
||||
return 0;
|
||||
goto out_release_group;
|
||||
}
|
||||
|
||||
count -= cp_count;
|
||||
}
|
||||
|
||||
return -EACCES;
|
||||
ret = -EACCES;
|
||||
|
||||
out_release_group:
|
||||
put_group_info(group_info);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ping_init_sock);
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,11 @@
|
|||
#include <linux/skbuff.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <net/net_namespace.h>
|
||||
|
||||
struct idletimer_tg_attr {
|
||||
|
|
@ -58,22 +63,65 @@ struct idletimer_tg {
|
|||
struct kobject *kobj;
|
||||
struct idletimer_tg_attr attr;
|
||||
|
||||
struct timespec delayed_timer_trigger;
|
||||
struct timespec last_modified_timer;
|
||||
struct timespec last_suspend_time;
|
||||
struct notifier_block pm_nb;
|
||||
|
||||
int timeout;
|
||||
unsigned int refcnt;
|
||||
bool work_pending;
|
||||
bool send_nl_msg;
|
||||
bool active;
|
||||
};
|
||||
|
||||
static LIST_HEAD(idletimer_tg_list);
|
||||
static DEFINE_MUTEX(list_mutex);
|
||||
static DEFINE_SPINLOCK(timestamp_lock);
|
||||
|
||||
static struct kobject *idletimer_tg_kobj;
|
||||
|
||||
static bool check_for_delayed_trigger(struct idletimer_tg *timer,
|
||||
struct timespec *ts)
|
||||
{
|
||||
bool state;
|
||||
struct timespec temp;
|
||||
spin_lock_bh(×tamp_lock);
|
||||
timer->work_pending = false;
|
||||
if ((ts->tv_sec - timer->last_modified_timer.tv_sec) > timer->timeout ||
|
||||
timer->delayed_timer_trigger.tv_sec != 0) {
|
||||
state = false;
|
||||
temp.tv_sec = timer->timeout;
|
||||
temp.tv_nsec = 0;
|
||||
if (timer->delayed_timer_trigger.tv_sec != 0) {
|
||||
temp = timespec_add(timer->delayed_timer_trigger, temp);
|
||||
ts->tv_sec = temp.tv_sec;
|
||||
ts->tv_nsec = temp.tv_nsec;
|
||||
timer->delayed_timer_trigger.tv_sec = 0;
|
||||
timer->work_pending = true;
|
||||
schedule_work(&timer->work);
|
||||
} else {
|
||||
temp = timespec_add(timer->last_modified_timer, temp);
|
||||
ts->tv_sec = temp.tv_sec;
|
||||
ts->tv_nsec = temp.tv_nsec;
|
||||
}
|
||||
} else {
|
||||
state = timer->active;
|
||||
}
|
||||
spin_unlock_bh(×tamp_lock);
|
||||
return state;
|
||||
}
|
||||
|
||||
static void notify_netlink_uevent(const char *iface, struct idletimer_tg *timer)
|
||||
{
|
||||
char iface_msg[NLMSG_MAX_SIZE];
|
||||
char state_msg[NLMSG_MAX_SIZE];
|
||||
char *envp[] = { iface_msg, state_msg, NULL };
|
||||
char timestamp_msg[NLMSG_MAX_SIZE];
|
||||
char *envp[] = { iface_msg, state_msg, timestamp_msg, NULL };
|
||||
int res;
|
||||
struct timespec ts;
|
||||
uint64_t time_ns;
|
||||
bool state;
|
||||
|
||||
res = snprintf(iface_msg, NLMSG_MAX_SIZE, "INTERFACE=%s",
|
||||
iface);
|
||||
|
|
@ -81,12 +129,24 @@ static void notify_netlink_uevent(const char *iface, struct idletimer_tg *timer)
|
|||
pr_err("message too long (%d)", res);
|
||||
return;
|
||||
}
|
||||
|
||||
get_monotonic_boottime(&ts);
|
||||
state = check_for_delayed_trigger(timer, &ts);
|
||||
res = snprintf(state_msg, NLMSG_MAX_SIZE, "STATE=%s",
|
||||
timer->active ? "active" : "inactive");
|
||||
state ? "active" : "inactive");
|
||||
|
||||
if (NLMSG_MAX_SIZE <= res) {
|
||||
pr_err("message too long (%d)", res);
|
||||
return;
|
||||
}
|
||||
|
||||
time_ns = timespec_to_ns(&ts);
|
||||
res = snprintf(timestamp_msg, NLMSG_MAX_SIZE, "TIME_NS=%llu", time_ns);
|
||||
if (NLMSG_MAX_SIZE <= res) {
|
||||
timestamp_msg[0] = '\0';
|
||||
pr_err("message too long (%d)", res);
|
||||
}
|
||||
|
||||
pr_debug("putting nlmsg: <%s> <%s>\n", iface_msg, state_msg);
|
||||
kobject_uevent_env(idletimer_tg_kobj, KOBJ_CHANGE, envp);
|
||||
return;
|
||||
|
|
@ -151,9 +211,55 @@ static void idletimer_tg_expired(unsigned long data)
|
|||
struct idletimer_tg *timer = (struct idletimer_tg *) data;
|
||||
|
||||
pr_debug("timer %s expired\n", timer->attr.attr.name);
|
||||
|
||||
spin_lock_bh(×tamp_lock);
|
||||
timer->active = false;
|
||||
timer->work_pending = true;
|
||||
schedule_work(&timer->work);
|
||||
spin_unlock_bh(×tamp_lock);
|
||||
}
|
||||
|
||||
static int idletimer_resume(struct notifier_block *notifier,
|
||||
unsigned long pm_event, void *unused)
|
||||
{
|
||||
struct timespec ts;
|
||||
unsigned long time_diff, now = jiffies;
|
||||
struct idletimer_tg *timer = container_of(notifier,
|
||||
struct idletimer_tg, pm_nb);
|
||||
if (!timer)
|
||||
return NOTIFY_DONE;
|
||||
switch (pm_event) {
|
||||
case PM_SUSPEND_PREPARE:
|
||||
get_monotonic_boottime(&timer->last_suspend_time);
|
||||
break;
|
||||
case PM_POST_SUSPEND:
|
||||
spin_lock_bh(×tamp_lock);
|
||||
if (!timer->active) {
|
||||
spin_unlock_bh(×tamp_lock);
|
||||
break;
|
||||
}
|
||||
/* since jiffies are not updated when suspended now represents
|
||||
* the time it would have suspended */
|
||||
if (time_after(timer->timer.expires, now)) {
|
||||
get_monotonic_boottime(&ts);
|
||||
ts = timespec_sub(ts, timer->last_suspend_time);
|
||||
time_diff = timespec_to_jiffies(&ts);
|
||||
if (timer->timer.expires > (time_diff + now)) {
|
||||
mod_timer_pending(&timer->timer,
|
||||
(timer->timer.expires - time_diff));
|
||||
} else {
|
||||
del_timer(&timer->timer);
|
||||
timer->timer.expires = 0;
|
||||
timer->active = false;
|
||||
timer->work_pending = true;
|
||||
schedule_work(&timer->work);
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(×tamp_lock);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static int idletimer_tg_create(struct idletimer_tg_info *info)
|
||||
|
|
@ -187,6 +293,18 @@ static int idletimer_tg_create(struct idletimer_tg_info *info)
|
|||
info->timer->refcnt = 1;
|
||||
info->timer->send_nl_msg = (info->send_nl_msg == 0) ? false : true;
|
||||
info->timer->active = true;
|
||||
info->timer->timeout = info->timeout;
|
||||
|
||||
info->timer->delayed_timer_trigger.tv_sec = 0;
|
||||
info->timer->delayed_timer_trigger.tv_nsec = 0;
|
||||
info->timer->work_pending = false;
|
||||
get_monotonic_boottime(&info->timer->last_modified_timer);
|
||||
|
||||
info->timer->pm_nb.notifier_call = idletimer_resume;
|
||||
ret = register_pm_notifier(&info->timer->pm_nb);
|
||||
if (ret)
|
||||
printk(KERN_WARNING "[%s] Failed to register pm notifier %d\n",
|
||||
__func__, ret);
|
||||
|
||||
mod_timer(&info->timer->timer,
|
||||
msecs_to_jiffies(info->timeout * 1000) + jiffies);
|
||||
|
|
@ -203,6 +321,34 @@ static int idletimer_tg_create(struct idletimer_tg_info *info)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void reset_timer(const struct idletimer_tg_info *info)
|
||||
{
|
||||
unsigned long now = jiffies;
|
||||
struct idletimer_tg *timer = info->timer;
|
||||
bool timer_prev;
|
||||
|
||||
spin_lock_bh(×tamp_lock);
|
||||
timer_prev = timer->active;
|
||||
timer->active = true;
|
||||
/* timer_prev is used to guard overflow problem in time_before*/
|
||||
if (!timer_prev || time_before(timer->timer.expires, now)) {
|
||||
pr_debug("Starting Checkentry timer (Expired, Jiffies): %lu, %lu\n",
|
||||
timer->timer.expires, now);
|
||||
/* checks if there is a pending inactive notification*/
|
||||
if (timer->work_pending)
|
||||
timer->delayed_timer_trigger = timer->last_modified_timer;
|
||||
else {
|
||||
timer->work_pending = true;
|
||||
schedule_work(&timer->work);
|
||||
}
|
||||
}
|
||||
|
||||
get_monotonic_boottime(&timer->last_modified_timer);
|
||||
mod_timer(&timer->timer,
|
||||
msecs_to_jiffies(info->timeout * 1000) + now);
|
||||
spin_unlock_bh(×tamp_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* The actual xt_tables plugin.
|
||||
*/
|
||||
|
|
@ -226,9 +372,7 @@ static unsigned int idletimer_tg_target(struct sk_buff *skb,
|
|||
}
|
||||
|
||||
/* TODO: Avoid modifying timers on each packet */
|
||||
mod_timer(&info->timer->timer,
|
||||
msecs_to_jiffies(info->timeout * 1000) + now);
|
||||
|
||||
reset_timer(info);
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
|
|
@ -236,7 +380,6 @@ static int idletimer_tg_checkentry(const struct xt_tgchk_param *par)
|
|||
{
|
||||
struct idletimer_tg_info *info = par->targinfo;
|
||||
int ret;
|
||||
unsigned long now = jiffies;
|
||||
|
||||
pr_debug("checkentry targinfo %s\n", info->label);
|
||||
|
||||
|
|
@ -257,17 +400,7 @@ static int idletimer_tg_checkentry(const struct xt_tgchk_param *par)
|
|||
info->timer = __idletimer_tg_find_by_label(info->label);
|
||||
if (info->timer) {
|
||||
info->timer->refcnt++;
|
||||
info->timer->active = true;
|
||||
|
||||
if (time_before(info->timer->timer.expires, now)) {
|
||||
schedule_work(&info->timer->work);
|
||||
pr_debug("Starting Checkentry timer (Expired, Jiffies): %lu, %lu\n",
|
||||
info->timer->timer.expires, now);
|
||||
}
|
||||
|
||||
mod_timer(&info->timer->timer,
|
||||
msecs_to_jiffies(info->timeout * 1000) + now);
|
||||
|
||||
reset_timer(info);
|
||||
pr_debug("increased refcnt of timer %s to %u\n",
|
||||
info->label, info->timer->refcnt);
|
||||
} else {
|
||||
|
|
@ -298,6 +431,7 @@ static void idletimer_tg_destroy(const struct xt_tgdtor_param *par)
|
|||
list_del(&info->timer->entry);
|
||||
del_timer_sync(&info->timer->timer);
|
||||
sysfs_remove_file(idletimer_tg_kobj, &info->timer->attr.attr);
|
||||
unregister_pm_notifier(&info->timer->pm_nb);
|
||||
kfree(info->timer->attr.attr.name);
|
||||
kfree(info->timer);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -444,11 +444,15 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
|
|||
avc_dump_query(ab, ad->selinux_audit_data->ssid,
|
||||
ad->selinux_audit_data->tsid,
|
||||
ad->selinux_audit_data->tclass);
|
||||
if (ad->selinux_audit_data->denied) {
|
||||
audit_log_format(ab, " permissive=%u",
|
||||
ad->selinux_audit_data->result ? 0 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the slow part of avc audit with big stack footprint */
|
||||
noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
|
||||
u32 requested, u32 audited, u32 denied,
|
||||
u32 requested, u32 audited, u32 denied, int result,
|
||||
struct common_audit_data *a,
|
||||
unsigned flags)
|
||||
{
|
||||
|
|
@ -477,6 +481,7 @@ noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
|
|||
sad.tsid = tsid;
|
||||
sad.audited = audited;
|
||||
sad.denied = denied;
|
||||
sad.result = result;
|
||||
|
||||
a->selinux_audit_data = &sad;
|
||||
|
||||
|
|
|
|||
|
|
@ -2714,6 +2714,7 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na
|
|||
|
||||
static noinline int audit_inode_permission(struct inode *inode,
|
||||
u32 perms, u32 audited, u32 denied,
|
||||
int result,
|
||||
unsigned flags)
|
||||
{
|
||||
struct common_audit_data ad;
|
||||
|
|
@ -2724,7 +2725,7 @@ static noinline int audit_inode_permission(struct inode *inode,
|
|||
ad.u.inode = inode;
|
||||
|
||||
rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
|
||||
audited, denied, &ad, flags);
|
||||
audited, denied, result, &ad, flags);
|
||||
if (rc)
|
||||
return rc;
|
||||
return 0;
|
||||
|
|
@ -2766,7 +2767,7 @@ static int selinux_inode_permission(struct inode *inode, int mask)
|
|||
if (likely(!audited))
|
||||
return rc;
|
||||
|
||||
rc2 = audit_inode_permission(inode, perms, audited, denied, flags);
|
||||
rc2 = audit_inode_permission(inode, perms, audited, denied, rc, flags);
|
||||
if (rc2)
|
||||
return rc2;
|
||||
return rc;
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ static inline u32 avc_audit_required(u32 requested,
|
|||
}
|
||||
|
||||
int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
|
||||
u32 requested, u32 audited, u32 denied,
|
||||
u32 requested, u32 audited, u32 denied, int result,
|
||||
struct common_audit_data *a,
|
||||
unsigned flags);
|
||||
|
||||
|
|
@ -137,7 +137,7 @@ static inline int avc_audit(u32 ssid, u32 tsid,
|
|||
if (likely(!audited))
|
||||
return 0;
|
||||
return slow_avc_audit(ssid, tsid, tclass,
|
||||
requested, audited, denied,
|
||||
requested, audited, denied, result,
|
||||
a, flags);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user