diff options
| -rw-r--r-- | arch/arm/Kconfig | 26 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/head.S | 96 | ||||
| -rw-r--r-- | arch/arm/configs/aokp_mako_defconfig | 4 | ||||
| -rw-r--r-- | arch/arm/configs/mako_defconfig | 4 | ||||
| -rw-r--r-- | arch/arm/include/asm/kexec.h | 8 | ||||
| -rw-r--r-- | arch/arm/kernel/atags.c | 51 | ||||
| -rw-r--r-- | arch/arm/kernel/machine_kexec.c | 22 | ||||
| -rw-r--r-- | arch/arm/kernel/relocate_kernel.S | 55 | ||||
| -rw-r--r-- | arch/arm/mach-msm/include/mach/memory.h | 10 | ||||
| -rw-r--r-- | arch/arm/mach-msm/lge/devices_lge.c | 15 | ||||
| -rw-r--r-- | arch/arm/mach-msm/restart.c | 16 | ||||
| -rw-r--r-- | drivers/usb/otg/msm_otg.c | 64 | ||||
| -rw-r--r-- | include/linux/kexec.h | 19 | ||||
| -rw-r--r-- | kernel/kexec.c | 4 |
14 files changed, 348 insertions, 46 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a6e0a129d04..349d10b5e9a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -2191,6 +2191,32 @@ config ATAGS_PROC Should the atags used to boot the kernel be exported in an "atags" file in procfs. Useful with kexec. +config KEXEC_HARDBOOT + bool "Support hard booting to a kexec kernel" + depends on KEXEC + help + Allows hard booting (i.e., with a full hardware reboot) to a kernel + previously loaded in memory by kexec. This works around the problem of + soft-booted kernel hangs due to improper device shutdown and/or + reinitialization. Support is comprised of two components: + + First, a "hardboot" flag is added to the kexec syscall to force a hard + reboot in relocate_new_kernel() (which requires machine-specific assembly + code). This also requires the kexec userspace tool to load the kexec'd + kernel in memory region left untouched by the bootloader (i.e., not + explicitly cleared and not overwritten by the boot kernel). Just prior + to reboot, the kexec kernel arguments are stashed in a machine-specific + memory page that must also be preserved. Note that this hardboot page + need not be reserved during regular kernel execution. + + Second, the zImage decompresor of the boot (bootloader-loaded) kernel is + modified to check the hardboot page for fresh kexec arguments, and if + present, attempts to jump to the kexec'd kernel preserved in memory. + + Note that hardboot support is only required in the boot kernel and any + kernel capable of performing a hardboot kexec. It is _not_ required by a + kexec'd kernel. + config CRASH_DUMP bool "Build kdump crash kernel (EXPERIMENTAL)" depends on EXPERIMENTAL diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index e0a139d489c..ab3b19bb5a8 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -10,6 +10,11 @@ */ #include <linux/linkage.h> +#ifdef CONFIG_KEXEC_HARDBOOT + #include <asm/kexec.h> + #include <asm/memory.h> +#endif + /* * Debugging stuff * @@ -135,6 +140,97 @@ start: 1: mov r7, r1 @ save architecture ID mov r8, r2 @ save atags pointer +#ifdef CONFIG_KEXEC_HARDBOOT + /* Check hardboot page for a kexec kernel. */ + ldr r3, =KEXEC_HB_PAGE_ADDR + ldr r0, [r3] + ldr r1, =KEXEC_HB_PAGE_MAGIC + teq r0, r1 + bne not_booting_other + + /* Clear hardboot page magic to avoid boot loop. */ + mov r0, #0 + str r0, [r3] + +/* Copy the kernel tagged list (atags): + * + * The kernel requires atags to be located in a direct-mapped region, + * usually below the kernel in the first 16 kB of RAM. If they're above + * (the start of) the kernel, they need to be copied to a suitable + * location, e.g., the machine-defined params_phys. + * + * The assumption is that the tags will only be "out of place" if the + * decompressor code is also, so copying is implemented only in the "won't + * overwrite" case (which should be fixed). Still need to make sure that + * the copied tags don't overwrite either the kernel or decompressor code + * (or rather, the remainder of it since everything up to here has already + * been executed). + * + * Vojtech Bocek <vbocek@gmail.com>: I've moved atags copying from guest + * kernel to the host and rewrote it from C to assembler in order to remove + * the need for guest kernel to be patched. I don't know assembler very well, + * so it doesn't look very good and I have no idea if I didn't accidentally + * break something, causing problems down the road. It's worked every time + * and I didn't notice any problems so far though. + * + * r4: zreladdr (kernel start) + * r8: kexec_boot_atags + * r2: boot_atags */ + ldr r8, [r3, #12] @ kexec_boot_atags (r2: boot_atags) + ldr r4, =zreladdr @ zreladdr + + /* No need to copy atags if they're already below kernel */ + cmp r8, r4 + blo no_atags_cpy + + /* r0: min(zreladdr, pc) */ + mov r0, pc + cmp r4, r0 + movlo r0, r4 + + /* Compute max space for atags, if max <= 0 don't copy. */ + subs r5, r0, r2 @ max = min(zreladdr, pc) - dest + bls no_atags_cpy + + /* Copy atags to params_phys. */ + /* r8 src, r2 dest, r5 max */ + + ldr r0, [r8] @ first tag size + cmp r0, #0 + moveq r4, #8 + beq catags_empty + mov r4, r8 + +catags_foreach: + lsl r0, r0, #2 @ Multiply by 4 + ldr r0, [r4, r0]! @ Load next tag size to r0 and address to r4 + cmp r0, #0 + bne catags_foreach + + rsb r4, r8, r4 @ r4 -= r8 (get only size) + add r4, r4, #8 @ add size of the last tag +catags_empty: + cmp r5, r4 @ if(max <= size) + bcc no_atags_cpy + + mov r5, #0 @ iterator +catags_cpy: + ldr r0, [r8, r5] + str r0, [r2, r5] + add r5, r5, #4 + cmp r5, r4 + blo catags_cpy + +no_atags_cpy: + /* Load boot arguments and jump to kexec kernel. */ + ldr r1, [r3, #8] @ kexec_mach_type + ldr pc, [r3, #4] @ kexec_start_address + + .ltorg + +not_booting_other: +#endif + #ifndef __ARM_ARCH_2__ /* * Booting from Angel - need to enter SVC mode and disable diff --git a/arch/arm/configs/aokp_mako_defconfig b/arch/arm/configs/aokp_mako_defconfig index f66913cd4b8..182ee1108a9 100644 --- a/arch/arm/configs/aokp_mako_defconfig +++ b/arch/arm/configs/aokp_mako_defconfig @@ -512,3 +512,7 @@ CONFIG_SECURITY_NETWORK=y CONFIG_LSM_MMAP_MIN_ADDR=4096 CONFIG_SECURITY_SELINUX=y CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_KEXEC=y +CONFIG_KEXEC_HARDBOOT=y +CONFIG_ATAGS_PROC=y +CONFIG_PROC_DEVICETREE=y
\ No newline at end of file diff --git a/arch/arm/configs/mako_defconfig b/arch/arm/configs/mako_defconfig index 061020c00a9..521379f67a8 100644 --- a/arch/arm/configs/mako_defconfig +++ b/arch/arm/configs/mako_defconfig @@ -504,3 +504,7 @@ CONFIG_SECURITY_SELINUX=y CONFIG_CRYPTO_TWOFISH=y # CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set +CONFIG_KEXEC=y +CONFIG_KEXEC_HARDBOOT=y +CONFIG_ATAGS_PROC=y +CONFIG_PROC_DEVICETREE=y diff --git a/arch/arm/include/asm/kexec.h b/arch/arm/include/asm/kexec.h index c2b9b4bdec0..564c55b394e 100644 --- a/arch/arm/include/asm/kexec.h +++ b/arch/arm/include/asm/kexec.h @@ -17,6 +17,10 @@ #define KEXEC_ARM_ATAGS_OFFSET 0x1000 #define KEXEC_ARM_ZIMAGE_OFFSET 0x8000 +#ifdef CONFIG_KEXEC_HARDBOOT + #define KEXEC_HB_PAGE_MAGIC 0x4a5db007 +#endif + #ifndef __ASSEMBLY__ /** @@ -53,6 +57,10 @@ static inline void crash_setup_regs(struct pt_regs *newregs, /* Function pointer to optional machine-specific reinitialization */ extern void (*kexec_reinit)(void); +#ifdef CONFIG_KEXEC_HARDBOOT +extern void (*kexec_hardboot_hook)(void); +#endif + #endif /* __ASSEMBLY__ */ #endif /* CONFIG_KEXEC */ diff --git a/arch/arm/kernel/atags.c b/arch/arm/kernel/atags.c index 42a1a1415fa..0cfd7e48038 100644 --- a/arch/arm/kernel/atags.c +++ b/arch/arm/kernel/atags.c @@ -4,29 +4,45 @@ #include <asm/types.h> #include <asm/page.h> +/* + * [PATCH] Backport arch/arm/kernel/atags.c from 3.10 + * + * There is a bug in older kernels, causing kexec-tools binary to + * only read first 1024 bytes from /proc/atags. I guess the bug is + * somewhere in /fs/proc/, since I don't think the callback in atags.c + * does something wrong. It might affect all procfs files using that + * old read callback instead of fops. Doesn't matter though, since it + * was accidentally fixed when 3.10 removed it. + * + * This might have no particular effect on real devices, because the + * atags _might_ be organized "just right", but it might be very hard + * to track down on a device where it causes problems. + * + */ + struct buffer { size_t size; char data[]; }; -static int -read_buffer(char* page, char** start, off_t off, int count, - int* eof, void* data) -{ - struct buffer *buffer = (struct buffer *)data; - - if (off >= buffer->size) { - *eof = 1; - return 0; - } - - count = min((int) (buffer->size - off), count); +static struct buffer* atags_buffer = NULL; - memcpy(page, &buffer->data[off], count); - - return count; +static ssize_t atags_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + // These are introduced in kernel 3.10. I don't want to backport + // the whole chunk, and other things (ram_console) use static + // variable to keep data too, so I guess it's okay. + //struct buffer *b = PDE_DATA(file_inode(file)); + struct buffer *b = atags_buffer; + return simple_read_from_buffer(buf, count, ppos, b->data, b->size); } +static const struct file_operations atags_fops = { + .read = atags_read, + .llseek = default_llseek, +}; + #define BOOT_PARAMS_SIZE 1536 static char __initdata atags_copy[BOOT_PARAMS_SIZE]; @@ -66,12 +82,13 @@ static int __init init_atags_procfs(void) b->size = size; memcpy(b->data, atags_copy, size); - tags_entry = create_proc_read_entry("atags", 0400, - NULL, read_buffer, b); + tags_entry = proc_create_data("atags", 0400, NULL, &atags_fops, b); if (!tags_entry) goto nomem; + atags_buffer = b; + return 0; nomem: diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index c355aebdf2d..449394d81fb 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -14,6 +14,7 @@ #include <asm/cacheflush.h> #include <asm/mach-types.h> #include <asm/system_misc.h> +#include <asm/mmu_writeable.h> extern const unsigned char relocate_new_kernel[]; extern const unsigned int relocate_new_kernel_size; @@ -22,6 +23,10 @@ extern unsigned long kexec_start_address; extern unsigned long kexec_indirection_page; extern unsigned long kexec_mach_type; extern unsigned long kexec_boot_atags; +#ifdef CONFIG_KEXEC_HARDBOOT +extern unsigned long kexec_hardboot; +void (*kexec_hardboot_hook)(void); +#endif static atomic_t waiting_for_crash_ipi; @@ -120,10 +125,13 @@ void machine_kexec(struct kimage *image) reboot_code_buffer = page_address(image->control_code_page); /* Prepare parameters for reboot_code_buffer*/ - kexec_start_address = image->start; - kexec_indirection_page = page_list; - kexec_mach_type = machine_arch_type; - kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; + mem_text_write_kernel_word(&kexec_start_address, image->start); + mem_text_write_kernel_word(&kexec_indirection_page, page_list); + mem_text_write_kernel_word(&kexec_mach_type, machine_arch_type); + mem_text_write_kernel_word(&kexec_boot_atags, image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET); +#ifdef CONFIG_KEXEC_HARDBOOT + mem_text_write_kernel_word(&kexec_hardboot, image->hardboot); +#endif /* copy our kernel relocation code to the control code page */ memcpy(reboot_code_buffer, @@ -137,5 +145,11 @@ void machine_kexec(struct kimage *image) if (kexec_reinit) kexec_reinit(); +#ifdef CONFIG_KEXEC_HARDBOOT + /* Run any final machine-specific shutdown code. */ + if (image->hardboot && kexec_hardboot_hook) + kexec_hardboot_hook(); +#endif + soft_restart(reboot_code_buffer_phys); } diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S index d0cdedf4864..f5342939d95 100644 --- a/arch/arm/kernel/relocate_kernel.S +++ b/arch/arm/kernel/relocate_kernel.S @@ -4,6 +4,15 @@ #include <asm/kexec.h> +#ifdef CONFIG_KEXEC_HARDBOOT +#include <asm/memory.h> +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC) + #include <mach/iomap.h> +#elif defined(CONFIG_ARCH_APQ8064) + #include <mach/msm_iomap.h> +#endif +#endif + .globl relocate_new_kernel relocate_new_kernel: @@ -52,6 +61,12 @@ relocate_new_kernel: b 0b 2: +#ifdef CONFIG_KEXEC_HARDBOOT + ldr r0, kexec_hardboot + teq r0, #0 + bne hardboot +#endif + /* Jump to relocated kernel */ mov lr,r1 mov r0,#0 @@ -60,6 +75,40 @@ relocate_new_kernel: ARM( mov pc, lr ) THUMB( bx lr ) +#ifdef CONFIG_KEXEC_HARDBOOT +hardboot: + /* Stash boot arguments in hardboot page: + * 0: KEXEC_HB_PAGE_MAGIC + * 4: kexec_start_address + * 8: kexec_mach_type + * 12: kexec_boot_atags */ + ldr r0, =KEXEC_HB_PAGE_ADDR + str r1, [r0, #4] + ldr r1, kexec_mach_type + str r1, [r0, #8] + ldr r1, kexec_boot_atags + str r1, [r0, #12] + ldr r1, =KEXEC_HB_PAGE_MAGIC + str r1, [r0] + +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC) + ldr r0, =TEGRA_PMC_BASE + ldr r1, [r0] + orr r1, r1, #0x10 + str r1, [r0] +loop: b loop +#elif defined(CONFIG_ARCH_APQ8064) + /* Restart using the PMIC chip, see mach-msm/restart.c */ + ldr r0, =APQ8064_TLMM_PHYS + mov r1, #0 + str r1, [r0, #0x820] @ PSHOLD_CTL_SU +loop: b loop +#else +#error "No reboot method defined for hardboot." +#endif + + .ltorg +#endif .align .globl kexec_start_address @@ -79,6 +128,12 @@ kexec_mach_type: kexec_boot_atags: .long 0x0 +#ifdef CONFIG_KEXEC_HARDBOOT + .globl kexec_hardboot +kexec_hardboot: + .long 0x0 +#endif + relocate_new_kernel_end: .globl relocate_new_kernel_size diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h index 83296117c70..d9f6b78b01d 100644 --- a/arch/arm/mach-msm/include/mach/memory.h +++ b/arch/arm/mach-msm/include/mach/memory.h @@ -20,6 +20,16 @@ /* physical offset of RAM */ #define PLAT_PHYS_OFFSET UL(CONFIG_PHYS_OFFSET) +#if defined(CONFIG_KEXEC_HARDBOOT) +#if defined(CONFIG_MACH_APQ8064_FLO) +#define KEXEC_HB_PAGE_ADDR UL(0x88C00000) +#elif defined(CONFIG_MACH_APQ8064_MAKO) +#define KEXEC_HB_PAGE_ADDR UL(0x88600000) +#else +#error "Adress for kexec hardboot page not defined" +#endif +#endif + #define MAX_PHYSMEM_BITS 32 #define SECTION_SIZE_BITS 28 diff --git a/arch/arm/mach-msm/lge/devices_lge.c b/arch/arm/mach-msm/lge/devices_lge.c index 504cc1ebe4a..f74e4e793c2 100644 --- a/arch/arm/mach-msm/lge/devices_lge.c +++ b/arch/arm/mach-msm/lge/devices_lge.c @@ -26,6 +26,10 @@ #include <ram_console.h> +#ifdef CONFIG_KEXEC_HARDBOOT +#include <linux/memblock.h> +#endif + /* setting whether uart console is enalbed or disabled */ static int uart_console_mode = 0; @@ -187,6 +191,17 @@ void __init lge_add_persistent_ram(void) void __init lge_reserve(void) { +#ifdef CONFIG_KEXEC_HARDBOOT + // Reserve space for hardboot page, just before the ram_console + struct membank* bank = &meminfo.bank[0]; + phys_addr_t start = bank->start + bank->size - SZ_1M - LGE_PERSISTENT_RAM_SIZE; + int ret = memblock_remove(start, SZ_1M); + if(!ret) + pr_info("Hardboot page reserved at 0x%X\n", start); + else + pr_err("Failed to reserve space for hardboot page at 0x%X!\n", start); +#endif + lge_add_persistent_ram(); } diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c index 8fac40c7586..74ef77a2103 100644 --- a/arch/arm/mach-msm/restart.c +++ b/arch/arm/mach-msm/restart.c @@ -35,6 +35,10 @@ #include "msm_watchdog.h" #include "timer.h" +#ifdef CONFIG_KEXEC_HARDBOOT +#include <asm/kexec.h> +#endif + #define WDT0_RST 0x38 #define WDT0_EN 0x40 #define WDT0_BARK_TIME 0x4C @@ -322,6 +326,14 @@ static int __init msm_pmic_restart_init(void) late_initcall(msm_pmic_restart_init); +#ifdef CONFIG_KEXEC_HARDBOOT +static void msm_kexec_hardboot_hook(void) +{ + // Set PMIC to restart-on-poweroff + pm8xxx_reset_pwr_off(1); +} +#endif + static int __init msm_restart_init(void) { #ifdef CONFIG_MSM_DLOAD_MODE @@ -337,6 +349,10 @@ static int __init msm_restart_init(void) restart_reason = MSM_IMEM_BASE + RESTART_REASON_ADDR; pm_power_off = msm_power_off; +#ifdef CONFIG_KEXEC_HARDBOOT + kexec_hardboot_hook = msm_kexec_hardboot_hook; +#endif + return 0; } early_initcall(msm_restart_init); diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c index 50d2209753e..ac8639df511 100644 --- a/drivers/usb/otg/msm_otg.c +++ b/drivers/usb/otg/msm_otg.c @@ -1133,7 +1133,8 @@ static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA) if (g && g->is_a_peripheral) return; - if ((motg->chg_type == USB_ACA_DOCK_CHARGER || + // charge limit should not be imposed for dock charger -ziddey + if ((//motg->chg_type == USB_ACA_DOCK_CHARGER || motg->chg_type == USB_ACA_A_CHARGER || motg->chg_type == USB_ACA_B_CHARGER || motg->chg_type == USB_ACA_C_CHARGER) && @@ -1232,9 +1233,12 @@ static int msm_otg_usbdev_notify(struct notifier_block *self, * ACA dock can supply IDEV_CHG irrespective devices connected * on the accessory port. */ - if (!udev->parent || udev->parent->parent || + + // do not cause required code to be skipped -ziddey + // will not switch to a_host or charge otherwise + /*if (!udev->parent || udev->parent->parent || motg->chg_type == USB_ACA_DOCK_CHARGER) - goto out; + goto out;*/ switch (action) { case USB_DEVICE_ADD: @@ -2154,8 +2158,13 @@ static void msm_chg_detect_work(struct work_struct *w) break; } - if (line_state) /* DP > VLGC or/and DM > VLGC */ - motg->chg_type = USB_PROPRIETARY_CHARGER; + if (line_state) /* DP > VLGC or/and DM > VLGC */ { + // simulate ID_A to force host mode with charging -ziddey + pr_info("*** FORCING USB HOST MODE WITH CHARGING ***\n"); + set_bit(ID_A, &motg->inputs); + motg->chg_type = USB_ACA_DOCK_CHARGER; + //motg->chg_type = USB_PROPRIETARY_CHARGER; + } else motg->chg_type = USB_SDP_CHARGER; @@ -3011,11 +3020,13 @@ static void msm_otg_set_vbus_state(int online) { static bool init; struct msm_otg *motg = the_msm_otg; - struct usb_otg *otg = motg->phy.otg; + + // need BSV interrupt in A Host Mode to detect cable unplug -ziddey + //struct usb_otg *otg = motg->phy.otg; /* In A Host Mode, ignore received BSV interrupts */ - if (otg->phy->state >= OTG_STATE_A_IDLE) - return; + /*if (otg->phy->state >= OTG_STATE_A_IDLE) + return;*/ if (online) { pr_debug("PMIC: BSV set\n"); @@ -3023,6 +3034,10 @@ static void msm_otg_set_vbus_state(int online) } else { pr_debug("PMIC: BSV clear\n"); clear_bit(B_SESS_VLD, &motg->inputs); + + // disable host mode (if enabled) -ziddey + if (test_and_clear_bit(ID_A, &motg->inputs)) + pr_info("*** UNFORCING USB HOST MODE ***\n"); } if (!init) { @@ -3144,39 +3159,43 @@ static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf, goto out; } + // always force req_mode, and use ID_A instead of ID for host mode -ziddey switch (req_mode) { case USB_NONE: - switch (phy->state) { + /*switch (phy->state) { case OTG_STATE_A_HOST: case OTG_STATE_B_PERIPHERAL: - set_bit(ID, &motg->inputs); + set_bit(ID, &motg->inputs);*/ + clear_bit(ID_A, &motg->inputs); clear_bit(B_SESS_VLD, &motg->inputs); break; - default: + /*default: goto out; } - break; + break;*/ case USB_PERIPHERAL: - switch (phy->state) { + /*switch (phy->state) { case OTG_STATE_B_IDLE: case OTG_STATE_A_HOST: - set_bit(ID, &motg->inputs); + set_bit(ID, &motg->inputs);*/ + clear_bit(ID_A, &motg->inputs); set_bit(B_SESS_VLD, &motg->inputs); break; - default: + /*default: goto out; } - break; + break;*/ case USB_HOST: - switch (phy->state) { + /*switch (phy->state) { case OTG_STATE_B_IDLE: case OTG_STATE_B_PERIPHERAL: - clear_bit(ID, &motg->inputs); + clear_bit(ID, &motg->inputs);*/ + set_bit(ID_A, &motg->inputs); break; - default: + /*default: goto out; } - break; + break;*/ default: goto out; } @@ -3341,8 +3360,9 @@ static int msm_otg_debugfs_init(struct msm_otg *motg) if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root)) return -ENODEV; - if (motg->pdata->mode == USB_OTG && - motg->pdata->otg_control == OTG_USER_CONTROL) { + // enable /sys/kernel/debug/msm_otg/host -ziddey + if (motg->pdata->mode == USB_OTG /*&& + motg->pdata->otg_control == OTG_USER_CONTROL*/) { msm_otg_dentry = debugfs_create_file("mode", S_IRUGO | S_IWUSR, msm_otg_dbg_root, motg, diff --git a/include/linux/kexec.h b/include/linux/kexec.h index af84a25ef6b..a4509adc86a 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -111,6 +111,10 @@ struct kimage { #define KEXEC_TYPE_CRASH 1 unsigned int preserve_context : 1; +#ifdef CONFIG_KEXEC_HARDBOOT + unsigned int hardboot : 1; +#endif + #ifdef ARCH_HAS_KIMAGE_ARCH struct kimage_arch arch; #endif @@ -178,6 +182,11 @@ extern struct kimage *kexec_crash_image; #define KEXEC_ON_CRASH 0x00000001 #define KEXEC_PRESERVE_CONTEXT 0x00000002 + +#ifdef CONFIG_KEXEC_HARDBOOT +#define KEXEC_HARDBOOT 0x00000004 +#endif + #define KEXEC_ARCH_MASK 0xffff0000 /* These values match the ELF architecture values. @@ -196,10 +205,14 @@ extern struct kimage *kexec_crash_image; #define KEXEC_ARCH_MIPS ( 8 << 16) /* List of defined/legal kexec flags */ -#ifndef CONFIG_KEXEC_JUMP -#define KEXEC_FLAGS KEXEC_ON_CRASH -#else +#if defined(CONFIG_KEXEC_JUMP) && defined(CONFIG_KEXEC_HARDBOOT) +#define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT | KEXEC_HARDBOOT) +#elif defined(CONFIG_KEXEC_JUMP) #define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT) +#elif defined(CONFIG_KEXEC_HARDBOOT) +#define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_HARDBOOT) +#else +#define KEXEC_FLAGS (KEXEC_ON_CRASH) #endif #define VMCOREINFO_BYTES (4096) diff --git a/kernel/kexec.c b/kernel/kexec.c index 4e2e472f6ae..aef789344c2 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -1004,6 +1004,10 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, if (flags & KEXEC_PRESERVE_CONTEXT) image->preserve_context = 1; +#ifdef CONFIG_KEXEC_HARDBOOT + if (flags & KEXEC_HARDBOOT) + image->hardboot = 1; +#endif result = machine_kexec_prepare(image); if (result) goto out; |
