linux-spi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] spi: spi-ti-qspi: Fix FLEN and WLEN settings if bits_per_word is overridden
@ 2016-04-05 19:45 Ben Hutchings
       [not found] ` <1459885528.26669.5.camel-4yDnlxn2s6sWdaTGBSpHTA@public.gmane.org>
  0 siblings, 1 reply; 8+ messages in thread
From: Ben Hutchings @ 2016-04-05 19:45 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA, CT kernel

Each transfer can specify 8, 16 or 32 bits per word independently of
the default for the device being addressed.  Currently we always set
the FLEN register field according to the device default.  Also, if
multiple transfers in the same message have differing bits_per_word,
we bitwise-or the different values in the WLEN register field.  Fix
both of these.

Cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Ben Hutchings <ben.hutchings-4yDnlxn2s6sWdaTGBSpHTA@public.gmane.org>
---
Unfortunately I don't have a test setup where bits_per_word is
overridden.  But it is straightforward to verify that the driver is no
longer using spi->bits_per_word.

Ben.

 drivers/spi/spi-ti-qspi.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c
index 64318fcfacf2..e5cefaca0589 100644
--- a/drivers/spi/spi-ti-qspi.c
+++ b/drivers/spi/spi-ti-qspi.c
@@ -94,6 +94,7 @@ struct ti_qspi {
 #define QSPI_FLEN(n)			((n - 1) << 0)
 #define QSPI_WLEN_MAX_BITS		128
 #define QSPI_WLEN_MAX_BYTES		16
+#define QSPI_WLEN_MASK			QSPI_WLEN(QSPI_WLEN_MAX_BITS)
 
 /* STATUS REGISTER */
 #define BUSY				0x01
@@ -373,7 +374,7 @@ static int ti_qspi_start_transfer_one(struct spi_master *master,
 	struct spi_device *spi = m->spi;
 	struct spi_transfer *t;
 	int status = 0, ret;
-	int frame_length;
+	unsigned int frame_length;
 
 	/* setup device control reg */
 	qspi->dc = 0;
@@ -385,9 +386,10 @@ static int ti_qspi_start_transfer_one(struct spi_master *master,
 	if (spi->mode & SPI_CS_HIGH)
 		qspi->dc |= QSPI_CSPOL(spi->chip_select);
 
-	frame_length = (m->frame_length << 3) / spi->bits_per_word;
-
-	frame_length = clamp(frame_length, 0, QSPI_FRAME);
+	frame_length = 0;
+	list_for_each_entry(t, &m->transfers, transfer_list)
+		frame_length += t->len / (t->bits_per_word >> 3);
+	frame_length = min_t(unsigned int, frame_length, QSPI_FRAME);
 
 	/* setup command reg */
 	qspi->cmd = 0;
@@ -399,7 +401,8 @@ static int ti_qspi_start_transfer_one(struct spi_master *master,
 	mutex_lock(&qspi->list_lock);
 
 	list_for_each_entry(t, &m->transfers, transfer_list) {
-		qspi->cmd |= QSPI_WLEN(t->bits_per_word);
+		qspi->cmd = ((qspi->cmd & ~QSPI_WLEN_MASK) |
+			     QSPI_WLEN(t->bits_per_word));
 
 		ret = qspi_transfer_msg(qspi, t);
 		if (ret) {
-- 
2.8.0.rc3



-- 
Ben Hutchings
Software Developer, Codethink Ltd.


--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/2] spi: spi-ti-qspi: Handle truncated frames properly
       [not found] ` <1459885528.26669.5.camel-4yDnlxn2s6sWdaTGBSpHTA@public.gmane.org>
