Patch "serial: max310x: fix IO data corruption in batched operations" has been added to the 5.4-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    serial: max310x: fix IO data corruption in batched operations

to the 5.4-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     serial-max310x-fix-io-data-corruption-in-batched-ope.patch
and it can be found in the queue-5.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit d7faa29817ea3f45b730da93db62aab57b9e9f4b
Author: Jan Kundrát <jan.kundrat@xxxxxxxxx>
Date:   Wed Apr 5 22:14:23 2023 +0200

    serial: max310x: fix IO data corruption in batched operations
    
    [ Upstream commit 3f42b142ea1171967e40e10e4b0241c0d6d28d41 ]
    
    After upgrading from 5.16 to 6.1, our board with a MAX14830 started
    producing lots of garbage data over UART. Bisection pointed out commit
    285e76fc049c as the culprit. That patch tried to replace hand-written
    code which I added in 2b4bac48c1084 ("serial: max310x: Use batched reads
    when reasonably safe") with the generic regmap infrastructure for
    batched operations.
    
    Unfortunately, the `regmap_raw_read` and `regmap_raw_write` which were
    used are actually functions which perform IO over *multiple* registers.
    That's not what is needed for accessing these Tx/Rx FIFOs; the
    appropriate functions are the `_noinc_` versions, not the `_raw_` ones.
    
    Fix this regression by using `regmap_noinc_read()` and
    `regmap_noinc_write()` along with the necessary `regmap_config` setup;
    with this patch in place, our board communicates happily again. Since
    our board uses SPI for talking to this chip, the I2C part is completely
    untested.
    
    Fixes: 285e76fc049c ("serial: max310x: use regmap methods for SPI batch operations")
    Cc: stable@xxxxxxxxxxxxxxx
    Reviewed-by: Andy Shevchenko <andy.shevchenko@xxxxxxxxx>
    Signed-off-by: Jan Kundrát <jan.kundrat@xxxxxxxxx>
    Link: https://lore.kernel.org/r/79db8e82aadb0e174bc82b9996423c3503c8fb37.1680732084.git.jan.kundrat@xxxxxxxxx
    Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index ed1aaa19854fd..2f88eae8a55a1 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -533,6 +533,11 @@ static bool max310x_reg_precious(struct device *dev, unsigned int reg)
 	return false;
 }
 
+static bool max310x_reg_noinc(struct device *dev, unsigned int reg)
+{
+	return reg == MAX310X_RHR_REG;
+}
+
 static int max310x_set_baud(struct uart_port *port, int baud)
 {
 	unsigned int mode = 0, div = 0, frac = 0, c = 0, F = 0;
@@ -667,14 +672,14 @@ static void max310x_batch_write(struct uart_port *port, u8 *txbuf, unsigned int
 {
 	struct max310x_one *one = to_max310x_port(port);
 
-	regmap_raw_write(one->regmap, MAX310X_THR_REG, txbuf, len);
+	regmap_noinc_write(one->regmap, MAX310X_THR_REG, txbuf, len);
 }
 
 static void max310x_batch_read(struct uart_port *port, u8 *rxbuf, unsigned int len)
 {
 	struct max310x_one *one = to_max310x_port(port);
 
-	regmap_raw_read(one->regmap, MAX310X_RHR_REG, rxbuf, len);
+	regmap_noinc_read(one->regmap, MAX310X_RHR_REG, rxbuf, len);
 }
 
 static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
@@ -1508,6 +1513,10 @@ static struct regmap_config regcfg = {
 	.writeable_reg = max310x_reg_writeable,
 	.volatile_reg = max310x_reg_volatile,
 	.precious_reg = max310x_reg_precious,
+	.writeable_noinc_reg = max310x_reg_noinc,
+	.readable_noinc_reg = max310x_reg_noinc,
+	.max_raw_read = MAX310X_FIFO_SIZE,
+	.max_raw_write = MAX310X_FIFO_SIZE,
 };
 
 #ifdef CONFIG_SPI_MASTER
@@ -1593,6 +1602,10 @@ static struct regmap_config regcfg_i2c = {
 	.volatile_reg = max310x_reg_volatile,
 	.precious_reg = max310x_reg_precious,
 	.max_register = MAX310X_I2C_REVID_EXTREG,
+	.writeable_noinc_reg = max310x_reg_noinc,
+	.readable_noinc_reg = max310x_reg_noinc,
+	.max_raw_read = MAX310X_FIFO_SIZE,
+	.max_raw_write = MAX310X_FIFO_SIZE,
 };
 
 static const struct max310x_if_cfg max310x_i2c_if_cfg = {




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux