Created
July 19, 2017 07:52
-
-
Save sunwayforever/8b4fde551ed28ece24a3256da557187f to your computer and use it in GitHub Desktop.
kgdb patch for android 7.1 on nexus5x
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/arch/arm64/configs/bullhead_defconfig b/arch/arm64/configs/bullhead_defconfig | |
index 8256805..3a4a363 100644 | |
--- a/arch/arm64/configs/bullhead_defconfig | |
+++ b/arch/arm64/configs/bullhead_defconfig | |
@@ -672,3 +672,16 @@ CONFIG_CRYPTO_AES_ARM64_CE_BLK=y | |
CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y | |
CONFIG_QMI_ENCDEC=y | |
CONFIG_STRICT_MEMORY_RWX=y | |
+ | |
+CONFIG_CMDLINE=" kgdboc=ttyHSL0,115200" | |
+CONFIG_CMDLINE_EXTEND=y | |
+CONFIG_STRICT_MEMORY_RWX=n | |
+CONFIG_DEBUG_RODATA=n | |
+CONFIG_FRAME_POINTER=y | |
+CONFIG_DEBUG_KERNEL=y | |
+CONFIG_DEBUG_INFO=y | |
+CONFIG_HAVE_ARCH_KGDB=y | |
+CONFIG_KGDB=y | |
+CONFIG_KGDB_SERIAL_CONSOLE=y | |
+CONFIG_KALLSYMS=y | |
+CONFIG_MSM_WATCHDOG_V2=n | |
\ No newline at end of file | |
diff --git a/drivers/soc/qcom/lge/lge_handle_panic.c b/drivers/soc/qcom/lge/lge_handle_panic.c | |
index e2d1d43..c64ee68 100644 | |
--- a/drivers/soc/qcom/lge/lge_handle_panic.c | |
+++ b/drivers/soc/qcom/lge/lge_handle_panic.c | |
@@ -402,20 +402,23 @@ extern void __iomem *wdt_timer_get_timer0_base(void); | |
static int gen_wdt_bark(const char *val, struct kernel_param *kp) | |
{ | |
- void __iomem *msm_tmr0_base; | |
- msm_tmr0_base = wdt_timer_get_timer0_base(); | |
- | |
- pr_info("%s\n", __func__); | |
- writel_relaxed(0, msm_tmr0_base + WDT0_EN); | |
- writel_relaxed(1, msm_tmr0_base + WDT0_RST); | |
- writel_relaxed(0x31F3, msm_tmr0_base + WDT0_BARK_TIME); | |
- writel_relaxed(5 * 0x31F3, msm_tmr0_base + WDT0_BITE_TIME); | |
- writel_relaxed(1, msm_tmr0_base + WDT0_EN); | |
- mb(); | |
- mdelay(5000); | |
- | |
- pr_err("%s failed\n", __func__); | |
- | |
+ /* | |
+ * void __iomem *msm_tmr0_base; | |
+ * msm_tmr0_base = wdt_timer_get_timer0_base(); | |
+ * | |
+ * pr_info("%s\n", __func__); | |
+ * writel_relaxed(0, msm_tmr0_base + WDT0_EN); | |
+ * writel_relaxed(1, msm_tmr0_base + WDT0_RST); | |
+ * writel_relaxed(0x31F3, msm_tmr0_base + WDT0_BARK_TIME); | |
+ * writel_relaxed(5 * 0x31F3, msm_tmr0_base + WDT0_BITE_TIME); | |
+ * writel_relaxed(1, msm_tmr0_base + WDT0_EN); | |
+ * mb(); | |
+ * mdelay(5000); | |
+ * | |
+ * pr_err("%s failed\n", __func__); | |
+ * | |
+ * return -EIO; | |
+ */ | |
return -EIO; | |
} | |
module_param_call(gen_wdt_bark, gen_wdt_bark, param_get_bool, | |
@@ -423,20 +426,23 @@ module_param_call(gen_wdt_bark, gen_wdt_bark, param_get_bool, | |
static int gen_wdt_bite(const char *val, struct kernel_param *kp) | |
{ | |
- void __iomem *msm_tmr0_base; | |
- msm_tmr0_base = wdt_timer_get_timer0_base(); | |
- | |
- pr_info("%s\n", __func__); | |
- writel_relaxed(0, msm_tmr0_base + WDT0_EN); | |
- writel_relaxed(1, msm_tmr0_base + WDT0_RST); | |
- writel_relaxed(5 * 0x31F3, msm_tmr0_base + WDT0_BARK_TIME); | |
- writel_relaxed(0x31F3, msm_tmr0_base + WDT0_BITE_TIME); | |
- writel_relaxed(1, msm_tmr0_base + WDT0_EN); | |
- mb(); | |
- mdelay(5000); | |
- | |
- pr_err("%s failed\n", __func__); | |
- | |
+ /* | |
+ * void __iomem *msm_tmr0_base; | |
+ * msm_tmr0_base = wdt_timer_get_timer0_base(); | |
+ * | |
+ * pr_info("%s\n", __func__); | |
+ * writel_relaxed(0, msm_tmr0_base + WDT0_EN); | |
+ * writel_relaxed(1, msm_tmr0_base + WDT0_RST); | |
+ * writel_relaxed(5 * 0x31F3, msm_tmr0_base + WDT0_BARK_TIME); | |
+ * writel_relaxed(0x31F3, msm_tmr0_base + WDT0_BITE_TIME); | |
+ * writel_relaxed(1, msm_tmr0_base + WDT0_EN); | |
+ * mb(); | |
+ * mdelay(5000); | |
+ * | |
+ * pr_err("%s failed\n", __func__); | |
+ * | |
+ * return -EIO; | |
+ */ | |
return -EIO; | |
} | |
module_param_call(gen_wdt_bite, gen_wdt_bite, param_get_bool, | |
@@ -583,21 +589,23 @@ module_param_call(gen_unknown_reset, gen_unknown_reset, param_get_bool, | |
void lge_disable_watchdog(void) | |
{ | |
- static int once = 1; | |
- void __iomem *msm_tmr0_base; | |
- | |
- if (once > 1) | |
- return; | |
- | |
- msm_tmr0_base = wdt_timer_get_timer0_base(); | |
- if (!msm_tmr0_base) | |
- return; | |
- | |
- writel_relaxed(0, msm_tmr0_base + WDT0_EN); | |
- mb(); | |
- once++; | |
- | |
- pr_info("%s\n", __func__); | |
+ /* | |
+ * static int once = 1; | |
+ * void __iomem *msm_tmr0_base; | |
+ * | |
+ * if (once > 1) | |
+ * return; | |
+ * | |
+ * msm_tmr0_base = wdt_timer_get_timer0_base(); | |
+ * if (!msm_tmr0_base) | |
+ * return; | |
+ * | |
+ * writel_relaxed(0, msm_tmr0_base + WDT0_EN); | |
+ * mb(); | |
+ * once++; | |
+ * | |
+ * pr_info("%s\n", __func__); | |
+ */ | |
} | |
void lge_panic_handler_fb_free_page(unsigned long mem_addr, unsigned long size) | |
diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c | |
index 1002054..338c1ef 100644 | |
--- a/drivers/tty/serial/kgdboc.c | |
+++ b/drivers/tty/serial/kgdboc.c | |
@@ -29,6 +29,7 @@ static struct kgdb_io kgdboc_io_ops; | |
static int configured = -1; | |
static char config[MAX_CONFIG_LEN]; | |
+static int config_retry_time = 0; | |
static struct kparam_string kps = { | |
.string = config, | |
.maxlen = MAX_CONFIG_LEN, | |
@@ -152,7 +153,26 @@ static void cleanup_kgdboc(void) | |
if (configured == 1) | |
kgdb_unregister_io_module(&kgdboc_io_ops); | |
} | |
+static int kgdbretry_option_setup(char *opt) | |
+{ | |
+ if (strlen(opt) > MAX_CONFIG_LEN) { | |
+ printk(KERN_ERR "kgdbretry: config string too long\n"); | |
+ return -ENOSPC; | |
+ } | |
+ config_retry_time = simple_strtoul(opt, NULL, 10); | |
+ return 0; | |
+} | |
+ | |
+__setup("kgdbretry=", kgdbretry_option_setup); | |
+static int configure_kgdboc(void); | |
+static void ttycheck_func(struct work_struct *work) | |
+{ | |
+ config_retry_time = 0; | |
+ configure_kgdboc(); | |
+} | |
+ | |
+static DECLARE_DELAYED_WORK(ttycheck_work, ttycheck_func); | |
static int configure_kgdboc(void) | |
{ | |
struct tty_driver *p; | |
@@ -179,9 +199,16 @@ static int configure_kgdboc(void) | |
goto do_register; | |
p = tty_find_polling_driver(cptr, &tty_line); | |
- if (!p) | |
+ if (!p) { | |
+ printk(KERN_INFO "kgdb will retry in %d secs\n", config_retry_time); | |
+ if (config_retry_time > 0) { | |
+ INIT_DELAYED_WORK(&ttycheck_work, ttycheck_func); | |
+ schedule_delayed_work(&ttycheck_work, config_retry_time * HZ); | |
+ return -ENODEV; | |
+ } | |
goto noconfig; | |
- | |
+ } | |
+ | |
cons = console_drivers; | |
while (cons) { | |
int idx; | |
@@ -335,5 +362,6 @@ module_init(init_kgdboc); | |
module_exit(cleanup_kgdboc); | |
module_param_call(kgdboc, param_set_kgdboc_var, param_get_string, &kps, 0644); | |
MODULE_PARM_DESC(kgdboc, "<serial_device>[,baud]"); | |
+MODULE_PARM_DESC(kgdbretry, "<delay in seconds> before retrying tty"); | |
MODULE_DESCRIPTION("KGDB Console TTY Driver"); | |
MODULE_LICENSE("GPL"); | |
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c | |
index 87feac4..ae3a707 100644 | |
--- a/drivers/tty/serial/msm_serial_hs_lite.c | |
+++ b/drivers/tty/serial/msm_serial_hs_lite.c | |
@@ -821,6 +821,8 @@ static void msm_hsl_reset(struct uart_port *port) | |
msm_hsl_write(port, RESET_BREAK_INT, regmap[vid][UARTDM_CR]); | |
msm_hsl_write(port, RESET_CTS, regmap[vid][UARTDM_CR]); | |
msm_hsl_write(port, RFR_LOW, regmap[vid][UARTDM_CR]); | |
+ /* Disable DM modes */ | |
+ msm_hsl_write(port, 0, regmap[vid][UARTDM_DMEN]); | |
} | |
static unsigned int msm_hsl_get_mctrl(struct uart_port *port) | |
@@ -1355,6 +1357,136 @@ static void msm_hsl_power(struct uart_port *port, unsigned int state, | |
} | |
} | |
+#ifdef CONFIG_CONSOLE_POLL | |
+ | |
+/* defines from msm_serial.h */ | |
+#define UARTDM_DMEN_RX_SC_ENABLE BIT(5) | |
+#define UARTDM_DMEN_TX_SC_ENABLE BIT(4) | |
+ | |
+#define UARTDM_RXFS_BUF_SHIFT 0x7 | |
+#define UARTDM_RXFS_BUF_MASK 0x7 | |
+ | |
+static int msm_poll_init(struct uart_port *port) | |
+{ | |
+ unsigned int vid; | |
+ | |
+ vid = UART_TO_MSM(port)->ver_id; | |
+ | |
+ /* Enable single character mode on RX FIFO */ | |
+ /* A later patch from David Boyd suggests this causes problems... */ | |
+ /*msm_hsl_write(port, UARTDM_DMEN_RX_SC_ENABLE, regmap[vid][UARTDM_DMEN]);*/ | |
+ | |
+ return 0; | |
+} | |
+ | |
+static int msm_poll_get_char_dm(struct uart_port *port) | |
+{ | |
+ int c; | |
+ static u32 slop; | |
+ static int count; | |
+ unsigned char *sp = (unsigned char *)&slop; | |
+ unsigned int vid; | |
+ | |
+ vid = UART_TO_MSM(port)->ver_id; | |
+ | |
+ /* Check if a previous read had more than one char */ | |
+ if (count) { | |
+ c = sp[sizeof(slop) - count]; | |
+ count--; | |
+ /* Or if FIFO is empty */ | |
+ } else if (!(msm_hsl_read(port, regmap[vid][UARTDM_SR]) & UARTDM_SR_RXRDY_BMSK)) { /* bit 0 */ | |
+ /* | |
+ * If RX packing buffer has less than a word, force stale to | |
+ * push contents into RX FIFO | |
+ */ | |
+ count = msm_hsl_read(port, regmap[vid][UARTDM_RXFS]); | |
+ | |
+ count = (count >> UARTDM_RXFS_BUF_SHIFT) & UARTDM_RXFS_BUF_MASK; | |
+ if (count) { | |
+ msm_hsl_write(port, FORCE_STALE_EVENT, regmap[vid][UARTDM_CR]); | |
+ slop = msm_hsl_read(port, regmap[vid][UARTDM_RF]); | |
+ c = sp[0]; | |
+ count--; | |
+ | |
+ msm_hsl_write(port, RESET_STALE_INT, regmap[vid][UARTDM_CR]); | |
+ msm_hsl_write(port, 0xFF, regmap[vid][UARTDM_DMRX]); | |
+ msm_hsl_write(port, STALE_EVENT_ENABLE, regmap[vid][UARTDM_CR]); | |
+ | |
+ } else { | |
+ c = NO_POLL_CHAR; | |
+ } | |
+ /* FIFO has a word */ | |
+ } else { | |
+ slop = msm_hsl_read(port, regmap[vid][UARTDM_RF]); | |
+ c = sp[0]; | |
+ count = sizeof(slop) - 1; | |
+ } | |
+ return c; | |
+} | |
+ | |
+ | |
+static int msm_poll_get_char(struct uart_port *port) | |
+{ | |
+ u32 imr; | |
+ int c; | |
+ unsigned int vid; | |
+ | |
+ vid = UART_TO_MSM(port)->ver_id; | |
+ | |
+ /* Disable all interrupts */ | |
+ imr = msm_hsl_read(port, regmap[vid][UARTDM_IMR]); | |
+ msm_hsl_write(port, 0, regmap[vid][UARTDM_IMR]); | |
+ | |
+ | |
+ c = msm_poll_get_char_dm(port); | |
+ | |
+ | |
+ /* Enable interrupts */ | |
+ msm_hsl_write(port, imr, regmap[vid][UARTDM_IMR]); | |
+ return c; | |
+} | |
+ | |
+static void reset_dm_count(struct uart_port *port, int count) | |
+{ | |
+ unsigned int vid; | |
+ | |
+ vid = UART_TO_MSM(port)->ver_id; | |
+ | |
+ wait_for_xmitr(port); | |
+ msm_hsl_write(port, count, regmap[vid][UARTDM_NCF_TX]); | |
+ msm_hsl_read(port, regmap[vid][UARTDM_NCF_TX]); | |
+} | |
+ | |
+static void msm_poll_put_char(struct uart_port *port, unsigned char c) | |
+{ | |
+ u32 imr; | |
+ unsigned int vid; | |
+ | |
+ vid = UART_TO_MSM(port)->ver_id; | |
+ | |
+ /* Disable all interrupts */ | |
+ imr = msm_hsl_read(port, regmap[vid][UARTDM_IMR]); | |
+ msm_hsl_write(port, 0, regmap[vid][UARTDM_IMR]); | |
+ | |
+ /*if (msm_port->is_uartdm)*/ | |
+ reset_dm_count(port, 1); | |
+ | |
+ /* Wait until FIFO is empty */ | |
+ while (!(msm_hsl_read(port, regmap[vid][UARTDM_SR]) & UARTDM_SR_TXRDY_BMSK)) | |
+ cpu_relax(); | |
+ | |
+ /* Write a character */ | |
+ msm_hsl_write(port, c, regmap[vid][UARTDM_TF]); | |
+ | |
+ /* Wait until FIFO is empty */ | |
+ while (!(msm_hsl_read(port, regmap[vid][UARTDM_SR]) & UARTDM_SR_TXRDY_BMSK)) | |
+ cpu_relax(); | |
+ | |
+ /* Enable interrupts */ | |
+ msm_hsl_write(port, imr, regmap[vid][UARTDM_IMR]); | |
+ return; | |
+} | |
+#endif | |
static struct uart_ops msm_hsl_uart_pops = { | |
.tx_empty = msm_hsl_tx_empty, | |
.set_mctrl = msm_hsl_set_mctrl, | |
@@ -1373,6 +1505,11 @@ static struct uart_ops msm_hsl_uart_pops = { | |
.config_port = msm_hsl_config_port, | |
.verify_port = msm_hsl_verify_port, | |
.pm = msm_hsl_power, | |
+ #ifdef CONFIG_CONSOLE_POLL | |
+ .poll_init = msm_poll_init, | |
+ .poll_get_char = msm_poll_get_char, | |
+ .poll_put_char = msm_poll_put_char, | |
+ #endif | |
}; | |
static struct msm_hsl_port msm_hsl_uart_ports[] = { |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment