diff mbox series

spi: Replace spi_pcpu_stats_totalize() macro by a C function

Message ID cb7690d9d04c06eec23dbb98fbb5444082125cff.1677594432.git.geert+renesas@glider.be (mailing list archive)
State Accepted
Commit fc12d4bb3227f21e1e7d6d78231074ca542c060d
Headers show
Series spi: Replace spi_pcpu_stats_totalize() macro by a C function | expand

Commit Message

Geert Uytterhoeven Feb. 28, 2023, 2:43 p.m. UTC
spi_pcpu_stats_totalize() is a rather large macro, and is instantiated
28 times, causing a large amount of duplication in the amount of
generated code.

Reduce the duplication by replacing spi_pcpu_stats_totalize() by a real
C function, and absorb all other common code from
spi_statistics_##name##_show().  As (a) the old "field" parameter was
the name of a structure member, which cannot be passed to a function,
and (b) passing a pointer to the member is also not an option, due to
the loop over all possible CPUs, the "field" parameter is replaced by an
"offset" parameter, pointing to a location within the structure.

This reduces kernel size by ca. 4 KiB (on arm32 and arm64).

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Should the address calculation use RELOC_HIDE()? I.e.

    field = RELOC_HIDE((void *)pcpu_stats, offset);
---
 drivers/spi/spi.c | 47 ++++++++++++++++++++++++-----------------------
 1 file changed, 24 insertions(+), 23 deletions(-)

Comments

Mark Brown Feb. 28, 2023, 3:11 p.m. UTC | #1
On Tue, Feb 28, 2023 at 03:43:08PM +0100, Geert Uytterhoeven wrote:

> Should the address calculation use RELOC_HIDE()? I.e.
> 
>     field = RELOC_HIDE((void *)pcpu_stats, offset);

I have no real idea there, I'd hope per_cpu_ptr() was taking care of any
issue there.
Mark Brown March 6, 2023, 1:05 p.m. UTC | #2
On Tue, 28 Feb 2023 15:43:08 +0100, Geert Uytterhoeven wrote:
> spi_pcpu_stats_totalize() is a rather large macro, and is instantiated
> 28 times, causing a large amount of duplication in the amount of
> generated code.
> 
> Reduce the duplication by replacing spi_pcpu_stats_totalize() by a real
> C function, and absorb all other common code from
> spi_statistics_##name##_show().  As (a) the old "field" parameter was
> the name of a structure member, which cannot be passed to a function,
> and (b) passing a pointer to the member is also not an option, due to
> the loop over all possible CPUs, the "field" parameter is replaced by an
> "offset" parameter, pointing to a location within the structure.
> 
> [...]

Applied to

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

Thanks!

[1/1] spi: Replace spi_pcpu_stats_totalize() macro by a C function
      commit: fc12d4bb3227f21e1e7d6d78231074ca542c060d

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
diff mbox series

Patch

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 6d41cef7f9c93934..56d078bac4236a09 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -117,24 +117,28 @@  static struct spi_statistics __percpu *spi_alloc_pcpu_stats(struct device *dev)
 	return pcpu_stats;
 }
 
-#define spi_pcpu_stats_totalize(ret, in, field)				\
-do {									\
-	int i;								\
-	ret = 0;							\
-	for_each_possible_cpu(i) {					\
-		const struct spi_statistics *pcpu_stats;		\
-		u64 inc;						\
-		unsigned int start;					\
-		pcpu_stats = per_cpu_ptr(in, i);			\
-		do {							\
-			start = u64_stats_fetch_begin(		\
-					&pcpu_stats->syncp);		\
-			inc = u64_stats_read(&pcpu_stats->field);	\
-		} while (u64_stats_fetch_retry(			\
-					&pcpu_stats->syncp, start));	\
-		ret += inc;						\
-	}								\
-} while (0)
+static ssize_t spi_emit_pcpu_stats(struct spi_statistics __percpu *stat,
+				   char *buf, size_t offset)
+{
+	u64 val = 0;
+	int i;
+
+	for_each_possible_cpu(i) {
+		const struct spi_statistics *pcpu_stats;
+		u64_stats_t *field;
+		unsigned int start;
+		u64 inc;
+
+		pcpu_stats = per_cpu_ptr(stat, i);
+		field = (void *)pcpu_stats + offset;
+		do {
+			start = u64_stats_fetch_begin(&pcpu_stats->syncp);
+			inc = u64_stats_read(field);
+		} while (u64_stats_fetch_retry(&pcpu_stats->syncp, start));
+		val += inc;
+	}
+	return sysfs_emit(buf, "%llu\n", val);
+}
 
 #define SPI_STATISTICS_ATTRS(field, file)				\
 static ssize_t spi_controller_##field##_show(struct device *dev,	\
@@ -165,11 +169,8 @@  static struct device_attribute dev_attr_spi_device_##field = {		\
 static ssize_t spi_statistics_##name##_show(struct spi_statistics __percpu *stat, \
 					    char *buf)			\
 {									\
-	ssize_t len;							\
-	u64 val;							\
-	spi_pcpu_stats_totalize(val, stat, field);			\
-	len = sysfs_emit(buf, "%llu\n", val);				\
-	return len;							\
+	return spi_emit_pcpu_stats(stat, buf,				\
+			offsetof(struct spi_statistics, field));	\
 }									\
 SPI_STATISTICS_ATTRS(name, file)