From: Wolfram Sang <wsa@the-dreams.de> To: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Cc: linux-sh-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Magnus Damm <magnus.damm-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>, Simon Horman <horms-/R6kz+dDXgpPR4JQBCEnsQ@public.gmane.org>, Laurent Pinchart <laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org>, Geert Uytterhoeven <geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org>, Wolfram Sang <wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org>, Kuninori Morimoto <kuninori.morimoto.gx-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>, Yoshihiro Kaneko <ykaneko0929-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>, Sergei Shtylyov <sergei.shtylyov-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org> Subject: [PATCH 5/9] i2c: rcar: init new messages in irq Date: Thu, 03 Sep 2015 20:20:09 +0000 [thread overview] Message-ID: <1441311613-2681-6-git-send-email-wsa@the-dreams.de> (raw) In-Reply-To: <1441311613-2681-1-git-send-email-wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org> From: Wolfram Sang <wsa+renesas@sang-engineering.com> Setting up new messages was done in process context while handling a message was in interrupt context. Because of the HW design, this IP core is sensitive to timing, so the context switches were too expensive. Move this setup to interrupt context as well. In my test setup, this fixed the occasional 'data byte sent twice' issue which a number of people have seen. It also fixes to send REP_START after a read message which was wrongly send as a STOP + START sequence before. Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com> --- drivers/i2c/busses/i2c-rcar.c | 74 +++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 6e459a338ccc75..36c79301044b71 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -266,6 +266,13 @@ static void rcar_i2c_prepare_msg(struct rcar_i2c_priv *priv) rcar_i2c_write(priv, ICMIER, read ? RCAR_IRQ_RECV : RCAR_IRQ_SEND); } +static void rcar_i2c_next_msg(struct rcar_i2c_priv *priv) +{ + priv->msg++; + priv->msgs_left--; + rcar_i2c_prepare_msg(priv); +} + /* * interrupt functions */ @@ -308,21 +315,17 @@ static int rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr) * [ICRXTX] -> [SHIFT] -> [I2C bus] */ - if (priv->flags & ID_LAST_MSG) + if (priv->flags & ID_LAST_MSG) { /* * If current msg is the _LAST_ msg, * prepare stop condition here. * ID_DONE will be set on STOP irq. */ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP); - else - /* - * If current msg is _NOT_ last msg, - * it doesn't call stop phase. - * thus, there is no STOP irq. - * return ID_DONE here. - */ - return ID_DONE; + } else { + rcar_i2c_next_msg(priv); + return 0; + } } rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_SEND); @@ -366,7 +369,10 @@ static int rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr) else rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA); - rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_RECV); + if (priv->pos = msg->len && !(priv->flags & ID_LAST_MSG)) + rcar_i2c_next_msg(priv); + else + rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_RECV); return 0; } @@ -461,6 +467,7 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr) /* Stop */ if (msr & MST) { + priv->msgs_left--; /* The last message also made it */ rcar_i2c_flags_set(priv, ID_DONE); goto out; } @@ -500,35 +507,28 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, /* This HW can't send STOP after address phase */ if (msgs[i].len = 0) { ret = -EOPNOTSUPP; - break; - } - - /* init each data */ - priv->msg = &msgs[i]; - priv->msgs_left = num - i; - - rcar_i2c_prepare_msg(priv); - - time_left = wait_event_timeout(priv->wait, - rcar_i2c_flags_has(priv, ID_DONE), - adap->timeout); - if (!time_left) { - rcar_i2c_init(priv); - ret = -ETIMEDOUT; - break; - } - - if (rcar_i2c_flags_has(priv, ID_NACK)) { - ret = -ENXIO; - break; - } - - if (rcar_i2c_flags_has(priv, ID_ARBLOST)) { - ret = -EAGAIN; - break; + goto out; } + } - ret = i + 1; /* The number of transfer */ + /* init data */ + priv->msg = msgs; + priv->msgs_left = num; + + rcar_i2c_prepare_msg(priv); + + time_left = wait_event_timeout(priv->wait, + rcar_i2c_flags_has(priv, ID_DONE), + num * adap->timeout); + if (!time_left) { + rcar_i2c_init(priv); + ret = -ETIMEDOUT; + } else if (rcar_i2c_flags_has(priv, ID_NACK)) { + ret = -ENXIO; + } else if (rcar_i2c_flags_has(priv, ID_ARBLOST)) { + ret = -EAGAIN; + } else { + ret = num - priv->msgs_left; /* The number of transfer */ } out: pm_runtime_put(dev); -- 2.1.4
WARNING: multiple messages have this Message-ID (diff)
From: Wolfram Sang <wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org> To: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Cc: linux-sh-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Magnus Damm <magnus.damm-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>, Simon Horman <horms-/R6kz+dDXgpPR4JQBCEnsQ@public.gmane.org>, Laurent Pinchart <laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org>, Geert Uytterhoeven <geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org>, Wolfram Sang <wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org>, Kuninori Morimoto <kuninori.morimoto.gx-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>, Yoshihiro Kaneko <ykaneko0929-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>, Sergei Shtylyov <sergei.shtylyov-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org> Subject: [PATCH 5/9] i2c: rcar: init new messages in irq Date: Thu, 3 Sep 2015 22:20:09 +0200 [thread overview] Message-ID: <1441311613-2681-6-git-send-email-wsa@the-dreams.de> (raw) In-Reply-To: <1441311613-2681-1-git-send-email-wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org> From: Wolfram Sang <wsa+renesas-jBu1N2QxHDJrcw3mvpCnnVaTQe2KTcn/@public.gmane.org> Setting up new messages was done in process context while handling a message was in interrupt context. Because of the HW design, this IP core is sensitive to timing, so the context switches were too expensive. Move this setup to interrupt context as well. In my test setup, this fixed the occasional 'data byte sent twice' issue which a number of people have seen. It also fixes to send REP_START after a read message which was wrongly send as a STOP + START sequence before. Signed-off-by: Wolfram Sang <wsa+renesas-jBu1N2QxHDJrcw3mvpCnnVaTQe2KTcn/@public.gmane.org> --- drivers/i2c/busses/i2c-rcar.c | 74 +++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 6e459a338ccc75..36c79301044b71 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -266,6 +266,13 @@ static void rcar_i2c_prepare_msg(struct rcar_i2c_priv *priv) rcar_i2c_write(priv, ICMIER, read ? RCAR_IRQ_RECV : RCAR_IRQ_SEND); } +static void rcar_i2c_next_msg(struct rcar_i2c_priv *priv) +{ + priv->msg++; + priv->msgs_left--; + rcar_i2c_prepare_msg(priv); +} + /* * interrupt functions */ @@ -308,21 +315,17 @@ static int rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr) * [ICRXTX] -> [SHIFT] -> [I2C bus] */ - if (priv->flags & ID_LAST_MSG) + if (priv->flags & ID_LAST_MSG) { /* * If current msg is the _LAST_ msg, * prepare stop condition here. * ID_DONE will be set on STOP irq. */ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP); - else - /* - * If current msg is _NOT_ last msg, - * it doesn't call stop phase. - * thus, there is no STOP irq. - * return ID_DONE here. - */ - return ID_DONE; + } else { + rcar_i2c_next_msg(priv); + return 0; + } } rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_SEND); @@ -366,7 +369,10 @@ static int rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr) else rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA); - rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_RECV); + if (priv->pos == msg->len && !(priv->flags & ID_LAST_MSG)) + rcar_i2c_next_msg(priv); + else + rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_RECV); return 0; } @@ -461,6 +467,7 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr) /* Stop */ if (msr & MST) { + priv->msgs_left--; /* The last message also made it */ rcar_i2c_flags_set(priv, ID_DONE); goto out; } @@ -500,35 +507,28 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, /* This HW can't send STOP after address phase */ if (msgs[i].len == 0) { ret = -EOPNOTSUPP; - break; - } - - /* init each data */ - priv->msg = &msgs[i]; - priv->msgs_left = num - i; - - rcar_i2c_prepare_msg(priv); - - time_left = wait_event_timeout(priv->wait, - rcar_i2c_flags_has(priv, ID_DONE), - adap->timeout); - if (!time_left) { - rcar_i2c_init(priv); - ret = -ETIMEDOUT; - break; - } - - if (rcar_i2c_flags_has(priv, ID_NACK)) { - ret = -ENXIO; - break; - } - - if (rcar_i2c_flags_has(priv, ID_ARBLOST)) { - ret = -EAGAIN; - break; + goto out; } + } - ret = i + 1; /* The number of transfer */ + /* init data */ + priv->msg = msgs; + priv->msgs_left = num; + + rcar_i2c_prepare_msg(priv); + + time_left = wait_event_timeout(priv->wait, + rcar_i2c_flags_has(priv, ID_DONE), + num * adap->timeout); + if (!time_left) { + rcar_i2c_init(priv); + ret = -ETIMEDOUT; + } else if (rcar_i2c_flags_has(priv, ID_NACK)) { + ret = -ENXIO; + } else if (rcar_i2c_flags_has(priv, ID_ARBLOST)) { + ret = -EAGAIN; + } else { + ret = num - priv->msgs_left; /* The number of transfer */ } out: pm_runtime_put(dev); -- 2.1.4
next prev parent reply other threads:[~2015-09-03 20:20 UTC|newest] Thread overview: 67+ messages / expand[flat|nested] mbox.gz Atom feed top 2015-09-03 20:20 [PATCH 0/9] i2c: rcar: tackle race conditions in the driver Wolfram Sang 2015-09-03 20:20 ` Wolfram Sang 2015-09-03 20:20 ` [PATCH 1/9] i2c: rcar: rework hw init Wolfram Sang 2015-09-03 20:20 ` Wolfram Sang 2015-09-03 20:20 ` [PATCH 2/9] i2c: rcar: remove unused IOERROR state Wolfram Sang 2015-09-03 20:20 ` Wolfram Sang 2015-09-03 20:20 ` [PATCH 6/9] i2c: rcar: don't issue stop when HW does it automatically Wolfram Sang 2015-09-03 20:20 ` Wolfram Sang [not found] ` <1441311613-2681-1-git-send-email-wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org> 2015-09-03 20:20 ` [PATCH 3/9] i2c: rcar: remove spinlock Wolfram Sang 2015-09-03 20:20 ` Wolfram Sang 2015-09-03 20:20 ` [PATCH 4/9] i2c: rcar: refactor setup of a msg Wolfram Sang 2015-09-03 20:20 ` Wolfram Sang 2015-09-03 20:20 ` Wolfram Sang [this message] 2015-09-03 20:20 ` [PATCH 5/9] i2c: rcar: init new messages in irq Wolfram Sang 2015-10-21 23:10 ` Laurent Pinchart 2015-10-21 23:10 ` Laurent Pinchart 2015-10-22 11:05 ` Wolfram Sang 2015-10-22 11:05 ` Wolfram Sang 2015-10-22 11:12 ` Laurent Pinchart 2015-10-22 11:12 ` Laurent Pinchart 2015-10-23 8:06 ` Wolfram Sang 2015-10-23 8:06 ` Wolfram Sang 2015-10-23 8:57 ` Laurent Pinchart 2015-10-23 9:45 ` Wolfram Sang 2015-10-23 9:45 ` Wolfram Sang 2015-10-23 10:28 ` Laurent Pinchart 2015-10-23 10:28 ` Laurent Pinchart 2015-10-23 12:14 ` Wolfram Sang 2015-10-23 12:14 ` Wolfram Sang 2015-10-23 13:14 ` Laurent Pinchart 2015-10-23 13:14 ` Laurent Pinchart 2015-10-25 15:53 ` Wolfram Sang 2015-10-25 15:53 ` Wolfram Sang 2015-10-29 19:23 ` Wolfram Sang 2015-10-29 19:23 ` Wolfram Sang 2015-10-23 10:04 ` Geert Uytterhoeven 2015-10-23 10:04 ` Geert Uytterhoeven 2015-10-23 10:07 ` Wolfram Sang 2015-10-23 10:07 ` Wolfram Sang 2015-09-03 20:20 ` [PATCH 7/9] i2c: rcar: check master irqs before slave irqs Wolfram Sang 2015-09-03 20:20 ` Wolfram Sang 2015-09-03 20:20 ` [PATCH 8/9] i2c: rcar: revoke START request early Wolfram Sang 2015-09-03 20:20 ` Wolfram Sang 2015-09-03 20:20 ` [PATCH 9/9] i2c: rcar: clean up after refactoring Wolfram Sang 2015-09-03 20:20 ` Wolfram Sang 2015-09-03 20:35 ` [PATCH 0/9] i2c: rcar: tackle race conditions in the driver Laurent Pinchart 2015-09-03 20:35 ` Laurent Pinchart 2015-09-03 20:40 ` Wolfram Sang 2015-09-03 20:40 ` Wolfram Sang 2015-09-03 20:47 ` Laurent Pinchart 2015-09-03 20:47 ` Laurent Pinchart 2015-09-03 20:55 ` Wolfram Sang 2015-09-03 20:55 ` Wolfram Sang 2015-09-04 4:33 ` Magnus Damm 2015-09-04 4:33 ` Magnus Damm 2015-09-05 7:31 ` Wolfram Sang 2015-09-05 7:31 ` Wolfram Sang 2015-09-07 16:04 ` Magnus Damm 2015-09-07 16:04 ` Magnus Damm [not found] ` <CANqRtoRs=f=07B=HSLCVg5G4rnhxj6Heod+spYwxHiKFLZqFWg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2015-09-08 10:53 ` Wolfram Sang 2015-09-08 10:53 ` Wolfram Sang 2015-09-09 5:08 ` Magnus Damm 2015-09-09 5:08 ` Magnus Damm 2015-09-09 8:54 ` Wolfram Sang 2015-09-09 8:54 ` Wolfram Sang 2015-10-09 21:34 ` Wolfram Sang 2015-10-09 21:34 ` Wolfram Sang
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1441311613-2681-6-git-send-email-wsa@the-dreams.de \ --to=wsa@the-dreams.de \ --cc=geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org \ --cc=horms-/R6kz+dDXgpPR4JQBCEnsQ@public.gmane.org \ --cc=kuninori.morimoto.gx-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \ --cc=laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org \ --cc=linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \ --cc=linux-sh-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \ --cc=magnus.damm-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \ --cc=sergei.shtylyov-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org \ --cc=wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org \ --cc=ykaneko0929-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.