Skip to content

Commit d944b27

Browse files
khfengWolfram Sang
authored andcommitted
i2c: nvidia-gpu: Handle timeout correctly in gpu_i2c_check_status()
Nvidia card may come with a "phantom" UCSI device, and its driver gets stuck in probe routine, prevents any system PM operations like suspend. There's an unaccounted case that the target time can equal to jiffies in gpu_i2c_check_status(), let's solve that by using readl_poll_timeout() instead of jiffies comparison functions. Fixes: c71bcdc ("i2c: add i2c bus driver for NVIDIA GPU") Suggested-by: Andy Shevchenko <[email protected]> Signed-off-by: Kai-Heng Feng <[email protected]> Reviewed-by: Andy Shevchenko <[email protected]> Reviewed-by: Ajay Gupta <[email protected]> Tested-by: Ajay Gupta <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent 692b65c commit d944b27

File tree

1 file changed

+8
-12
lines changed

1 file changed

+8
-12
lines changed

drivers/i2c/busses/i2c-nvidia-gpu.c

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/delay.h>
99
#include <linux/i2c.h>
1010
#include <linux/interrupt.h>
11+
#include <linux/iopoll.h>
1112
#include <linux/module.h>
1213
#include <linux/pci.h>
1314
#include <linux/platform_device.h>
@@ -75,20 +76,15 @@ static void gpu_enable_i2c_bus(struct gpu_i2c_dev *i2cd)
7576

7677
static int gpu_i2c_check_status(struct gpu_i2c_dev *i2cd)
7778
{
78-
unsigned long target = jiffies + msecs_to_jiffies(1000);
7979
u32 val;
80+
int ret;
8081

81-
do {
82-
val = readl(i2cd->regs + I2C_MST_CNTL);
83-
if (!(val & I2C_MST_CNTL_CYCLE_TRIGGER))
84-
break;
85-
if ((val & I2C_MST_CNTL_STATUS) !=
86-
I2C_MST_CNTL_STATUS_BUS_BUSY)
87-
break;
88-
usleep_range(500, 600);
89-
} while (time_is_after_jiffies(target));
90-
91-
if (time_is_before_jiffies(target)) {
82+
ret = readl_poll_timeout(i2cd->regs + I2C_MST_CNTL, val,
83+
!(val & I2C_MST_CNTL_CYCLE_TRIGGER) ||
84+
(val & I2C_MST_CNTL_STATUS) != I2C_MST_CNTL_STATUS_BUS_BUSY,
85+
500, 1000 * USEC_PER_MSEC);
86+
87+
if (ret) {
9288
dev_err(i2cd->dev, "i2c timeout error %x\n", val);
9389
return -ETIMEDOUT;
9490
}

0 commit comments

Comments
 (0)