@ 2016-04-05 19:48   ` Ben Hutchings
       [not found]     ` <1459885728.26669.7.camel-4yDnlxn2s6sWdaTGBSpHTA@public.gmane.org>
  2016-04-12  1:30   ` [PATCH 1/2] spi: spi-ti-qspi: Fix FLEN and WLEN settings if bits_per_word is overridden Mark Brown
  1 sibling, 1 reply; 8+ messages in thread
From: Ben Hutchings @ 2016-04-05 19:48 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA, CT kernel

We clamp frame_length to a maximum of 4096, but do not limit the
number of words written or read properly.  This causes 4K reads (which
some m25p80-like flash chips support) to return garbage for the last
few bytes.

Recalculate the length of each transfer, taking the frame length into
account.  Use this length in qspi_{read,write}_msg(), and to increment
spi_message::actual_length.

Cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Ben Hutchings <ben.hutchings-4yDnlxn2s6sWdaTGBSpHTA@public.gmane.org>
---
 drivers/spi/spi-ti-qspi.c | 32 ++++++++++++++++++++------------
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c
index e5cefaca0589..4c0acee7a55f 100644
--- a/drivers/spi/spi-ti-qspi.c
+++ b/drivers/spi/spi-ti-qspi.c
@@ -225,16 +225,16 @@ static inline int ti_qspi_poll_wc(struct ti_qspi *qspi)
 	return  -ETIMEDOUT;
 }
 
-static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
+static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t,
+			  int count)
 {
-	int wlen, count, xfer_len;
+	int wlen, xfer_len;
 	unsigned int cmd;
 	const u8 *txbuf;
 	u32 data;
 
 	txbuf = t->tx_buf;
 	cmd = qspi->cmd | QSPI_WR_SNGL;
-	count = t->len;
 	wlen = t->bits_per_word >> 3;	/* in bytes */
 	xfer_len = wlen;
 
@@ -294,9 +294,10 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
 	return 0;
 }
 
-static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t)
+static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t,
+			 int count)
 {
-	int wlen, count;
+	int wlen;
 	unsigned int cmd;
 	u8 *rxbuf;
 
@@ -313,7 +314,6 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t)
 		cmd |= QSPI_RD_SNGL;
 		break;
 	}
-	count = t->len;
 	wlen = t->bits_per_word >> 3;	/* in bytes */
 
 	while (count) {
@@ -344,12 +344,13 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t)
 	return 0;
 }
 
-static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t)
+static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t,
+			     int count)
 {
 	int ret;
 
 	if (t->tx_buf) {
-		ret = qspi_write_msg(qspi, t);
+		ret = qspi_write_msg(qspi, t, count);
 		if (ret) {
 			dev_dbg(qspi->dev, "Error while writing\n");
 			return ret;
@@ -357,7 +358,7 @@ static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t)
 	}
 
 	if (t->rx_buf) {
-		ret = qspi_read_msg(qspi, t);
+		ret = qspi_read_msg(qspi, t, count);
 		if (ret) {
 			dev_dbg(qspi->dev, "Error while reading\n");
 			return ret;
@@ -374,7 +375,8 @@ static int ti_qspi_start_transfer_one(struct spi_master *master,
 	struct spi_device *spi = m->spi;
 	struct spi_transfer *t;
 	int status = 0, ret;
-	unsigned int frame_length;
+	unsigned int frame_length, transfer_length;
+	int wlen;
 
 	/* setup device control reg */
 	qspi->dc = 0;
@@ -404,14 +406,20 @@ static int ti_qspi_start_transfer_one(struct spi_master *master,
 		qspi->cmd = ((qspi->cmd & ~QSPI_WLEN_MASK) |
 			     QSPI_WLEN(t->bits_per_word));
 
-		ret = qspi_transfer_msg(qspi, t);
+		wlen = t->bits_per_word >> 3;
+		transfer_length = min(t->len / wlen, frame_length);
+
+		ret = qspi_transfer_msg(qspi, t, transfer_length * wlen);
 		if (ret) {
 			dev_dbg(qspi->dev, "transfer message failed\n");
 			mutex_unlock(&qspi->list_lock);
 			return -EINVAL;
 		}
 
-		m->actual_length += t->len;
+		m->actual_length += transfer_length * wlen;
+		frame_length -= transfer_length;
+		if (frame_length == 0)
+			break;
 	}
 
 	mutex_unlock(&qspi->list_lock);
-- 
2.8.0.rc3


-- 
Ben Hutchings
Software Developer, Codethink Ltd.


--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] spi: spi-ti-qspi: Fix FLEN and WLEN settings if bits_per_word is overridden
       [not found] ` <1459885528.26669.5.camel-4yDnlxn2s6sWdaTGBSpHTA@public.gmane.org>
  2016-04-05 19:48   ` [PATCH 2/2] spi: spi-ti-qspi: Handle truncated frames properly Ben Hutchings
@ 2016-04-12  1:30   ` Mark Brown
       [not found]     ` <20160412013014.GR3351-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
  1 sibling, 1 reply; 8+ messages in thread
From: Mark Brown @ 2016-04-12  1:30 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA, CT kernel

[-- Attachment #1: Type: text/plain, Size: 467 bytes --]

On Tue, Apr 05, 2016 at 08:45:28PM +0100, Ben Hutchings wrote:

> +	frame_length = 0;
> +	list_for_each_entry(t, &m->transfers, transfer_list)
> +		frame_length += t->len / (t->bits_per_word >> 3);
> +	frame_length = min_t(unsigned int, frame_length, QSPI_FRAME);
>  

This doesn't seem obviously correct - what exactly is the frame length
here and why doesn't it change per transfer like the word length does?
There's nothing in the changelog about this.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] spi: spi-ti-qspi: Handle truncated frames properly
       [not found]     ` <1459885728.26669.7.camel-4yDnlxn2s6sWdaTGBSpHTA@public.gmane.org>
