Skip to content

Commit b35f8db

Browse files
hvilleneuvedoogregkh
authored andcommitted
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: 10d8b34 ("serial: max310x: Driver rework") Cc: [email protected] Signed-off-by: Hugo Villeneuve <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 8afa6c6 commit b35f8db

File tree

1 file changed

+18
-2
lines changed

1 file changed

+18
-2
lines changed

drivers/tty/serial/max310x.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,10 @@
237237
#define MAX310x_REV_MASK (0xf8)
238238
#define MAX310X_WRITE_BIT 0x80
239239

240+
/* Port startup definitions */
241+
#define MAX310X_PORT_STARTUP_WAIT_RETRIES 20 /* Number of retries */
242+
#define MAX310X_PORT_STARTUP_WAIT_DELAY_MS 10 /* Delay between retries */
243+
240244
/* Crystal-related definitions */
241245
#define MAX310X_XTAL_WAIT_RETRIES 20 /* Number of retries */
242246
#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
13461350
goto out_clk;
13471351

13481352
for (i = 0; i < devtype->nr; i++) {
1353+
bool started = false;
1354+
unsigned int try = 0, val = 0;
1355+
13491356
/* Reset port */
13501357
regmap_write(regmaps[i], MAX310X_MODE2_REG,
13511358
MAX310X_MODE2_RST_BIT);
@@ -1354,8 +1361,17 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
13541361

13551362
/* Wait for port startup */
13561363
do {
1357-
regmap_read(regmaps[i], MAX310X_BRGDIVLSB_REG, &ret);
1358-
} while (ret != 0x01);
1364+
msleep(MAX310X_PORT_STARTUP_WAIT_DELAY_MS);
1365+
regmap_read(regmaps[i], MAX310X_BRGDIVLSB_REG, &val);
1366+
1367+
if (val == 0x01)
1368+
started = true;
1369+
} while (!started && (++try < MAX310X_PORT_STARTUP_WAIT_RETRIES));
1370+
1371+
if (!started) {
1372+
ret = dev_err_probe(dev, -EAGAIN, "port reset failed\n");
1373+
goto out_uart;
1374+
}
13591375

13601376
regmap_write(regmaps[i], MAX310X_MODE1_REG, devtype->mode1);
13611377
}

0 commit comments

Comments
 (0)