From: Sasha Levin Date: Thu, 27 Feb 2020 03:38:57 +0000 (-0500) Subject: fixes for 4.19 X-Git-Tag: v4.4.215~50 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7ad3af80a2e4917b681726c35f43fccd575697e0;p=thirdparty%2Fkernel%2Fstable-queue.git fixes for 4.19 Signed-off-by: Sasha Levin --- diff --git a/queue-4.19/drm-nouveau-kms-gv100-re-set-lut-after-clearing-for-.patch b/queue-4.19/drm-nouveau-kms-gv100-re-set-lut-after-clearing-for-.patch new file mode 100644 index 00000000000..8c9780e9596 --- /dev/null +++ b/queue-4.19/drm-nouveau-kms-gv100-re-set-lut-after-clearing-for-.patch @@ -0,0 +1,47 @@ +From d30c79f4862ca4fa07daa0f767519d79c27ffab8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2020 18:11:49 -0500 +Subject: drm/nouveau/kms/gv100-: Re-set LUT after clearing for modesets + +From: Lyude Paul + +[ Upstream commit f287d3d19769b1d22cba4e51fa0487f2697713c9 ] + +While certain modeset operations on gv100+ need us to temporarily +disable the LUT, we make the mistake of sometimes neglecting to +reprogram the LUT after such modesets. In particular, moving a head from +one encoder to another seems to trigger this quite often. GV100+ is very +picky about having a LUT in most scenarios, so this causes the display +engine to hang with the following error code: + +disp: chid 1 stat 00005080 reason 5 [INVALID_STATE] mthd 0200 data +00000001 code 0000002d) + +So, fix this by always re-programming the LUT if we're clearing it in a +state where the wndw is still visible, and has a XLUT handle programmed. + +Signed-off-by: Lyude Paul +Fixes: facaed62b4cb ("drm/nouveau/kms/gv100: initial support") +Cc: # v4.18+ +Signed-off-by: Ben Skeggs +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/nouveau/dispnv50/wndw.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c +index b3db4553098d5..d343ae66c64fe 100644 +--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c ++++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c +@@ -405,6 +405,8 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) + asyw->clr.ntfy = armw->ntfy.handle != 0; + asyw->clr.sema = armw->sema.handle != 0; + asyw->clr.xlut = armw->xlut.handle != 0; ++ if (asyw->clr.xlut && asyw->visible) ++ asyw->set.xlut = asyw->xlut.handle != 0; + if (wndw->func->image_clr) + asyw->clr.image = armw->image.handle[0] != 0; + } +-- +2.20.1 + diff --git a/queue-4.19/lib-stackdepot-fix-outdated-comments.patch b/queue-4.19/lib-stackdepot-fix-outdated-comments.patch new file mode 100644 index 00000000000..587e601c255 --- /dev/null +++ b/queue-4.19/lib-stackdepot-fix-outdated-comments.patch @@ -0,0 +1,47 @@ +From 844d3e76628130384370c6ffa0c2db3da374bce4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Aug 2019 19:32:46 +0800 +Subject: lib/stackdepot: Fix outdated comments + +From: Miles Chen + +[ Upstream commit ee050dc83bc326ad5ef8ee93bca344819371e7a5 ] + +Replace "depot_save_stack" with "stack_depot_save" in code comments because +depot_save_stack() was replaced in commit c0cfc337264c ("lib/stackdepot: +Provide functions which operate on plain storage arrays") and removed in +commit 56d8f079c51a ("lib/stackdepot: Remove obsolete functions") + +Signed-off-by: Miles Chen +Signed-off-by: Thomas Gleixner +Link: https://lkml.kernel.org/r/20190815113246.18478-1-miles.chen@mediatek.com +Signed-off-by: Sasha Levin +--- + lib/stackdepot.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/stackdepot.c b/lib/stackdepot.c +index e513459a5601a..c5e06c43228f9 100644 +--- a/lib/stackdepot.c ++++ b/lib/stackdepot.c +@@ -96,7 +96,7 @@ static bool init_stack_slab(void **prealloc) + stack_slabs[depot_index + 1] = *prealloc; + /* + * This smp_store_release pairs with smp_load_acquire() from +- * |next_slab_inited| above and in depot_save_stack(). ++ * |next_slab_inited| above and in stack_depot_save(). + */ + smp_store_release(&next_slab_inited, 1); + } +@@ -123,7 +123,7 @@ static struct stack_record *depot_alloc_stack(unsigned long *entries, int size, + depot_offset = 0; + /* + * smp_store_release() here pairs with smp_load_acquire() from +- * |next_slab_inited| in depot_save_stack() and ++ * |next_slab_inited| in stack_depot_save() and + * init_stack_slab(). + */ + if (depot_index + 1 < STACK_ALLOC_MAX_SLABS) +-- +2.20.1 + diff --git a/queue-4.19/lib-stackdepot.c-fix-global-out-of-bounds-in-stack_s.patch b/queue-4.19/lib-stackdepot.c-fix-global-out-of-bounds-in-stack_s.patch new file mode 100644 index 00000000000..74b9aa58559 --- /dev/null +++ b/queue-4.19/lib-stackdepot.c-fix-global-out-of-bounds-in-stack_s.patch @@ -0,0 +1,62 @@ +From d33350b62bd2427b787999177442685a31e5ffbc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2020 20:04:30 -0800 +Subject: lib/stackdepot.c: fix global out-of-bounds in stack_slabs + +From: Alexander Potapenko + +[ Upstream commit 305e519ce48e935702c32241f07d393c3c8fed3e ] + +Walter Wu has reported a potential case in which init_stack_slab() is +called after stack_slabs[STACK_ALLOC_MAX_SLABS - 1] has already been +initialized. In that case init_stack_slab() will overwrite +stack_slabs[STACK_ALLOC_MAX_SLABS], which may result in a memory +corruption. + +Link: http://lkml.kernel.org/r/20200218102950.260263-1-glider@google.com +Fixes: cd11016e5f521 ("mm, kasan: stackdepot implementation. Enable stackdepot for SLAB") +Signed-off-by: Alexander Potapenko +Reported-by: Walter Wu +Cc: Dmitry Vyukov +Cc: Matthias Brugger +Cc: Thomas Gleixner +Cc: Josh Poimboeuf +Cc: Kate Stewart +Cc: Greg Kroah-Hartman +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + lib/stackdepot.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/lib/stackdepot.c b/lib/stackdepot.c +index c5e06c43228f9..34c71973932e0 100644 +--- a/lib/stackdepot.c ++++ b/lib/stackdepot.c +@@ -92,15 +92,19 @@ static bool init_stack_slab(void **prealloc) + return true; + if (stack_slabs[depot_index] == NULL) { + stack_slabs[depot_index] = *prealloc; ++ *prealloc = NULL; + } else { +- stack_slabs[depot_index + 1] = *prealloc; ++ /* If this is the last depot slab, do not touch the next one. */ ++ if (depot_index + 1 < STACK_ALLOC_MAX_SLABS) { ++ stack_slabs[depot_index + 1] = *prealloc; ++ *prealloc = NULL; ++ } + /* + * This smp_store_release pairs with smp_load_acquire() from + * |next_slab_inited| above and in stack_depot_save(). + */ + smp_store_release(&next_slab_inited, 1); + } +- *prealloc = NULL; + return true; + } + +-- +2.20.1 + diff --git a/queue-4.19/series b/queue-4.19/series index aca69c2707b..e1fc745538c 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -51,3 +51,12 @@ drm-amdgpu-soc15-fix-xclk-for-raven.patch xhci-apply-xhci_pme_stuck_quirk-to-intel-comet-lake-platforms.patch kvm-nvmx-don-t-emulate-instructions-in-guest-mode.patch kvm-x86-don-t-notify-userspace-ioapic-on-edge-triggered-interrupt-eoi.patch +tty-serial-qcom_geni_serial-fix-uart-hang.patch +tty-serial-qcom_geni_serial-remove-interrupt-storm.patch +tty-serial-qcom_geni_serial-remove-use-of-_relaxed-a.patch +tty-serial-qcom_geni_serial-remove-set_rfr_wm-and-re.patch +tty-serial-qcom_geni_serial-remove-xfer_mode-variabl.patch +tty-serial-qcom_geni_serial-fix-rx-cancel-command-fa.patch +lib-stackdepot-fix-outdated-comments.patch +lib-stackdepot.c-fix-global-out-of-bounds-in-stack_s.patch +drm-nouveau-kms-gv100-re-set-lut-after-clearing-for-.patch diff --git a/queue-4.19/tty-serial-qcom_geni_serial-fix-rx-cancel-command-fa.patch b/queue-4.19/tty-serial-qcom_geni_serial-fix-rx-cancel-command-fa.patch new file mode 100644 index 00000000000..40da61856fb --- /dev/null +++ b/queue-4.19/tty-serial-qcom_geni_serial-fix-rx-cancel-command-fa.patch @@ -0,0 +1,73 @@ +From 7eea30d0b1fac7b3dfefdcec64a22c3ad8305c2f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2020 15:43:02 +0530 +Subject: tty: serial: qcom_geni_serial: Fix RX cancel command failure + +From: satya priya + +[ Upstream commit 679aac5ead2f18d223554a52b543e1195e181811 ] + +RX cancel command fails when BT is switched on and off multiple times. + +To handle this, poll for the cancel bit in SE_GENI_S_IRQ_STATUS register +instead of SE_GENI_S_CMD_CTRL_REG. + +As per the HPG update, handle the RX last bit after cancel command +and flush out the RX FIFO buffer. + +Signed-off-by: satya priya +Cc: stable +Link: https://lore.kernel.org/r/1581415982-8793-1-git-send-email-skakit@codeaurora.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/qcom_geni_serial.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c +index 4182129925dec..4458419f053b6 100644 +--- a/drivers/tty/serial/qcom_geni_serial.c ++++ b/drivers/tty/serial/qcom_geni_serial.c +@@ -121,6 +121,7 @@ static int handle_rx_console(struct uart_port *uport, u32 bytes, bool drop); + static int handle_rx_uart(struct uart_port *uport, u32 bytes, bool drop); + static unsigned int qcom_geni_serial_tx_empty(struct uart_port *port); + static void qcom_geni_serial_stop_rx(struct uart_port *uport); ++static void qcom_geni_serial_handle_rx(struct uart_port *uport, bool drop); + + static const unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200, + 32000000, 48000000, 64000000, 80000000, +@@ -614,7 +615,7 @@ static void qcom_geni_serial_stop_rx(struct uart_port *uport) + u32 irq_en; + u32 status; + struct qcom_geni_serial_port *port = to_dev_port(uport, uport); +- u32 irq_clear = S_CMD_DONE_EN; ++ u32 s_irq_status; + + irq_en = readl(uport->membase + SE_GENI_S_IRQ_EN); + irq_en &= ~(S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN); +@@ -630,10 +631,19 @@ static void qcom_geni_serial_stop_rx(struct uart_port *uport) + return; + + geni_se_cancel_s_cmd(&port->se); +- qcom_geni_serial_poll_bit(uport, SE_GENI_S_CMD_CTRL_REG, +- S_GENI_CMD_CANCEL, false); ++ qcom_geni_serial_poll_bit(uport, SE_GENI_S_IRQ_STATUS, ++ S_CMD_CANCEL_EN, true); ++ /* ++ * If timeout occurs secondary engine remains active ++ * and Abort sequence is executed. ++ */ ++ s_irq_status = readl(uport->membase + SE_GENI_S_IRQ_STATUS); ++ /* Flush the Rx buffer */ ++ if (s_irq_status & S_RX_FIFO_LAST_EN) ++ qcom_geni_serial_handle_rx(uport, true); ++ writel(s_irq_status, uport->membase + SE_GENI_S_IRQ_CLEAR); ++ + status = readl(uport->membase + SE_GENI_STATUS); +- writel(irq_clear, uport->membase + SE_GENI_S_IRQ_CLEAR); + if (status & S_GENI_CMD_ACTIVE) + qcom_geni_serial_abort_rx(uport); + } +-- +2.20.1 + diff --git a/queue-4.19/tty-serial-qcom_geni_serial-fix-uart-hang.patch b/queue-4.19/tty-serial-qcom_geni_serial-fix-uart-hang.patch new file mode 100644 index 00000000000..4b327df3dd7 --- /dev/null +++ b/queue-4.19/tty-serial-qcom_geni_serial-fix-uart-hang.patch @@ -0,0 +1,52 @@ +From 2ace7701fd5a438f01b6791feae7659db882d598 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Dec 2018 12:33:53 -0800 +Subject: tty: serial: qcom_geni_serial: Fix UART hang + +From: Ryan Case + +[ Upstream commit 663abb1a7a7ff8fea9ab0145463de7fcff823755 ] + +If a serial console write occured while a UART transmit command was +waiting for a done signal then no further data would be sent until +something new kicked the system into gear. If there is already data +waiting in the circular buffer we must re-enable the tx watermark so we +receive the expected interrupts. + +Signed-off-by: Ryan Case +Reviewed-by: Evan Green +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/qcom_geni_serial.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c +index b3f7d1a1e97f8..2003dfcace5d8 100644 +--- a/drivers/tty/serial/qcom_geni_serial.c ++++ b/drivers/tty/serial/qcom_geni_serial.c +@@ -438,6 +438,7 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s, + bool locked = true; + unsigned long flags; + u32 geni_status; ++ u32 irq_en; + + WARN_ON(co->index < 0 || co->index >= GENI_UART_CONS_PORTS); + +@@ -472,6 +473,13 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s, + * has been sent, in which case we need to look for done first. + */ + qcom_geni_serial_poll_tx_done(uport); ++ ++ if (uart_circ_chars_pending(&uport->state->xmit)) { ++ irq_en = readl_relaxed(uport->membase + ++ SE_GENI_M_IRQ_EN); ++ writel_relaxed(irq_en | M_TX_FIFO_WATERMARK_EN, ++ uport->membase + SE_GENI_M_IRQ_EN); ++ } + } + + __qcom_geni_serial_console_write(uport, s, count); +-- +2.20.1 + diff --git a/queue-4.19/tty-serial-qcom_geni_serial-remove-interrupt-storm.patch b/queue-4.19/tty-serial-qcom_geni_serial-remove-interrupt-storm.patch new file mode 100644 index 00000000000..053e92e6aaa --- /dev/null +++ b/queue-4.19/tty-serial-qcom_geni_serial-remove-interrupt-storm.patch @@ -0,0 +1,87 @@ +From 22dfafadabd283123339e705d9cffde1bb0b0f1c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Dec 2018 11:43:20 -0800 +Subject: tty: serial: qcom_geni_serial: Remove interrupt storm + +From: Ryan Case + +[ Upstream commit 64a428077758383518c258641e81d57fcd454792 ] + +Disable M_TX_FIFO_WATERMARK_EN after we've sent all data for a given +transaction so we don't continue to receive a flurry of free space +interrupts while waiting for the M_CMD_DONE notification. Re-enable the +watermark when establishing the next transaction. + +Also clear the watermark interrupt after filling the FIFO so we do not +receive notification again prior to actually having free space. + +Signed-off-by: Ryan Case +Reviewed-by: Douglas Anderson +Tested-by: Douglas Anderson +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/qcom_geni_serial.c | 25 +++++++++++++++++++++++-- + 1 file changed, 23 insertions(+), 2 deletions(-) + +diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c +index 2003dfcace5d8..743d877e7ff94 100644 +--- a/drivers/tty/serial/qcom_geni_serial.c ++++ b/drivers/tty/serial/qcom_geni_serial.c +@@ -727,6 +727,7 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done, + size_t pending; + int i; + u32 status; ++ u32 irq_en; + unsigned int chunk; + int tail; + +@@ -755,6 +756,11 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done, + if (!port->tx_remaining) { + qcom_geni_serial_setup_tx(uport, pending); + port->tx_remaining = pending; ++ ++ irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); ++ if (!(irq_en & M_TX_FIFO_WATERMARK_EN)) ++ writel_relaxed(irq_en | M_TX_FIFO_WATERMARK_EN, ++ uport->membase + SE_GENI_M_IRQ_EN); + } + + remaining = chunk; +@@ -778,7 +784,23 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done, + } + + xmit->tail = tail & (UART_XMIT_SIZE - 1); ++ ++ /* ++ * The tx fifo watermark is level triggered and latched. Though we had ++ * cleared it in qcom_geni_serial_isr it will have already reasserted ++ * so we must clear it again here after our writes. ++ */ ++ writel_relaxed(M_TX_FIFO_WATERMARK_EN, ++ uport->membase + SE_GENI_M_IRQ_CLEAR); ++ + out_write_wakeup: ++ if (!port->tx_remaining) { ++ irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); ++ if (irq_en & M_TX_FIFO_WATERMARK_EN) ++ writel_relaxed(irq_en & ~M_TX_FIFO_WATERMARK_EN, ++ uport->membase + SE_GENI_M_IRQ_EN); ++ } ++ + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(uport); + } +@@ -814,8 +836,7 @@ static irqreturn_t qcom_geni_serial_isr(int isr, void *dev) + tty_insert_flip_char(tport, 0, TTY_OVERRUN); + } + +- if (m_irq_status & (M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN) && +- m_irq_en & (M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN)) ++ if (m_irq_status & m_irq_en & (M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN)) + qcom_geni_serial_handle_tx(uport, m_irq_status & M_CMD_DONE_EN, + geni_status & M_GENI_CMD_ACTIVE); + +-- +2.20.1 + diff --git a/queue-4.19/tty-serial-qcom_geni_serial-remove-set_rfr_wm-and-re.patch b/queue-4.19/tty-serial-qcom_geni_serial-remove-set_rfr_wm-and-re.patch new file mode 100644 index 00000000000..b0006545aea --- /dev/null +++ b/queue-4.19/tty-serial-qcom_geni_serial-remove-set_rfr_wm-and-re.patch @@ -0,0 +1,103 @@ +From 6fc1e94a14a9d40db946de3b6f813220bfe7360f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Jan 2019 17:58:36 -0800 +Subject: tty: serial: qcom_geni_serial: Remove set_rfr_wm() and related + variables + +From: Ryan Case + +[ Upstream commit a85fb9ce1fab34a3216fd4d769fede643dbc68d4 ] + +The variables of tx_wm and rx_wm were set to the same define value in +all cases, never updated, and the define was sometimes used +interchangably. Remove the variables/function and use the fixed value. + +Signed-off-by: Ryan Case +Reviewed-by: Evan Green +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/qcom_geni_serial.c | 25 ++++--------------------- + 1 file changed, 4 insertions(+), 21 deletions(-) + +diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c +index 4824869a4080d..080fa1d1ecbfd 100644 +--- a/drivers/tty/serial/qcom_geni_serial.c ++++ b/drivers/tty/serial/qcom_geni_serial.c +@@ -85,7 +85,7 @@ + #define DEF_FIFO_DEPTH_WORDS 16 + #define DEF_TX_WM 2 + #define DEF_FIFO_WIDTH_BITS 32 +-#define UART_CONSOLE_RX_WM 2 ++#define UART_RX_WM 2 + #define MAX_LOOPBACK_CFG 3 + + #ifdef CONFIG_CONSOLE_POLL +@@ -101,9 +101,6 @@ struct qcom_geni_serial_port { + u32 tx_fifo_depth; + u32 tx_fifo_width; + u32 rx_fifo_depth; +- u32 tx_wm; +- u32 rx_wm; +- u32 rx_rfr; + enum geni_se_xfer_mode xfer_mode; + bool setup; + int (*handle_rx)(struct uart_port *uport, u32 bytes, bool drop); +@@ -361,9 +358,7 @@ static int qcom_geni_serial_get_char(struct uart_port *uport) + static void qcom_geni_serial_poll_put_char(struct uart_port *uport, + unsigned char c) + { +- struct qcom_geni_serial_port *port = to_dev_port(uport, uport); +- +- writel(port->tx_wm, uport->membase + SE_GENI_TX_WATERMARK_REG); ++ writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG); + qcom_geni_serial_setup_tx(uport, 1); + WARN_ON(!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, + M_TX_FIFO_WATERMARK_EN, true)); +@@ -571,7 +566,7 @@ static void qcom_geni_serial_start_tx(struct uart_port *uport) + irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); + irq_en |= M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN; + +- writel(port->tx_wm, uport->membase + ++ writel(DEF_TX_WM, uport->membase + + SE_GENI_TX_WATERMARK_REG); + writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN); + } +@@ -840,17 +835,6 @@ static void get_tx_fifo_size(struct qcom_geni_serial_port *port) + (port->tx_fifo_depth * port->tx_fifo_width) / BITS_PER_BYTE; + } + +-static void set_rfr_wm(struct qcom_geni_serial_port *port) +-{ +- /* +- * Set RFR (Flow off) to FIFO_DEPTH - 2. +- * RX WM level at 10% RX_FIFO_DEPTH. +- * TX WM level at 10% TX_FIFO_DEPTH. +- */ +- port->rx_rfr = port->rx_fifo_depth - 2; +- port->rx_wm = UART_CONSOLE_RX_WM; +- port->tx_wm = DEF_TX_WM; +-} + + static void qcom_geni_serial_shutdown(struct uart_port *uport) + { +@@ -889,7 +873,6 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport) + + get_tx_fifo_size(port); + +- set_rfr_wm(port); + writel(rxstale, uport->membase + SE_UART_RX_STALE_CNT); + /* + * Make an unconditional cancel on the main sequencer to reset +@@ -902,7 +885,7 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport) + false, true, false); + geni_se_config_packing(&port->se, BITS_PER_BYTE, port->rx_bytes_pw, + false, false, true); +- geni_se_init(&port->se, port->rx_wm, port->rx_rfr); ++ geni_se_init(&port->se, UART_RX_WM, port->rx_fifo_depth - 2); + geni_se_select_mode(&port->se, port->xfer_mode); + if (!uart_console(uport)) { + port->rx_fifo = devm_kcalloc(uport->dev, +-- +2.20.1 + diff --git a/queue-4.19/tty-serial-qcom_geni_serial-remove-use-of-_relaxed-a.patch b/queue-4.19/tty-serial-qcom_geni_serial-remove-use-of-_relaxed-a.patch new file mode 100644 index 00000000000..9e4bd6a4e46 --- /dev/null +++ b/queue-4.19/tty-serial-qcom_geni_serial-remove-use-of-_relaxed-a.patch @@ -0,0 +1,474 @@ +From e3c77259e810cda9504699e6beb8e77259bf0332 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Jan 2019 17:58:35 -0800 +Subject: tty: serial: qcom_geni_serial: Remove use of *_relaxed() and mb() + +From: Ryan Case + +[ Upstream commit 9e06d55f7b856bfaf82036b50072600b21e52d20 ] + +A frequent side comment has been to remove the use of writel_relaxed, +readl_relaxed, and mb. This reduces driver complexity and the _relaxed +variants were not known to provide any noticeable performance benefit. + +Signed-off-by: Ryan Case +Reviewed-by: Evan Green +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/qcom_geni_serial.c | 191 +++++++++++--------------- + 1 file changed, 80 insertions(+), 111 deletions(-) + +diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c +index 743d877e7ff94..4824869a4080d 100644 +--- a/drivers/tty/serial/qcom_geni_serial.c ++++ b/drivers/tty/serial/qcom_geni_serial.c +@@ -226,7 +226,7 @@ static unsigned int qcom_geni_serial_get_mctrl(struct uart_port *uport) + if (uart_console(uport)) { + mctrl |= TIOCM_CTS; + } else { +- geni_ios = readl_relaxed(uport->membase + SE_GENI_IOS); ++ geni_ios = readl(uport->membase + SE_GENI_IOS); + if (!(geni_ios & IO2_DATA_IN)) + mctrl |= TIOCM_CTS; + } +@@ -244,7 +244,7 @@ static void qcom_geni_serial_set_mctrl(struct uart_port *uport, + + if (!(mctrl & TIOCM_RTS)) + uart_manual_rfr = UART_MANUAL_RFR_EN | UART_RFR_NOT_READY; +- writel_relaxed(uart_manual_rfr, uport->membase + SE_UART_MANUAL_RFR); ++ writel(uart_manual_rfr, uport->membase + SE_UART_MANUAL_RFR); + } + + static const char *qcom_geni_serial_get_type(struct uart_port *uport) +@@ -273,9 +273,6 @@ static bool qcom_geni_serial_poll_bit(struct uart_port *uport, + unsigned int fifo_bits; + unsigned long timeout_us = 20000; + +- /* Ensure polling is not re-ordered before the prior writes/reads */ +- mb(); +- + if (uport->private_data) { + port = to_dev_port(uport, uport); + baud = port->baud; +@@ -295,7 +292,7 @@ static bool qcom_geni_serial_poll_bit(struct uart_port *uport, + */ + timeout_us = DIV_ROUND_UP(timeout_us, 10) * 10; + while (timeout_us) { +- reg = readl_relaxed(uport->membase + offset); ++ reg = readl(uport->membase + offset); + if ((bool)(reg & field) == set) + return true; + udelay(10); +@@ -308,7 +305,7 @@ static void qcom_geni_serial_setup_tx(struct uart_port *uport, u32 xmit_size) + { + u32 m_cmd; + +- writel_relaxed(xmit_size, uport->membase + SE_UART_TX_TRANS_LEN); ++ writel(xmit_size, uport->membase + SE_UART_TX_TRANS_LEN); + m_cmd = UART_START_TX << M_OPCODE_SHFT; + writel(m_cmd, uport->membase + SE_GENI_M_CMD0); + } +@@ -321,13 +318,13 @@ static void qcom_geni_serial_poll_tx_done(struct uart_port *uport) + done = qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, + M_CMD_DONE_EN, true); + if (!done) { +- writel_relaxed(M_GENI_CMD_ABORT, uport->membase + ++ writel(M_GENI_CMD_ABORT, uport->membase + + SE_GENI_M_CMD_CTRL_REG); + irq_clear |= M_CMD_ABORT_EN; + qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, + M_CMD_ABORT_EN, true); + } +- writel_relaxed(irq_clear, uport->membase + SE_GENI_M_IRQ_CLEAR); ++ writel(irq_clear, uport->membase + SE_GENI_M_IRQ_CLEAR); + } + + static void qcom_geni_serial_abort_rx(struct uart_port *uport) +@@ -337,8 +334,8 @@ static void qcom_geni_serial_abort_rx(struct uart_port *uport) + writel(S_GENI_CMD_ABORT, uport->membase + SE_GENI_S_CMD_CTRL_REG); + qcom_geni_serial_poll_bit(uport, SE_GENI_S_CMD_CTRL_REG, + S_GENI_CMD_ABORT, false); +- writel_relaxed(irq_clear, uport->membase + SE_GENI_S_IRQ_CLEAR); +- writel_relaxed(FORCE_DEFAULT, uport->membase + GENI_FORCE_DEFAULT_REG); ++ writel(irq_clear, uport->membase + SE_GENI_S_IRQ_CLEAR); ++ writel(FORCE_DEFAULT, uport->membase + GENI_FORCE_DEFAULT_REG); + } + + #ifdef CONFIG_CONSOLE_POLL +@@ -347,19 +344,13 @@ static int qcom_geni_serial_get_char(struct uart_port *uport) + u32 rx_fifo; + u32 status; + +- status = readl_relaxed(uport->membase + SE_GENI_M_IRQ_STATUS); +- writel_relaxed(status, uport->membase + SE_GENI_M_IRQ_CLEAR); +- +- status = readl_relaxed(uport->membase + SE_GENI_S_IRQ_STATUS); +- writel_relaxed(status, uport->membase + SE_GENI_S_IRQ_CLEAR); ++ status = readl(uport->membase + SE_GENI_M_IRQ_STATUS); ++ writel(status, uport->membase + SE_GENI_M_IRQ_CLEAR); + +- /* +- * Ensure the writes to clear interrupts is not re-ordered after +- * reading the data. +- */ +- mb(); ++ status = readl(uport->membase + SE_GENI_S_IRQ_STATUS); ++ writel(status, uport->membase + SE_GENI_S_IRQ_CLEAR); + +- status = readl_relaxed(uport->membase + SE_GENI_RX_FIFO_STATUS); ++ status = readl(uport->membase + SE_GENI_RX_FIFO_STATUS); + if (!(status & RX_FIFO_WC_MSK)) + return NO_POLL_CHAR; + +@@ -372,13 +363,12 @@ static void qcom_geni_serial_poll_put_char(struct uart_port *uport, + { + struct qcom_geni_serial_port *port = to_dev_port(uport, uport); + +- writel_relaxed(port->tx_wm, uport->membase + SE_GENI_TX_WATERMARK_REG); ++ writel(port->tx_wm, uport->membase + SE_GENI_TX_WATERMARK_REG); + qcom_geni_serial_setup_tx(uport, 1); + WARN_ON(!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, + M_TX_FIFO_WATERMARK_EN, true)); +- writel_relaxed(c, uport->membase + SE_GENI_TX_FIFOn); +- writel_relaxed(M_TX_FIFO_WATERMARK_EN, uport->membase + +- SE_GENI_M_IRQ_CLEAR); ++ writel(c, uport->membase + SE_GENI_TX_FIFOn); ++ writel(M_TX_FIFO_WATERMARK_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); + qcom_geni_serial_poll_tx_done(uport); + } + #endif +@@ -386,7 +376,7 @@ static void qcom_geni_serial_poll_put_char(struct uart_port *uport, + #ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE + static void qcom_geni_serial_wr_char(struct uart_port *uport, int ch) + { +- writel_relaxed(ch, uport->membase + SE_GENI_TX_FIFOn); ++ writel(ch, uport->membase + SE_GENI_TX_FIFOn); + } + + static void +@@ -405,7 +395,7 @@ __qcom_geni_serial_console_write(struct uart_port *uport, const char *s, + bytes_to_send++; + } + +- writel_relaxed(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG); ++ writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG); + qcom_geni_serial_setup_tx(uport, bytes_to_send); + for (i = 0; i < count; ) { + size_t chars_to_write = 0; +@@ -423,7 +413,7 @@ __qcom_geni_serial_console_write(struct uart_port *uport, const char *s, + chars_to_write = min_t(size_t, count - i, avail / 2); + uart_console_write(uport, s + i, chars_to_write, + qcom_geni_serial_wr_char); +- writel_relaxed(M_TX_FIFO_WATERMARK_EN, uport->membase + ++ writel(M_TX_FIFO_WATERMARK_EN, uport->membase + + SE_GENI_M_IRQ_CLEAR); + i += chars_to_write; + } +@@ -452,7 +442,7 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s, + else + spin_lock_irqsave(&uport->lock, flags); + +- geni_status = readl_relaxed(uport->membase + SE_GENI_STATUS); ++ geni_status = readl(uport->membase + SE_GENI_STATUS); + + /* Cancel the current write to log the fault */ + if (!locked) { +@@ -462,11 +452,10 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s, + geni_se_abort_m_cmd(&port->se); + qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, + M_CMD_ABORT_EN, true); +- writel_relaxed(M_CMD_ABORT_EN, uport->membase + ++ writel(M_CMD_ABORT_EN, uport->membase + + SE_GENI_M_IRQ_CLEAR); + } +- writel_relaxed(M_CMD_CANCEL_EN, uport->membase + +- SE_GENI_M_IRQ_CLEAR); ++ writel(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); + } else if ((geni_status & M_GENI_CMD_ACTIVE) && !port->tx_remaining) { + /* + * It seems we can't interrupt existing transfers if all data +@@ -475,9 +464,8 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s, + qcom_geni_serial_poll_tx_done(uport); + + if (uart_circ_chars_pending(&uport->state->xmit)) { +- irq_en = readl_relaxed(uport->membase + +- SE_GENI_M_IRQ_EN); +- writel_relaxed(irq_en | M_TX_FIFO_WATERMARK_EN, ++ irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); ++ writel(irq_en | M_TX_FIFO_WATERMARK_EN, + uport->membase + SE_GENI_M_IRQ_EN); + } + } +@@ -580,12 +568,12 @@ static void qcom_geni_serial_start_tx(struct uart_port *uport) + if (!qcom_geni_serial_tx_empty(uport)) + return; + +- irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); ++ irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); + irq_en |= M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN; + +- writel_relaxed(port->tx_wm, uport->membase + ++ writel(port->tx_wm, uport->membase + + SE_GENI_TX_WATERMARK_REG); +- writel_relaxed(irq_en, uport->membase + SE_GENI_M_IRQ_EN); ++ writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN); + } + } + +@@ -595,35 +583,28 @@ static void qcom_geni_serial_stop_tx(struct uart_port *uport) + u32 status; + struct qcom_geni_serial_port *port = to_dev_port(uport, uport); + +- irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); ++ irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); + irq_en &= ~M_CMD_DONE_EN; + if (port->xfer_mode == GENI_SE_FIFO) { + irq_en &= ~M_TX_FIFO_WATERMARK_EN; +- writel_relaxed(0, uport->membase + ++ writel(0, uport->membase + + SE_GENI_TX_WATERMARK_REG); + } +- writel_relaxed(irq_en, uport->membase + SE_GENI_M_IRQ_EN); +- status = readl_relaxed(uport->membase + SE_GENI_STATUS); ++ writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN); ++ status = readl(uport->membase + SE_GENI_STATUS); + /* Possible stop tx is called multiple times. */ + if (!(status & M_GENI_CMD_ACTIVE)) + return; + +- /* +- * Ensure cancel command write is not re-ordered before checking +- * the status of the Primary Sequencer. +- */ +- mb(); +- + geni_se_cancel_m_cmd(&port->se); + if (!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, + M_CMD_CANCEL_EN, true)) { + geni_se_abort_m_cmd(&port->se); + qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, + M_CMD_ABORT_EN, true); +- writel_relaxed(M_CMD_ABORT_EN, uport->membase + +- SE_GENI_M_IRQ_CLEAR); ++ writel(M_CMD_ABORT_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); + } +- writel_relaxed(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); ++ writel(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); + } + + static void qcom_geni_serial_start_rx(struct uart_port *uport) +@@ -632,26 +613,20 @@ static void qcom_geni_serial_start_rx(struct uart_port *uport) + u32 status; + struct qcom_geni_serial_port *port = to_dev_port(uport, uport); + +- status = readl_relaxed(uport->membase + SE_GENI_STATUS); ++ status = readl(uport->membase + SE_GENI_STATUS); + if (status & S_GENI_CMD_ACTIVE) + qcom_geni_serial_stop_rx(uport); + +- /* +- * Ensure setup command write is not re-ordered before checking +- * the status of the Secondary Sequencer. +- */ +- mb(); +- + geni_se_setup_s_cmd(&port->se, UART_START_READ, 0); + + if (port->xfer_mode == GENI_SE_FIFO) { +- irq_en = readl_relaxed(uport->membase + SE_GENI_S_IRQ_EN); ++ irq_en = readl(uport->membase + SE_GENI_S_IRQ_EN); + irq_en |= S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN; +- writel_relaxed(irq_en, uport->membase + SE_GENI_S_IRQ_EN); ++ writel(irq_en, uport->membase + SE_GENI_S_IRQ_EN); + +- irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); ++ irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); + irq_en |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN; +- writel_relaxed(irq_en, uport->membase + SE_GENI_M_IRQ_EN); ++ writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN); + } + } + +@@ -663,31 +638,25 @@ static void qcom_geni_serial_stop_rx(struct uart_port *uport) + u32 irq_clear = S_CMD_DONE_EN; + + if (port->xfer_mode == GENI_SE_FIFO) { +- irq_en = readl_relaxed(uport->membase + SE_GENI_S_IRQ_EN); ++ irq_en = readl(uport->membase + SE_GENI_S_IRQ_EN); + irq_en &= ~(S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN); +- writel_relaxed(irq_en, uport->membase + SE_GENI_S_IRQ_EN); ++ writel(irq_en, uport->membase + SE_GENI_S_IRQ_EN); + +- irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); ++ irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); + irq_en &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN); +- writel_relaxed(irq_en, uport->membase + SE_GENI_M_IRQ_EN); ++ writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN); + } + +- status = readl_relaxed(uport->membase + SE_GENI_STATUS); ++ status = readl(uport->membase + SE_GENI_STATUS); + /* Possible stop rx is called multiple times. */ + if (!(status & S_GENI_CMD_ACTIVE)) + return; + +- /* +- * Ensure cancel command write is not re-ordered before checking +- * the status of the Secondary Sequencer. +- */ +- mb(); +- + geni_se_cancel_s_cmd(&port->se); + qcom_geni_serial_poll_bit(uport, SE_GENI_S_CMD_CTRL_REG, + S_GENI_CMD_CANCEL, false); +- status = readl_relaxed(uport->membase + SE_GENI_STATUS); +- writel_relaxed(irq_clear, uport->membase + SE_GENI_S_IRQ_CLEAR); ++ status = readl(uport->membase + SE_GENI_STATUS); ++ writel(irq_clear, uport->membase + SE_GENI_S_IRQ_CLEAR); + if (status & S_GENI_CMD_ACTIVE) + qcom_geni_serial_abort_rx(uport); + } +@@ -701,7 +670,7 @@ static void qcom_geni_serial_handle_rx(struct uart_port *uport, bool drop) + u32 total_bytes; + struct qcom_geni_serial_port *port = to_dev_port(uport, uport); + +- status = readl_relaxed(uport->membase + SE_GENI_RX_FIFO_STATUS); ++ status = readl(uport->membase + SE_GENI_RX_FIFO_STATUS); + word_cnt = status & RX_FIFO_WC_MSK; + last_word_partial = status & RX_LAST; + last_word_byte_cnt = (status & RX_LAST_BYTE_VALID_MSK) >> +@@ -731,7 +700,7 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done, + unsigned int chunk; + int tail; + +- status = readl_relaxed(uport->membase + SE_GENI_TX_FIFO_STATUS); ++ status = readl(uport->membase + SE_GENI_TX_FIFO_STATUS); + + /* Complete the current tx command before taking newly added data */ + if (active) +@@ -757,9 +726,9 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done, + qcom_geni_serial_setup_tx(uport, pending); + port->tx_remaining = pending; + +- irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); ++ irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); + if (!(irq_en & M_TX_FIFO_WATERMARK_EN)) +- writel_relaxed(irq_en | M_TX_FIFO_WATERMARK_EN, ++ writel(irq_en | M_TX_FIFO_WATERMARK_EN, + uport->membase + SE_GENI_M_IRQ_EN); + } + +@@ -790,14 +759,14 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done, + * cleared it in qcom_geni_serial_isr it will have already reasserted + * so we must clear it again here after our writes. + */ +- writel_relaxed(M_TX_FIFO_WATERMARK_EN, ++ writel(M_TX_FIFO_WATERMARK_EN, + uport->membase + SE_GENI_M_IRQ_CLEAR); + + out_write_wakeup: + if (!port->tx_remaining) { +- irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); ++ irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); + if (irq_en & M_TX_FIFO_WATERMARK_EN) +- writel_relaxed(irq_en & ~M_TX_FIFO_WATERMARK_EN, ++ writel(irq_en & ~M_TX_FIFO_WATERMARK_EN, + uport->membase + SE_GENI_M_IRQ_EN); + } + +@@ -821,12 +790,12 @@ static irqreturn_t qcom_geni_serial_isr(int isr, void *dev) + return IRQ_NONE; + + spin_lock_irqsave(&uport->lock, flags); +- m_irq_status = readl_relaxed(uport->membase + SE_GENI_M_IRQ_STATUS); +- s_irq_status = readl_relaxed(uport->membase + SE_GENI_S_IRQ_STATUS); +- geni_status = readl_relaxed(uport->membase + SE_GENI_STATUS); +- m_irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); +- writel_relaxed(m_irq_status, uport->membase + SE_GENI_M_IRQ_CLEAR); +- writel_relaxed(s_irq_status, uport->membase + SE_GENI_S_IRQ_CLEAR); ++ m_irq_status = readl(uport->membase + SE_GENI_M_IRQ_STATUS); ++ s_irq_status = readl(uport->membase + SE_GENI_S_IRQ_STATUS); ++ geni_status = readl(uport->membase + SE_GENI_STATUS); ++ m_irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); ++ writel(m_irq_status, uport->membase + SE_GENI_M_IRQ_CLEAR); ++ writel(s_irq_status, uport->membase + SE_GENI_S_IRQ_CLEAR); + + if (WARN_ON(m_irq_status & M_ILLEGAL_CMD_EN)) + goto out_unlock; +@@ -921,7 +890,7 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport) + get_tx_fifo_size(port); + + set_rfr_wm(port); +- writel_relaxed(rxstale, uport->membase + SE_UART_RX_STALE_CNT); ++ writel(rxstale, uport->membase + SE_UART_RX_STALE_CNT); + /* + * Make an unconditional cancel on the main sequencer to reset + * it else we could end up in data loss scenarios. +@@ -1025,10 +994,10 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport, + ser_clk_cfg |= clk_div << CLK_DIV_SHFT; + + /* parity */ +- tx_trans_cfg = readl_relaxed(uport->membase + SE_UART_TX_TRANS_CFG); +- tx_parity_cfg = readl_relaxed(uport->membase + SE_UART_TX_PARITY_CFG); +- rx_trans_cfg = readl_relaxed(uport->membase + SE_UART_RX_TRANS_CFG); +- rx_parity_cfg = readl_relaxed(uport->membase + SE_UART_RX_PARITY_CFG); ++ tx_trans_cfg = readl(uport->membase + SE_UART_TX_TRANS_CFG); ++ tx_parity_cfg = readl(uport->membase + SE_UART_TX_PARITY_CFG); ++ rx_trans_cfg = readl(uport->membase + SE_UART_RX_TRANS_CFG); ++ rx_parity_cfg = readl(uport->membase + SE_UART_RX_PARITY_CFG); + if (termios->c_cflag & PARENB) { + tx_trans_cfg |= UART_TX_PAR_EN; + rx_trans_cfg |= UART_RX_PAR_EN; +@@ -1084,17 +1053,17 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport, + uart_update_timeout(uport, termios->c_cflag, baud); + + if (!uart_console(uport)) +- writel_relaxed(port->loopback, ++ writel(port->loopback, + uport->membase + SE_UART_LOOPBACK_CFG); +- writel_relaxed(tx_trans_cfg, uport->membase + SE_UART_TX_TRANS_CFG); +- writel_relaxed(tx_parity_cfg, uport->membase + SE_UART_TX_PARITY_CFG); +- writel_relaxed(rx_trans_cfg, uport->membase + SE_UART_RX_TRANS_CFG); +- writel_relaxed(rx_parity_cfg, uport->membase + SE_UART_RX_PARITY_CFG); +- writel_relaxed(bits_per_char, uport->membase + SE_UART_TX_WORD_LEN); +- writel_relaxed(bits_per_char, uport->membase + SE_UART_RX_WORD_LEN); +- writel_relaxed(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN); +- writel_relaxed(ser_clk_cfg, uport->membase + GENI_SER_M_CLK_CFG); +- writel_relaxed(ser_clk_cfg, uport->membase + GENI_SER_S_CLK_CFG); ++ writel(tx_trans_cfg, uport->membase + SE_UART_TX_TRANS_CFG); ++ writel(tx_parity_cfg, uport->membase + SE_UART_TX_PARITY_CFG); ++ writel(rx_trans_cfg, uport->membase + SE_UART_RX_TRANS_CFG); ++ writel(rx_parity_cfg, uport->membase + SE_UART_RX_PARITY_CFG); ++ writel(bits_per_char, uport->membase + SE_UART_TX_WORD_LEN); ++ writel(bits_per_char, uport->membase + SE_UART_RX_WORD_LEN); ++ writel(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN); ++ writel(ser_clk_cfg, uport->membase + GENI_SER_M_CLK_CFG); ++ writel(ser_clk_cfg, uport->membase + GENI_SER_S_CLK_CFG); + out_restart_rx: + qcom_geni_serial_start_rx(uport); + } +@@ -1185,13 +1154,13 @@ static int __init qcom_geni_serial_earlycon_setup(struct earlycon_device *dev, + geni_se_init(&se, DEF_FIFO_DEPTH_WORDS / 2, DEF_FIFO_DEPTH_WORDS - 2); + geni_se_select_mode(&se, GENI_SE_FIFO); + +- writel_relaxed(tx_trans_cfg, uport->membase + SE_UART_TX_TRANS_CFG); +- writel_relaxed(tx_parity_cfg, uport->membase + SE_UART_TX_PARITY_CFG); +- writel_relaxed(rx_trans_cfg, uport->membase + SE_UART_RX_TRANS_CFG); +- writel_relaxed(rx_parity_cfg, uport->membase + SE_UART_RX_PARITY_CFG); +- writel_relaxed(bits_per_char, uport->membase + SE_UART_TX_WORD_LEN); +- writel_relaxed(bits_per_char, uport->membase + SE_UART_RX_WORD_LEN); +- writel_relaxed(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN); ++ writel(tx_trans_cfg, uport->membase + SE_UART_TX_TRANS_CFG); ++ writel(tx_parity_cfg, uport->membase + SE_UART_TX_PARITY_CFG); ++ writel(rx_trans_cfg, uport->membase + SE_UART_RX_TRANS_CFG); ++ writel(rx_parity_cfg, uport->membase + SE_UART_RX_PARITY_CFG); ++ writel(bits_per_char, uport->membase + SE_UART_TX_WORD_LEN); ++ writel(bits_per_char, uport->membase + SE_UART_RX_WORD_LEN); ++ writel(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN); + + dev->con->write = qcom_geni_serial_earlycon_write; + dev->con->setup = NULL; +-- +2.20.1 + diff --git a/queue-4.19/tty-serial-qcom_geni_serial-remove-xfer_mode-variabl.patch b/queue-4.19/tty-serial-qcom_geni_serial-remove-xfer_mode-variabl.patch new file mode 100644 index 00000000000..e774ddcf6fd --- /dev/null +++ b/queue-4.19/tty-serial-qcom_geni_serial-remove-xfer_mode-variabl.patch @@ -0,0 +1,151 @@ +From 916215111278a6268997e8e4f05354cea4412d1d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Jan 2019 17:58:37 -0800 +Subject: tty: serial: qcom_geni_serial: Remove xfer_mode variable + +From: Ryan Case + +[ Upstream commit bdc05a8a3f822ca0662464055f902faf760da6be ] + +The driver only supports FIFO mode so setting and checking this variable +is unnecessary. If DMA support is ever added then such checks can be +introduced. + +Signed-off-by: Ryan Case +Reviewed-by: Evan Green +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/qcom_geni_serial.c | 67 ++++++++++----------------- + 1 file changed, 24 insertions(+), 43 deletions(-) + +diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c +index 080fa1d1ecbfd..4182129925dec 100644 +--- a/drivers/tty/serial/qcom_geni_serial.c ++++ b/drivers/tty/serial/qcom_geni_serial.c +@@ -101,7 +101,6 @@ struct qcom_geni_serial_port { + u32 tx_fifo_depth; + u32 tx_fifo_width; + u32 rx_fifo_depth; +- enum geni_se_xfer_mode xfer_mode; + bool setup; + int (*handle_rx)(struct uart_port *uport, u32 bytes, bool drop); + unsigned int baud; +@@ -547,29 +546,20 @@ static int handle_rx_uart(struct uart_port *uport, u32 bytes, bool drop) + static void qcom_geni_serial_start_tx(struct uart_port *uport) + { + u32 irq_en; +- struct qcom_geni_serial_port *port = to_dev_port(uport, uport); + u32 status; + +- if (port->xfer_mode == GENI_SE_FIFO) { +- /* +- * readl ensures reading & writing of IRQ_EN register +- * is not re-ordered before checking the status of the +- * Serial Engine. +- */ +- status = readl(uport->membase + SE_GENI_STATUS); +- if (status & M_GENI_CMD_ACTIVE) +- return; ++ status = readl(uport->membase + SE_GENI_STATUS); ++ if (status & M_GENI_CMD_ACTIVE) ++ return; + +- if (!qcom_geni_serial_tx_empty(uport)) +- return; ++ if (!qcom_geni_serial_tx_empty(uport)) ++ return; + +- irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); +- irq_en |= M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN; ++ irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); ++ irq_en |= M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN; + +- writel(DEF_TX_WM, uport->membase + +- SE_GENI_TX_WATERMARK_REG); +- writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN); +- } ++ writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG); ++ writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN); + } + + static void qcom_geni_serial_stop_tx(struct uart_port *uport) +@@ -579,12 +569,8 @@ static void qcom_geni_serial_stop_tx(struct uart_port *uport) + struct qcom_geni_serial_port *port = to_dev_port(uport, uport); + + irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); +- irq_en &= ~M_CMD_DONE_EN; +- if (port->xfer_mode == GENI_SE_FIFO) { +- irq_en &= ~M_TX_FIFO_WATERMARK_EN; +- writel(0, uport->membase + +- SE_GENI_TX_WATERMARK_REG); +- } ++ irq_en &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN); ++ writel(0, uport->membase + SE_GENI_TX_WATERMARK_REG); + writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN); + status = readl(uport->membase + SE_GENI_STATUS); + /* Possible stop tx is called multiple times. */ +@@ -614,15 +600,13 @@ static void qcom_geni_serial_start_rx(struct uart_port *uport) + + geni_se_setup_s_cmd(&port->se, UART_START_READ, 0); + +- if (port->xfer_mode == GENI_SE_FIFO) { +- irq_en = readl(uport->membase + SE_GENI_S_IRQ_EN); +- irq_en |= S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN; +- writel(irq_en, uport->membase + SE_GENI_S_IRQ_EN); ++ irq_en = readl(uport->membase + SE_GENI_S_IRQ_EN); ++ irq_en |= S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN; ++ writel(irq_en, uport->membase + SE_GENI_S_IRQ_EN); + +- irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); +- irq_en |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN; +- writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN); +- } ++ irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); ++ irq_en |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN; ++ writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN); + } + + static void qcom_geni_serial_stop_rx(struct uart_port *uport) +@@ -632,15 +616,13 @@ static void qcom_geni_serial_stop_rx(struct uart_port *uport) + struct qcom_geni_serial_port *port = to_dev_port(uport, uport); + u32 irq_clear = S_CMD_DONE_EN; + +- if (port->xfer_mode == GENI_SE_FIFO) { +- irq_en = readl(uport->membase + SE_GENI_S_IRQ_EN); +- irq_en &= ~(S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN); +- writel(irq_en, uport->membase + SE_GENI_S_IRQ_EN); ++ irq_en = readl(uport->membase + SE_GENI_S_IRQ_EN); ++ irq_en &= ~(S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN); ++ writel(irq_en, uport->membase + SE_GENI_S_IRQ_EN); + +- irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); +- irq_en &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN); +- writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN); +- } ++ irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); ++ irq_en &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN); ++ writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN); + + status = readl(uport->membase + SE_GENI_STATUS); + /* Possible stop rx is called multiple times. */ +@@ -878,7 +860,6 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport) + * Make an unconditional cancel on the main sequencer to reset + * it else we could end up in data loss scenarios. + */ +- port->xfer_mode = GENI_SE_FIFO; + if (uart_console(uport)) + qcom_geni_serial_poll_tx_done(uport); + geni_se_config_packing(&port->se, BITS_PER_BYTE, port->tx_bytes_pw, +@@ -886,7 +867,7 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport) + geni_se_config_packing(&port->se, BITS_PER_BYTE, port->rx_bytes_pw, + false, false, true); + geni_se_init(&port->se, UART_RX_WM, port->rx_fifo_depth - 2); +- geni_se_select_mode(&port->se, port->xfer_mode); ++ geni_se_select_mode(&port->se, GENI_SE_FIFO); + if (!uart_console(uport)) { + port->rx_fifo = devm_kcalloc(uport->dev, + port->rx_fifo_depth, sizeof(u32), GFP_KERNEL); +-- +2.20.1 +