Skip to contentSkip to conversation

spi: bcm2835aux: use 64-bit arithmetic instead of 32-bit

PATCH In review Gustavo A. R. Silva 7 participants 13 messages Feb 7, 2018 – Feb 14, 2018

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 spi: bcm2835aux: use 64-bit arithmetic instead of 32-bit

Add suffix ULL to constant 9 in order to give the compiler complete information about the proper arithmetic to use. Notice that this constant is used in a context that expects an expression of type unsigned long long (64 bits, unsigned).

The expression tfr->len * 9 * 1000000 is currently being evaluated using 32-bit arithmetic.

Addresses-Coverity-ID: 1339619

---
 drivers/spi/spi-bcm2835aux.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/spi/spi-bcm2835aux.c +1 -1
index 7428091..a768c23 100644
@@ -363,7 +363,7 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
 	 * chunk getting transferred - in our case the chunk size
 	 * is 3 bytes, so we approximate this by 9 bits/byte
 	 */
-	xfer_time_us = tfr->len * 9 * 1000000;
+	xfer_time_us = tfr->len * 9ULL * 1000000;
 	do_div(xfer_time_us, spi_used_hz);
 
 	/* run in polling mode for short transfers */
Signature · 1 line
2.7.4
Reviewed-by on v1 1/1
#1 lore raw
Quoted 10 lines · Gustavo A. R. Silva

Add suffix ULL to constant 9 in order to give the compiler complete information about the proper arithmetic to use. Notice that this constant is used in a context that expects an expression of type unsigned long long (64 bits, unsigned).

The expression tfr->len * 9 * 1000000 is currently being evaluated using 32-bit arithmetic.

Addresses-Coverity-ID: 1339619

The effect looks like it would be that we would have chosen polling mode instead of waiting for interrupts for some transfers >477 seconds. Seems like a good fix for an unlikely bug.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180208/e27ae2aa/attachment.sig>

#3 lore raw
In reply to Gustavo A. R. Silva
Quoted 9 lines · Gustavo A. R. Silva

Add suffix ULL to constant 9 in order to give the compiler complete information about the proper arithmetic to use. Notice that this constant is used in a context that expects an expression of type unsigned long long (64 bits, unsigned).

The expression tfr->len * 9 * 1000000 is currently being evaluated using 32-bit arithmetic.

Addresses-Coverity-ID: 1339619

What does this number mean? If it is an index into some internal database, please remove it.

Quoted 26 lines
---
 drivers/spi/spi-bcm2835aux.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/spi/spi-bcm2835aux.c +1 -2
index 7428091..a768c23 100644
@@ -363,7 +363,7 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
         * chunk getting transferred - in our case the chunk size
         * is 3 bytes, so we approximate this by 9 bits/byte
         */
-       xfer_time_us = tfr->len * 9 * 1000000;
+       xfer_time_us = tfr->len * 9ULL * 1000000;
        do_div(xfer_time_us, spi_used_hz);
 
        /* run in polling mode for short transfers */
--

2.7.4

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

#2 lore raw
In reply to Eric Anholt

Hi Eric,

Quoted 10 lines · Eric Anholt
Quoted 8 lines · Gustavo A. R. Silva

Add suffix ULL to constant 9 in order to give the compiler complete information about the proper arithmetic to use. Notice that this constant is used in a context that expects an expression of type unsigned long long (64 bits, unsigned).

The expression tfr->len * 9 * 1000000 is currently being evaluated using 32-bit arithmetic.

Quoted 9 lines
Quoted 2 lines

Addresses-Coverity-ID: 1339619

The effect looks like it would be that we would have chosen polling mode instead of waiting for interrupts for some transfers >477 seconds. Seems like a good fix for an unlikely bug.

Thank you for your review.

--
Gustavo

#4 lore raw
In reply to Ard Biesheuvel

Hi Ard,

Quoted 6 lines · Ard Biesheuvel
Quoted 5 lines · Gustavo A. R. Silva

Add suffix ULL to constant 9 in order to give the compiler complete information about the proper arithmetic to use. Notice that this constant is used in a context that expects an expression of type unsigned long long (64 bits, unsigned).

Quoted 8 lines
Quoted 4 lines

The expression tfr->len * 9 * 1000000 is currently being evaluated using 32-bit arithmetic.

Addresses-Coverity-ID: 1339619

What does this number mean? If it is an index into some internal database, please remove it.

