From fc12d4bb3227f21e1e7d6d78231074ca542c060d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 28 Feb 2023 15:43:08 +0100 Subject: spi: Replace spi_pcpu_stats_totalize() macro by a C function 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 Link: https://lore.kernel.org/r/cb7690d9d04c06eec23dbb98fbb5444082125cff.1677594432.git.geert+renesas@glider.be Signed-off-by: Mark Brown --- drivers/spi/spi.c | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 44b85a8d47f1..798030c0c5ce 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) -- cgit v1.2.3 From c7cc588bf0054ce33a11b98d05859105c046c706 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 6 Mar 2023 20:29:13 +0200 Subject: spi: Propagate firmware node Propagate firmware node by using a specific API call, i.e. device_set_node(). Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20230306182913.87231-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 798030c0c5ce..295d02e7f0a8 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2368,8 +2368,8 @@ of_register_spi_device(struct spi_controller *ctlr, struct device_node *nc) /* Store a pointer to the node in the device structure */ of_node_get(nc); - spi->dev.of_node = nc; - spi->dev.fwnode = of_fwnode_handle(nc); + + device_set_node(&spi->dev, of_fwnode_handle(nc)); /* Register the new device */ rc = spi_add_device(spi); -- cgit v1.2.3 From 20064c47f63e995216e0dfb0a6ea37b653ed534c Mon Sep 17 00:00:00 2001 From: William Zhang Date: Mon, 6 Mar 2023 17:20:04 -0800 Subject: spi: Fix cocci warnings cocci reported warning: !A || A && B is equivalent to !A || B. This fix simplified the condition check to !A || B. Fixes: 76a85704cb91 ("spi: spi-mem: Allow controller supporting mem_ops without exec_op") Reported-by: kernel test robot Link: https://lore.kernel.org/oe-kbuild-all/202303010051.HrHWSr9y-lkp@intel.com/ Signed-off-by: William Zhang Link: https://lore.kernel.org/r/20230307012004.414502-1-william.zhang@broadcom.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 295d02e7f0a8..c725b4bab7af 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -3076,7 +3076,7 @@ static int spi_controller_check_ops(struct spi_controller *ctlr) * If ->mem_ops or ->mem_ops->exec_op is NULL, we request that at least * one of the ->transfer_xxx() method be implemented. */ - if (!ctlr->mem_ops || (ctlr->mem_ops && !ctlr->mem_ops->exec_op)) { + if (!ctlr->mem_ops || !ctlr->mem_ops->exec_op) { if (!ctlr->transfer && !ctlr->transfer_one && !ctlr->transfer_one_message) { return -EINVAL; -- cgit v1.2.3 From 027781f3920ad16f40133890fc87247b8baa2d8d Mon Sep 17 00:00:00 2001 From: Leonard Göhrs Date: Fri, 10 Mar 2023 10:20:52 +0100 Subject: spi: core: add spi_split_transfers_maxwords MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add spi_split_transfers_maxwords() function that splits spi_transfers transparently into multiple transfers that are below a given number of SPI words. This function reuses most of its code from spi_split_transfers_maxsize() and for transfers with eight or less bits per word actually behaves the same. Signed-off-by: Leonard Göhrs Link: https://lore.kernel.org/r/20230310092053.1006459-1-l.goehrs@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/spi/spi.h | 4 ++++ 2 files changed, 53 insertions(+) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index c725b4bab7af..9036d7a50674 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -3622,6 +3622,55 @@ int spi_split_transfers_maxsize(struct spi_controller *ctlr, } EXPORT_SYMBOL_GPL(spi_split_transfers_maxsize); + +/** + * spi_split_transfers_maxwords - split spi transfers into multiple transfers + * when an individual transfer exceeds a + * certain number of SPI words + * @ctlr: the @spi_controller for this transfer + * @msg: the @spi_message to transform + * @maxwords: the number of words to limit each transfer to + * @gfp: GFP allocation flags + * + * Return: status of transformation + */ +int spi_split_transfers_maxwords(struct spi_controller *ctlr, + struct spi_message *msg, + size_t maxwords, + gfp_t gfp) +{ + struct spi_transfer *xfer; + + /* + * Iterate over the transfer_list, + * but note that xfer is advanced to the last transfer inserted + * to avoid checking sizes again unnecessarily (also xfer does + * potentially belong to a different list by the time the + * replacement has happened). + */ + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + size_t maxsize; + int ret; + + if (xfer->bits_per_word <= 8) + maxsize = maxwords; + else if (xfer->bits_per_word <= 16) + maxsize = 2 * maxwords; + else + maxsize = 4 * maxwords; + + if (xfer->len > maxsize) { + ret = __spi_split_transfer_maxsize(ctlr, msg, &xfer, + maxsize, gfp); + if (ret) + return ret; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(spi_split_transfers_maxwords); + /*-------------------------------------------------------------------------*/ /* Core methods for SPI controller protocol drivers. Some of the diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 74bff5a2f53d..873ced6ae4ca 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -1295,6 +1295,10 @@ extern int spi_split_transfers_maxsize(struct spi_controller *ctlr, struct spi_message *msg, size_t maxsize, gfp_t gfp); +extern int spi_split_transfers_maxwords(struct spi_controller *ctlr, + struct spi_message *msg, + size_t maxwords, + gfp_t gfp); /*---------------------------------------------------------------------------*/ -- cgit v1.2.3