Skip to content

Commit

Permalink
w1: mxc_w1: Fix timeout resolution problem leading to bus error
Browse files Browse the repository at this point in the history
commit c972375 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: f80b258 ("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>
  • Loading branch information
Martin Fuzzey authored and gregkh committed Nov 5, 2020
1 parent 0c399a6 commit 7a5b764
Showing 1 changed file with 7 additions and 7 deletions.
14 changes: 7 additions & 7 deletions drivers/w1/masters/mxc_w1.c
Expand Up @@ -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>
Expand Down Expand Up @@ -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);

Expand All @@ -55,7 +55,7 @@ static u8 mxc_w1_ds2_reset_bus(void *data)
/* 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;
}
Expand All @@ -68,12 +68,12 @@ static u8 mxc_w1_ds2_reset_bus(void *data)
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);

Expand All @@ -83,7 +83,7 @@ static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit)
/* 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;
}
Expand Down

0 comments on commit 7a5b764

Please sign in to comment.