From patchwork Tue Aug 5 01:06:32 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Rowand X-Patchwork-Id: 4674111 Return-Path: X-Original-To: patchwork-linux-arm-msm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 80693C0338 for ; Tue, 5 Aug 2014 01:06:40 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5C8BF200ED for ; Tue, 5 Aug 2014 01:06:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3CB542014A for ; Tue, 5 Aug 2014 01:06:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753438AbaHEBGh (ORCPT ); Mon, 4 Aug 2014 21:06:37 -0400 Received: from mail-pd0-f179.google.com ([209.85.192.179]:57657 "EHLO mail-pd0-f179.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753307AbaHEBGf (ORCPT ); Mon, 4 Aug 2014 21:06:35 -0400 Received: by mail-pd0-f179.google.com with SMTP id ft15so297605pdb.38 for ; Mon, 04 Aug 2014 18:06:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:date:from:reply-to:user-agent:mime-version:cc:subject :references:in-reply-to:content-type:content-transfer-encoding; bh=KwiBndIU3K4cVE0A0gzIzVAtEe88B9Myz2cKL4ivA+I=; b=jdu2pNQGwShvlAUWgK+qgsmwHdUj7mj/YrEcTExXugoPloCPeb8o4MgLEdcP6Bpr+3 CtlKZjMcPi/ty/RlECvBwR2B/f/QwBq4vLK/vbIQSxk8IdF5XtdEUPUNUA8mGDiRBELV s6RxQxVmq+1CAuQIlf6KfZJj1zDda5RKzqDZf2/tRTJUrZHxlaLhVhOjMILxpzPjyWo7 07r/XhTuHgCT9ylUSSrnwX27Or4AxHXdjNxEPoLvU7xwF9I8JmFWorwRj6WF1Drt58Hw 7bhZYmVYjevldwuir/D+HYKPuhDcE00slLQTMTYFBEExaB4CsFh3D+KoDC3iPBskeV54 /mcw== X-Received: by 10.70.103.132 with SMTP id fw4mr312761pdb.99.1407200794742; Mon, 04 Aug 2014 18:06:34 -0700 (PDT) Received: from [172.26.79.116] ([64.211.224.253]) by mx.google.com with ESMTPSA id a12sm194994pdm.56.2014.08.04.18.06.32 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 04 Aug 2014 18:06:33 -0700 (PDT) Message-ID: <53E02E18.60602@gmail.com> Date: Mon, 04 Aug 2014 18:06:32 -0700 From: Frank Rowand Reply-To: frowand.list@gmail.com User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20130801 Thunderbird/17.0.8 MIME-Version: 1.0 CC: Stephen Boyd , David Brown , Daniel Walker , Bryan Huntsman , Greg Kroah-Hartman , Jiri Slaby , "linux-arm-msm@vger.kernel.org" , linux-serial@vger.kernel.org, Linux Kernel list , Jason Wessel , kgdb-bugreport@lists.sourceforge.net Subject: [test patch 3/4] use poll_post_exception in msm_serial References: <53E02C7C.4090206@gmail.com> In-Reply-To: <53E02C7C.4090206@gmail.com> To: unlisted-recipients:; (no To-header on input) Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Frank Rowand ********************************************************** I need help with this patch - it does not fix the issue. ********************************************************** Use framework to allow msm_serial driver to fixup state after operating in polled mode, before returning to interrupt mode. I do not have complete documentation on the hardware, so this patch is a set of shots in the dark. Each experiment can be enabled by enabling a #define. The issue I am trying to resolve with this patch is: kgdb properly communicates with the dragon board, but following the continue command, the serial driver does not get any stale (UART_IMR_RXSTALE) interrupts until 48 characters have been read, which triggers a high water interrupt. After the high water interrupt has been processed, the driver resumes properly getting stale interrupts. msm_poll_post_exception() will be called near the tail end of kgdb_cpu_enter(), via the path invoked by: /* Call the I/O driver's post_exception routine */ if (dbg_io_ops->post_exception) dbg_io_ops->post_exception(); Not-signed-off-by-yet: Frank Rowand --- drivers/tty/serial/msm_serial.c | 196 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Index: b/drivers/tty/serial/msm_serial.c =================================================================== --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -881,6 +881,201 @@ static void msm_poll_put_char(struct uar return; } + +int zzz_poll_put_char_reset; +static void msm_poll_post_exception(struct uart_port *port) +{ + int misr; + struct msm_port *msm_port = UART_TO_MSM(port); + + zzz_poll_put_char_reset++; + + msm_port->old_snap_state = 0; + +// #define ZZZ_ALT_1 +#ifdef ZZZ_ALT_1 + /* + * zzz alternate 1 -- trigger high water after continue <---- bad + * high water count == 48, set old_snap_state = 48 + * then stale total snap == 49, so count == 1 <---- good + * + * better than alternate 2 + */ + msm_read(port, UARTDM_RX_TOTAL_SNAP); + +#if 0 + misr = msm_read(port, UART_MISR); + if (misr & (UART_IMR_RXSTALE)) +#endif + msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR); + msm_write(port, 0xFFFFFF, UARTDM_DMRX); + msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR); +#endif /* ZZZ_ALT_1 */ + + +// #define ZZZ_ALT_2 +#ifdef ZZZ_ALT_2 + /* + * zzz alternate 2 -- trigger high water after continue <---- bad + * high water count == 48, set old_snap_state = 48 + * next total snap == 310 + * then stale total snap == 310, so count == 262 <---- bad + */ + msm_read(port, UARTDM_RX_TOTAL_SNAP); + + msm_write(port, UART_CR_CMD_FORCE_STALE, UART_CR); +#endif + + +// #define ZZZ_ALT_3_4 +#ifdef ZZZ_ALT_3_4 + /* + * zzz alternate 3 -- never trigger after continue <---- bad + */ + msm_read(port, UARTDM_RX_TOTAL_SNAP); + + msm_write(port, 0xFFFFFF, UARTDM_DMRX); + msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR); + + msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR); + msm_write(port, UART_CR_CMD_FORCE_STALE, UART_CR); + +#if 0 + /* + * zzz alternate 3, #if 1 this block + * zzz alternate 4, #if 0 this block + * zzz alternate 4 -- trigger high water after continue <---- bad + * high water count == 48, set old_snap_state = 48 + * then stale total snap == 49, so count == 1 <---- good + */ + misr = msm_read(port, UART_MISR); + while (!(misr & (UART_IMR_RXSTALE))) { + cpu_relax(); + misr = msm_read(port, UART_MISR); + } +#endif + +#endif /* ZZZ_ALT_3_4 */ + + +// #define ZZZ_ALT_5 +#ifdef ZZZ_ALT_5 + /* + * zzz alternate 5 -- trigger high water after continue <---- bad + * high water count == 48, set old_snap_state = 48 + * then stale total snap == 49, so count == 1 <---- good + */ + msm_read(port, UARTDM_RX_TOTAL_SNAP); + +#if 0 + misr = msm_read(port, UART_MISR); + if (misr & (UART_IMR_RXSTALE)) +#endif + msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR); + msm_write(port, 0xFFFFFF, UARTDM_DMRX); + msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR); + + /* zzz should not have to do this, trying anyway */ + /* restore interrupt */ + msm_write(port, msm_port->imr, UART_IMR); +#endif /* ZZZ_ALT_5 */ + + +// #define ZZZ_ALT_6 +#ifdef ZZZ_ALT_6 + /* + * zzz alternate 6 -- trigger high water after continue <---- bad + * high water count == 48, set old_snap_state = 48 + * then stale total snap == 49, so count == 1 <---- good + */ + msm_read(port, UARTDM_RX_TOTAL_SNAP); + + msm_write(port, 0, UART_IMR); /* disable interrupt */ + + misr = msm_read(port, UART_MISR); + if (misr & (UART_IMR_RXSTALE)) + msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR); + msm_write(port, 0xFFFFFF, UARTDM_DMRX); + msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR); + + msm_write(port, UART_CR_CMD_FORCE_STALE, UART_CR); + + /* restore interrupt */ + msm_write(port, msm_port->imr, UART_IMR); + +#endif /* ZZZ_ALT_6 */ + + +#define ZZZ_ALT_7 +#ifdef ZZZ_ALT_7 + /* + * Try to emulate entire interrupt driver read path.... + * + * zzzzzz what is missing that is fixed by the high water irq??? + * + * same result for versions A, B, C + * zzz alternate 7 -- trigger high water after continue <---- bad + * high water count == 48, set old_snap_state = 48 + * then stale total snap == 49, so count == 1 <---- good + */ + +{ + int imr_rx_stale; + unsigned int sr; + + /* + * zzz Grabbing a lock here will result in a deadlock if a breakpoint + * zzz is hit while the lock is held elsewhere. It would be best to + * zzz avoid this lock if possible. + * + * zzz It would be better to do a trylock and warn on failure to + * zzz acquire. + */ + spin_lock(&port->lock); + + misr = msm_read(port, UART_MISR); + imr_rx_stale = misr & UART_IMR_RXSTALE; + + msm_write(port, 0, UART_IMR); /* disable interrupt */ + + if ((msm_read(port, UART_SR) & UART_SR_OVERRUN)) + msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR); + + + /* zzz version A, read _either_ UARTDM_RX_TOTAL_SNAP or UART_RFWR */ + /* zzz version B, read UARTDM_RX_TOTAL_SNAP and UART_RFWR */ + /* zzz version C, read UART_RFWR */ + if (imr_rx_stale) + msm_read(port, UARTDM_RX_TOTAL_SNAP); + else + msm_read(port, UART_RFWR); + + sr = msm_read(port, UART_SR); + /* zzz this could be: while (sr & ...) {UARTDM_RF; UART_SR;} */ + while ((sr & UART_SR_RX_READY) != 0) { + msm_read(port, UARTDM_RF); + sr = msm_read(port, UART_SR); + } + + if (imr_rx_stale) + msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR); + msm_write(port, 0xFFFFFF, UARTDM_DMRX); + msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR); + + msm_write(port, msm_port->imr, UART_IMR); /* restore interrupt */ + + spin_unlock(&port->lock); +} + +#endif /* ZZZ_ALT_7 */ + + + + return; +} + + + #endif static struct uart_ops msm_uart_pops = { @@ -905,6 +1100,7 @@ static struct uart_ops msm_uart_pops = { .poll_init = msm_poll_init, .poll_get_char = msm_poll_get_char, .poll_put_char = msm_poll_put_char, + .poll_post_exception = msm_poll_post_exception, #endif };