@ 2016-04-12  1:58       ` Mark Brown
       [not found]         ` <20160412015809.GS3351-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
  0 siblings, 1 reply; 8+ messages in thread
From: Mark Brown @ 2016-04-12  1:58 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA, CT kernel

[-- Attachment #1: Type: text/plain, Size: 1062 bytes --]

On Tue, Apr 05, 2016 at 08:48:48PM +0100, Ben Hutchings wrote:

> We clamp frame_length to a maximum of 4096, but do not limit the
> number of words written or read properly.  This causes 4K reads (which
> some m25p80-like flash chips support) to return garbage for the last
> few bytes.

> Recalculate the length of each transfer, taking the frame length into
> account.  Use this length in qspi_{read,write}_msg(), and to increment
> spi_message::actual_length.

I'm having a hard time understanding what's actually wrong here or how
this change is intended to fix it, I think again because I don't know
what frame_length is intended to be.  As far as I can tell frame_length
is the number of words we're going to transfer in the entire message and
the driver has in some places been mixing up words and bytes which is
causing the breakage so the intention is to consistently use words
throught the driver.  Is that correct?

> -		ret = qspi_transfer_msg(qspi, t);
> +		wlen = t->bits_per_word >> 3;

For the benefit of readers:

	wlen = t->bits_per_word / 8.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] spi: spi-ti-qspi: Fix FLEN and WLEN settings if bits_per_word is overridden
       [not found]     ` <20160412013014.GR3351-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
@ 2016-04-12 11:07       ` Ben Hutchings
       [not found]         ` <1460459249.32355.4.camel-4yDnlxn2s6sWdaTGBSpHTA@public.gmane.org>
  0 siblings, 1 reply; 8+ messages in thread
From: Ben Hutchings @ 2016-04-12 11:07 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA, CT kernel

On Tue, 2016-04-12 at 02:30 +0100, Mark Brown wrote:
> On Tue, Apr 05, 2016 at 08:45:28PM +0100, Ben Hutchings wrote:
> 
> > +	frame_length = 0;
> > +	list_for_each_entry(t, &m->transfers, transfer_list)
> > +		frame_length += t->len / (t->bits_per_word >> 3);
> > +	frame_length = min_t(unsigned int, frame_length, QSPI_FRAME);
> >  
> 
> This doesn't seem obviously correct - what exactly is the frame length
> here and why doesn't it change per transfer like the word length does?
> There's nothing in the changelog about this.

The frame_length is the number of words in the frame, as it was before
this change.  Shall I insert a preparatory patch to give the variables
better names?

Ben.

-- 
Ben Hutchings
Software Developer, Codethink Ltd.


--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] spi: spi-ti-qspi: Handle truncated frames properly
       [not found]         ` <20160412015809.GS3351-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
@ 2016-04-12 11:09           ` Ben Hutchings
       [not found]             ` <1460459364.32355.6.camel-4yDnlxn2s6sWdaTGBSpHTA@public.gmane.org>
  0 siblings, 1 reply; 8+ messages in thread
From: Ben Hutchings @ 2016-04-12 11:09 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA, CT kernel

On Tue, 2016-04-12 at 02:58 +0100, Mark Brown wrote:
> On Tue, Apr 05, 2016 at 08:48:48PM +0100, Ben Hutchings wrote:
> 
> > We clamp frame_length to a maximum of 4096, but do not limit the
> > number of words written or read properly.  This causes 4K reads (which
> > some m25p80-like flash chips support) to return garbage for the last
> > few bytes.
> 
> > Recalculate the length of each transfer, taking the frame length into
> > account.  Use this length in qspi_{read,write}_msg(), and to increment
> > spi_message::actual_length.
> 
> I'm having a hard time understanding what's actually wrong here or how
> this change is intended to fix it,

"4K reads...return garbage"  That's wrong, no?