This is a unique Coverity identifier. We want to keep information like public Bugzilla IDs and tools like Coverity on the commit message.

Thanks
--
Gustavo

#5 lore raw
Quoted 18 lines · Gustavo A. R. Silva

Hi Ard,

Quoted 15 lines · Ard Biesheuvel
Quoted 10 lines · Gustavo A. R. Silva

Add suffix ULL to constant 9 in order to give the compiler complete information about the proper arithmetic to use. Notice that this constant is used in a context that expects an expression of type unsigned long long (64 bits, unsigned).

The expression tfr->len * 9 * 1000000 is currently being evaluated using 32-bit arithmetic.

Addresses-Coverity-ID: 1339619

Quoted 7 lines
Quoted 3 lines

What does this number mean? If it is an index into some internal database, please remove it.

This is a unique Coverity identifier. We want to keep information like public Bugzilla IDs and tools like Coverity on the commit message.

Who is 'we' in this case? And how is this id to any benefit of other people that have been excluded from 'we'?

If you add identifiers like this, make sure that they don't only make sense to the in-crowd. For instance, you could replace this with a http link to the database entry if you really must.

#6 lore raw
Quoted 24 lines · Ard Biesheuvel
Quoted 22 lines · Gustavo A. R. Silva

Hi Ard,

Quoted 18 lines · Ard Biesheuvel
Quoted 10 lines · Gustavo A. R. Silva

Add suffix ULL to constant 9 in order to give the compiler complete information about the proper arithmetic to use. Notice that this constant is used in a context that expects an expression of type unsigned long long (64 bits, unsigned).

The expression tfr->len * 9 * 1000000 is currently being evaluated using 32-bit arithmetic.

Addresses-Coverity-ID: 1339619

What does this number mean? If it is an index into some internal database, please remove it.

Quoted 6 lines
Quoted 3 lines

This is a unique Coverity identifier. We want to keep information like public Bugzilla IDs and tools like Coverity on the commit message.

Who is 'we' in this case? And how is this id to any benefit of other people that have been excluded from 'we'?

We is probably the greater Linux community here.

Quoted 4 lines

If you add identifiers like this, make sure that they don't only make sense to the in-crowd. For instance, you could replace this with a http link to the database entry if you really must.

I don't think it is that easy to extract good URLs from the public Linux coverity instance which is why referring to coverity IDs is being done AFAICT.

Signature · 1 line
Florian
#7 lore raw
Quoted 35 lines · Florian Fainelli
Quoted 24 lines · Ard Biesheuvel
Quoted 22 lines · Gustavo A. R. Silva

Hi Ard,

Quoted 18 lines · Ard Biesheuvel
Quoted 10 lines · Gustavo A. R. Silva

Add suffix ULL to constant 9 in order to give the compiler complete information about the proper arithmetic to use. Notice that this constant is used in a context that expects an expression of type unsigned long long (64 bits, unsigned).

The expression tfr->len * 9 * 1000000 is currently being evaluated using 32-bit arithmetic.

Addresses-Coverity-ID: 1339619

What does this number mean? If it is an index into some internal database, please remove it.

Quoted 6 lines
Quoted 3 lines

This is a unique Coverity identifier. We want to keep information like public Bugzilla IDs and tools like Coverity on the commit message.

Who is 'we' in this case? And how is this id to any benefit of other people that have been excluded from 'we'?

We is probably the greater Linux community here.

Quoted 1 line
Quoted 7 lines
Quoted 3 lines

If you add identifiers like this, make sure that they don't only make sense to the in-crowd. For instance, you could replace this with a http link to the database entry if you really must.

I don't think it is that easy to extract good URLs from the public Linux coverity instance which is why referring to coverity IDs is being done AFAICT.

Ah ok, pardon my ignorance then. I wasn't aware there is a public Linux coverity instance. Got a link?

#8 lore raw
Quoted 40 lines · Ard Biesheuvel
Quoted 39 lines · Florian Fainelli
Quoted 24 lines · Ard Biesheuvel
Quoted 22 lines · Gustavo A. R. Silva

Hi Ard,

Quoted 18 lines · Ard Biesheuvel
Quoted 10 lines · Gustavo A. R. Silva

Add suffix ULL to constant 9 in order to give the compiler complete information about the proper arithmetic to use. Notice that this constant is used in a context that expects an expression of type unsigned long long (64 bits, unsigned).

The expression tfr->len * 9 * 1000000 is currently being evaluated using 32-bit arithmetic.

