| From c9723750a699c3bd465493ac2be8992b72ccb105 Mon Sep 17 00:00:00 2001 |
| From: Martin Fuzzey <martin.fuzzey@flowbird.group> |
| Date: Wed, 30 Sep 2020 10:36:46 +0200 |
| Subject: w1: mxc_w1: Fix timeout resolution problem leading to bus error |
| |
| From: Martin Fuzzey <martin.fuzzey@flowbird.group> |
| |
| commit c9723750a699c3bd465493ac2be8992b72ccb105 upstream. |
| |
| On my platform (i.MX53) bus access sometimes fails with |
| w1_search: max_slave_count 64 reached, will continue next search. |
| |
| The reason is the use of jiffies to implement a 200us timeout in |
| mxc_w1_ds2_touch_bit(). |
| On some platforms the jiffies timer resolution is insufficient for this. |
| |
| Fix by replacing jiffies by ktime_get(). |
| |
| For consistency apply the same change to the other use of jiffies in |
| mxc_w1_ds2_reset_bus(). |
| |
| Fixes: f80b2581a706 ("w1: mxc_w1: Optimize mxc_w1_ds2_touch_bit()") |
| Cc: stable <stable@vger.kernel.org> |
| Signed-off-by: Martin Fuzzey <martin.fuzzey@flowbird.group> |
| Link: https://lore.kernel.org/r/1601455030-6607-1-git-send-email-martin.fuzzey@flowbird.group |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/w1/masters/mxc_w1.c | 14 +++++++------- |
| 1 file changed, 7 insertions(+), 7 deletions(-) |
| |
| --- a/drivers/w1/masters/mxc_w1.c |
| +++ b/drivers/w1/masters/mxc_w1.c |
| @@ -7,7 +7,7 @@ |
| #include <linux/clk.h> |
| #include <linux/delay.h> |
| #include <linux/io.h> |
| -#include <linux/jiffies.h> |
| +#include <linux/ktime.h> |
| #include <linux/module.h> |
| #include <linux/mod_devicetable.h> |
| #include <linux/platform_device.h> |
| @@ -40,12 +40,12 @@ struct mxc_w1_device { |
| static u8 mxc_w1_ds2_reset_bus(void *data) |
| { |
| struct mxc_w1_device *dev = data; |
| - unsigned long timeout; |
| + ktime_t timeout; |
| |
| writeb(MXC_W1_CONTROL_RPP, dev->regs + MXC_W1_CONTROL); |
| |
| /* Wait for reset sequence 511+512us, use 1500us for sure */ |
| - timeout = jiffies + usecs_to_jiffies(1500); |
| + timeout = ktime_add_us(ktime_get(), 1500); |
| |
| udelay(511 + 512); |
| |
| @@ -55,7 +55,7 @@ static u8 mxc_w1_ds2_reset_bus(void *dat |
| /* PST bit is valid after the RPP bit is self-cleared */ |
| if (!(ctrl & MXC_W1_CONTROL_RPP)) |
| return !(ctrl & MXC_W1_CONTROL_PST); |
| - } while (time_is_after_jiffies(timeout)); |
| + } while (ktime_before(ktime_get(), timeout)); |
| |
| return 1; |
| } |
| @@ -68,12 +68,12 @@ static u8 mxc_w1_ds2_reset_bus(void *dat |
| static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit) |
| { |
| struct mxc_w1_device *dev = data; |
| - unsigned long timeout; |
| + ktime_t timeout; |
| |
| writeb(MXC_W1_CONTROL_WR(bit), dev->regs + MXC_W1_CONTROL); |
| |
| /* Wait for read/write bit (60us, Max 120us), use 200us for sure */ |
| - timeout = jiffies + usecs_to_jiffies(200); |
| + timeout = ktime_add_us(ktime_get(), 200); |
| |
| udelay(60); |
| |
| @@ -83,7 +83,7 @@ static u8 mxc_w1_ds2_touch_bit(void *dat |
| /* RDST bit is valid after the WR1/RD bit is self-cleared */ |
| if (!(ctrl & MXC_W1_CONTROL_WR(bit))) |
| return !!(ctrl & MXC_W1_CONTROL_RDST); |
| - } while (time_is_after_jiffies(timeout)); |
| + } while (ktime_before(ktime_get(), timeout)); |
| |
| return 0; |
| } |