> I think again because I don't know
> what frame_length is intended to be.  As far as I can tell frame_length
> is the number of words we're going to transfer in the entire message

Yes.

> and the driver has in some places been mixing up words and bytes

No, it's been completely ignoring the (potentially truncated)
frame_length and using the original transfer lengths for each transfer.

> which is
> causing the breakage so the intention is to consistently use words
> throught the driver.  Is that correct?

No.

I'll add a renaming of variables to make it clearer.

Ben.

> > -		ret = qspi_transfer_msg(qspi, t);
> > +		wlen = t->bits_per_word >> 3;
> 
> For the benefit of readers:
> 
> 	wlen = t->bits_per_word / 8.

-- 
Ben Hutchings
Software Developer, Codethink Ltd.


--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] spi: spi-ti-qspi: Handle truncated frames properly
       [not found]             ` <1460459364.32355.6.camel-4yDnlxn2s6sWdaTGBSpHTA@public.gmane.org>
@ 2016-04-13  6:55               ` Mark Brown
  0 siblings, 0 replies; 8+ messages in thread
From: Mark Brown @ 2016-04-13  6:55 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA, CT kernel

[-- Attachment #1: Type: text/plain, Size: 852 bytes --]

On Tue, Apr 12, 2016 at 12:09:24PM +0100, Ben Hutchings wrote:
> On Tue, 2016-04-12 at 02:58 +0100, Mark Brown wrote:
> > On Tue, Apr 05, 2016 at 08:48:48PM +0100, Ben Hutchings wrote:

> > > We clamp frame_length to a maximum of 4096, but do not limit the
> > > number of words written or read properly.  This causes 4K reads (which
> > > some m25p80-like flash chips support) to return garbage for the last
> > > few bytes.

> > > Recalculate the length of each transfer, taking the frame length into
> > > account.  Use this length in qspi_{read,write}_msg(), and to increment
> > > spi_message::actual_length.

> > I'm having a hard time understanding what's actually wrong here or how
> > this change is intended to fix it,

> "4K reads...return garbage"  That's wrong, no?

It doesn't say what the driver is doing wrong which causes the garbage.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] spi: spi-ti-qspi: Fix FLEN and WLEN settings if bits_per_word is overridden
       [not found]         ` <1460459249.32355.4.camel-4yDnlxn2s6sWdaTGBSpHTA@public.gmane.org>
@ 2016-04-13  6:59           ` Mark Brown
  0 siblings, 0 replies; 8+ messages in thread
From: Mark Brown @ 2016-04-13  6:59 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA, CT kernel

[-- Attachment #1: Type: text/plain, Size: 510 bytes --]

On Tue, Apr 12, 2016 at 12:07:29PM +0100, Ben Hutchings wrote:
> On Tue, 2016-04-12 at 02:30 +0100, Mark Brown wrote:

> > This doesn't seem obviously correct - what exactly is the frame length
> > here and why doesn't it change per transfer like the word length does?
> > There's nothing in the changelog about this.

> The frame_length is the number of words in the frame, as it was before
> this change.  Shall I insert a preparatory patch to give the variables
> better names?

I see you did that already.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2016-04-13  6:59 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-04-05 19:45 [PATCH 1/2] spi: spi-ti-qspi: Fix FLEN and WLEN settings if bits_per_word is overridden Ben Hutchings
     [not found] ` <1459885528.26669.5.camel-4yDnlxn2s6sWdaTGBSpHTA@public.gmane.org>
2016-04-05 19:48   ` [PATCH 2/2] spi: spi-ti-qspi: Handle truncated frames properly Ben Hutchings
     [not found]     ` <1459885728.26669.7.camel-4yDnlxn2s6sWdaTGBSpHTA@public.gmane.org>
2016-04-12  1:58       ` Mark Brown
     [not found]         ` <20160412015809.GS3351-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2016-04-12 11:09           ` Ben Hutchings
     [not found]             ` <1460459364.32355.6.camel-4yDnlxn2s6sWdaTGBSpHTA@public.gmane.org>
2016-04-13  6:55               ` Mark Brown
2016-04-12  1:30   ` [PATCH 1/2] spi: spi-ti-qspi: Fix FLEN and WLEN settings if bits_per_word is overridden Mark Brown
     [not found]     ` <20160412013014.GR3351-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2016-04-12 11:07       ` Ben Hutchings
     [not found]         ` <1460459249.32355.4.camel-4yDnlxn2s6sWdaTGBSpHTA@public.gmane.org>
2016-04-13  6:59           ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).