Addresses-Coverity-ID: 1339619

What does this number mean? If it is an index into some internal database, please remove it.

Quoted 6 lines
Quoted 3 lines

This is a unique Coverity identifier. We want to keep information like public Bugzilla IDs and tools like Coverity on the commit message.

Who is 'we' in this case? And how is this id to any benefit of other people that have been excluded from 'we'?

We is probably the greater Linux community here.

Quoted 4 lines

If you add identifiers like this, make sure that they don't only make sense to the in-crowd. For instance, you could replace this with a http link to the database entry if you really must.

Quoted 6 lines
Quoted 3 lines

I don't think it is that easy to extract good URLs from the public Linux coverity instance which is why referring to coverity IDs is being done AFAICT.

Ah ok, pardon my ignorance then. I wasn't aware there is a public Linux coverity instance. Got a link?

It requires you to sign up to get notifications and have a dashboard, does this link work for you?

https://scan.coverity.com/projects/linux?tab=overview

Signature · 1 line
Florian
#9 lore raw
In reply to Gustavo A. R. Silva
Quoted 19 lines · Gustavo A. R. Silva

Add suffix ULL to constant 9 in order to give the compiler complete information about the proper arithmetic to use. Notice that this constant is used in a context that expects an expression of type unsigned long long (64 bits, unsigned).

The expression tfr->len * 9 * 1000000 is currently being evaluated using 32-bit arithmetic.

Addresses-Coverity-ID: 1339619

---
 drivers/spi/spi-bcm2835aux.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/spi/spi-bcm2835aux.c +0 -0
index 7428091..a768c23 100644

drivers/spi/spi-bcm2835aux.c static int bcm2835aux_spi_transfer_one(struct spi_master *master, · line 369

Quoted 8 lines
drivers/spi/spi-bcm2835aux.c +1 -1
@@ -363,7 +363,7 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
 	 * chunk getting transferred - in our case the chunk size
 	 * is 3 bytes, so we approximate this by 9 bits/byte
 	 */
-	xfer_time_us = tfr->len * 9 * 1000000;
+	xfer_time_us = tfr->len * 9ULL * 1000000;
 	do_div(xfer_time_us, spi_used_hz);
 
 	/* run in polling mode for short transfers */
	if (xfer_time_us < BCM2835_AUX_SPI_POLLING_LIMIT_US)

If one looks@the logic as a whole...

tfr->len * 9ULL * 100000 / spi_used_hz < 30

A little algebra can change that into:

tfr->len < spi_used_hz / 300000

So rather than add more 64-bit math, it can be removed entirely. Both the length and speed are 32 bits and there's no need to multiply them into something larger than might need 64 bits.

#10 lore raw

PATCH 1/1 spi: bcm2835aux: Avoid 64-bit arithmetic in xfer len calc

We want to check for xfers that are over 30 microseconds. Rather than find how many ?s a xfer will take, instead find how many bytes can be transferred in 30 ?s. The latter must be less than 32 bits (since our clock speed is limited to 32 bits), while the former involves 64 bit quantities and more arithmetic operations.

---
 drivers/spi/spi-bcm2835aux.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)
drivers/spi/spi-bcm2835aux.c +9 -9
index 7428091d3f5b..1431cb98fe40 100644
@@ -321,7 +321,6 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
 	struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
 	unsigned long spi_hz, clk_hz, speed;
 	unsigned long spi_used_hz;
-	unsigned long long xfer_time_us;
 
 	/* calculate the registers to handle
 	 *
@@ -358,20 +357,21 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
 	bs->rx_len = tfr->len;
 	bs->pending = 0;
 
-	/* calculate the estimated time in us the transfer runs
-	 * note that there are are 2 idle clocks after each
-	 * chunk getting transferred - in our case the chunk size
-	 * is 3 bytes, so we approximate this by 9 bits/byte
+	/* Calculate the estimated time in us the transfer runs.  Note that
+	 * there are are 2 idle clocks cycles after each chunk getting
+	 * transferred - in our case the chunk size is 3 bytes, so we
+	 * approximate this by 9 cycles/byte.  This is used to find the number
+	 * of Hz per byte per polling limit.  E.g., we can transfer 1 byte in
+	 * 30 ?s per 300,000 Hz of bus clock.
 	 */
