diff mbox series

spi: Replace spi_pcpu_stats_totalize() macro by a C function

Message ID cb7690d9d04c06eec23dbb98fbb5444082125cff.1677594432.git.geert+renesas@glider.be
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.
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)