serial: max310x: prevent infinite while() loop in port startup
If there is a problem after resetting a port, the do/while() loop that
checks the default value of DIVLSB register may run forever and spam the
I2C bus.
Add a delay before each read of DIVLSB, and a maximum number of tries to
prevent that situation from happening.
Also fail probe if port reset is unsuccessful.
Fixes: 10d8b34a42
("serial: max310x: Driver rework")
Cc: stable@vger.kernel.org
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Link: https://lore.kernel.org/r/20240116213001.3691629-5-hugo@hugovil.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
8afa6c6dec
commit
b35f8dbbce
@ -237,6 +237,10 @@
|
||||
#define MAX310x_REV_MASK (0xf8)
|
||||
#define MAX310X_WRITE_BIT 0x80
|
||||
|
||||
/* Port startup definitions */
|
||||
#define MAX310X_PORT_STARTUP_WAIT_RETRIES 20 /* Number of retries */
|
||||
#define MAX310X_PORT_STARTUP_WAIT_DELAY_MS 10 /* Delay between retries */
|
||||
|
||||
/* Crystal-related definitions */
|
||||
#define MAX310X_XTAL_WAIT_RETRIES 20 /* Number of retries */
|
||||
#define MAX310X_XTAL_WAIT_DELAY_MS 10 /* Delay between retries */
|
||||
@ -1346,6 +1350,9 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
|
||||
goto out_clk;
|
||||
|
||||
for (i = 0; i < devtype->nr; i++) {
|
||||
bool started = false;
|
||||
unsigned int try = 0, val = 0;
|
||||
|
||||
/* Reset port */
|
||||
regmap_write(regmaps[i], MAX310X_MODE2_REG,
|
||||
MAX310X_MODE2_RST_BIT);
|
||||
@ -1354,8 +1361,17 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
|
||||
|
||||
/* Wait for port startup */
|
||||
do {
|
||||
regmap_read(regmaps[i], MAX310X_BRGDIVLSB_REG, &ret);
|
||||
} while (ret != 0x01);
|
||||
msleep(MAX310X_PORT_STARTUP_WAIT_DELAY_MS);
|
||||
regmap_read(regmaps[i], MAX310X_BRGDIVLSB_REG, &val);
|
||||
|
||||
if (val == 0x01)
|
||||
started = true;
|
||||
} while (!started && (++try < MAX310X_PORT_STARTUP_WAIT_RETRIES));
|
||||
|
||||
if (!started) {
|
||||
ret = dev_err_probe(dev, -EAGAIN, "port reset failed\n");
|
||||
goto out_uart;
|
||||
}
|
||||
|
||||
regmap_write(regmaps[i], MAX310X_MODE1_REG, devtype->mode1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user