-	xfer_time_us = tfr->len * 9 * 1000000;
-	do_div(xfer_time_us, spi_used_hz);
-
+#define HZ_PER_BYTE ((9 * 1000000) / BCM2835_AUX_SPI_POLLING_LIMIT_US)
 	/* run in polling mode for short transfers */
-	if (xfer_time_us < BCM2835_AUX_SPI_POLLING_LIMIT_US)
+	if (tfr->len < spi_used_hz / HZ_PER_BYTE)
 		return bcm2835aux_spi_transfer_one_poll(master, spi, tfr);
 
 	/* run in interrupt mode for all others */
 	return bcm2835aux_spi_transfer_one_irq(master, spi, tfr);
+#undef HZ_PER_BYTE
 }
 
 static int bcm2835aux_spi_prepare_message(struct spi_master *master,
Signature · 1 line
2.14.3
maintainer
#11 lore raw

Re: [PATCH] spi: bcm2835aux: Avoid 64-bit arithmetic in xfer len calc

Quoted 5 lines · Trent Piepho

We want to check for xfers that are over 30 microseconds. Rather than find how many ?s a xfer will take, instead find how many bytes can be transferred in 30 ?s. The latter must be less than 32 bits (since our clock speed is limited to 32 bits), while the former involves 64 bit quantities and more arithmetic operations.

Please don't bury patches in the middle of existing threads, it makes it
much harder to find them.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180214/0cb94b3d/attachment-0001.sig>

maintainer
#12 lore raw

Applied "spi: bcm2835aux: Avoid 64-bit arithmetic in xfer len calc" to the spi tree

In reply to Trent Piepho

The patch

spi: bcm2835aux: Avoid 64-bit arithmetic in xfer len calc

has been applied to the spi tree at

https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git

All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying to this mail.

Thanks,
Mark

Quoted 1 line

From d704afffe65c8fab424963c1ba4ec4364c2d6a82 Mon Sep 17 00:00:00 2001

From: Trent Piepho <[email protected]>
Date: Mon, 12 Feb 2018 11:38:14 -0800
Subject: [PATCH] spi: bcm2835aux: Avoid 64-bit arithmetic in xfer len calc
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

We want to check for xfers that are over 30 microseconds. Rather than find how many ??s a xfer will take, instead find how many bytes can be transferred in 30 ??s. The latter must be less than 32 bits (since our clock speed is limited to 32 bits), while the former involves 64 bit quantities and more arithmetic operations.

---
 drivers/spi/spi-bcm2835aux.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)
drivers/spi/spi-bcm2835aux.c +9 -9
index 7428091d3f5b..1431cb98fe40 100644
@@ -321,7 +321,6 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
 	struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
 	unsigned long spi_hz, clk_hz, speed;
 	unsigned long spi_used_hz;
-	unsigned long long xfer_time_us;
 
 	/* calculate the registers to handle
 	 *
@@ -358,20 +357,21 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
 	bs->rx_len = tfr->len;
 	bs->pending = 0;
 
-	/* calculate the estimated time in us the transfer runs
-	 * note that there are are 2 idle clocks after each
-	 * chunk getting transferred - in our case the chunk size
-	 * is 3 bytes, so we approximate this by 9 bits/byte
+	/* Calculate the estimated time in us the transfer runs.  Note that
+	 * there are are 2 idle clocks cycles after each chunk getting
+	 * transferred - in our case the chunk size is 3 bytes, so we
+	 * approximate this by 9 cycles/byte.  This is used to find the number
+	 * of Hz per byte per polling limit.  E.g., we can transfer 1 byte in
+	 * 30 ??s per 300,000 Hz of bus clock.
 	 */
-	xfer_time_us = tfr->len * 9 * 1000000;
-	do_div(xfer_time_us, spi_used_hz);
-
+#define HZ_PER_BYTE ((9 * 1000000) / BCM2835_AUX_SPI_POLLING_LIMIT_US)
 	/* run in polling mode for short transfers */
-	if (xfer_time_us < BCM2835_AUX_SPI_POLLING_LIMIT_US)
+	if (tfr->len < spi_used_hz / HZ_PER_BYTE)
 		return bcm2835aux_spi_transfer_one_poll(master, spi, tfr);
 
 	/* run in interrupt mode for all others */
 	return bcm2835aux_spi_transfer_one_irq(master, spi, tfr);
+#undef HZ_PER_BYTE
 }
 
 static int bcm2835aux_spi_prepare_message(struct spi_master *master,
Signature · 1 line
2.16.1