From 59b1c9be01934222cf773b35de7c8d086dabaef6 Mon Sep 17 00:00:00 2001 From: Stephen Carlson Date: Fri, 10 Mar 2023 11:07:13 -0800 Subject: cmd: pci: Add command to set MPS of all PCIe devices Enable tuning of the PCI Express MPS (Maximum Payload Size) of each device. The Maximum Read Request Size is not altered. The SAFE method uses the largest MPS value supported by all devices in the system for each device. This method is the same algorithm as used by Linux pci=pcie_bus_safe. The PEER2PEER method sets all devices to the minimal (128 byte) MPS, which allows hot plug of devices later that might only support the minimum size, and ensures compatibility of DMA between two devices on the bus. Signed-off-by: Stephen Carlson --- include/pci.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include') diff --git a/include/pci.h b/include/pci.h index c55d6107a49..2f5eb30b83c 100644 --- a/include/pci.h +++ b/include/pci.h @@ -360,6 +360,13 @@ #define PCI_EXP_TYPE_PCIE_BRIDGE 0x8 /* PCI/PCI-X to PCIe Bridge */ #define PCI_EXP_DEVCAP 4 /* Device capabilities */ #define PCI_EXP_DEVCAP_FLR 0x10000000 /* Function Level Reset */ +#define PCI_EXP_DEVCAP_PAYLOAD 0x0007 /* Max payload size supported */ +#define PCI_EXP_DEVCAP_PAYLOAD_128B 0x0000 /* 128 Bytes */ +#define PCI_EXP_DEVCAP_PAYLOAD_256B 0x0001 /* 256 Bytes */ +#define PCI_EXP_DEVCAP_PAYLOAD_512B 0x0002 /* 512 Bytes */ +#define PCI_EXP_DEVCAP_PAYLOAD_1024B 0x0003 /* 1024 Bytes */ +#define PCI_EXP_DEVCAP_PAYLOAD_2048B 0x0004 /* 2048 Bytes */ +#define PCI_EXP_DEVCAP_PAYLOAD_4096B 0x0005 /* 4096 Bytes */ #define PCI_EXP_DEVCTL 8 /* Device Control */ #define PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */ #define PCI_EXP_DEVCTL_PAYLOAD_128B 0x0000 /* 128 Bytes */ -- cgit v1.3.1 From 447dfbc0638f65accaeba1afa3b33840bdb46b6e Mon Sep 17 00:00:00 2001 From: Stephen Carlson Date: Fri, 10 Mar 2023 11:07:15 -0800 Subject: test: Add test for new command pci_mps Adds a test for the new pci_mps command to ensure that it can set the Maximum Payload Size (MPS) of all devices to 256 bytes in the sandbox environment. Enables the pci_mps command in the sandbox environment so that this test can be run. Signed-off-by: Stephen Carlson --- MAINTAINERS | 6 ++++++ configs/sandbox_defconfig | 1 + include/test/suites.h | 2 ++ test/cmd/Makefile | 3 +++ test/cmd/pci_mps.c | 42 ++++++++++++++++++++++++++++++++++++++++++ test/cmd_ut.c | 6 ++++++ 6 files changed, 60 insertions(+) create mode 100644 test/cmd/pci_mps.c (limited to 'include') diff --git a/MAINTAINERS b/MAINTAINERS index 91d40ea4b6e..d2e245e5e90 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1249,6 +1249,12 @@ M: Heiko Schocher S: Maintained F: drivers/pci/pci_mpc85xx.c +PCI MPS +M: Stephen Carlson +S: Maintained +F: cmd/pci_mps.c +F: test/cmd/pci_mps.c + POWER M: Jaehoon Chung S: Maintained diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index b0f588da32e..2141c3d4698 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -78,6 +78,7 @@ CONFIG_CMD_MMC=y CONFIG_CMD_MUX=y CONFIG_CMD_OSD=y CONFIG_CMD_PCI=y +CONFIG_CMD_PCI_MPS=y CONFIG_CMD_READ=y CONFIG_CMD_REMOTEPROC=y CONFIG_CMD_SPI=y diff --git a/include/test/suites.h b/include/test/suites.h index 7c4960c004d..7349ce5aa60 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -48,6 +48,8 @@ int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); +int do_ut_pci_mps(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]); int do_ut_print(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_seama(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_setexpr(struct cmd_tbl *cmdtp, int flag, int argc, diff --git a/test/cmd/Makefile b/test/cmd/Makefile index 7848f348bc4..055adc65a25 100644 --- a/test/cmd/Makefile +++ b/test/cmd/Makefile @@ -14,6 +14,9 @@ obj-$(CONFIG_CMD_FDT) += fdt.o obj-$(CONFIG_CONSOLE_TRUETYPE) += font.o obj-$(CONFIG_CMD_LOADM) += loadm.o obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o +ifdef CONFIG_CMD_PCI +obj-$(CONFIG_CMD_PCI_MPS) += pci_mps.o +endif obj-$(CONFIG_CMD_PINMUX) += pinmux.o obj-$(CONFIG_CMD_PWM) += pwm.o obj-$(CONFIG_CMD_SEAMA) += seama.o diff --git a/test/cmd/pci_mps.c b/test/cmd/pci_mps.c new file mode 100644 index 00000000000..fd96f4fba6c --- /dev/null +++ b/test/cmd/pci_mps.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Tests that the PCI Maximum Payload Size (MPS) command can set the sandbox + * PCI Express device to safe mode and determine the correct payload size. + * + * Copyright 2023 Microsoft + * Written by Stephen Carlson + */ + +#include +#include +#include +#include + +#define PCI_MPS_TEST(_name, _flags) UNIT_TEST(_name, _flags, pci_mps_test) + +/* Test "pci_mps" command in safe "s" mode */ +static int test_pci_mps_safe(struct unit_test_state *uts) +{ + /* Enumerate PCI Express first */ + ut_assertok(run_command("pci e", 0)); + ut_assert_console_end(); + + /* Test pci_mps s */ + ut_assertok(run_command("pci_mps s", 0)); + ut_assert_nextline("Setting MPS of all devices to 256B"); + ut_assert_console_end(); + + return 0; +} + +PCI_MPS_TEST(test_pci_mps_safe, UT_TESTF_CONSOLE_REC); + +int do_ut_pci_mps(struct cmd_tbl *cmdtp, int flag, int argc, + char * const argv[]) +{ + struct unit_test *tests = UNIT_TEST_SUITE_START(pci_mps_test); + const int n = UNIT_TEST_SUITE_COUNT(pci_mps_test); + + return cmd_ut_category("cmd_pci_mps", "pci_mps_test_", tests, n, + argc, argv); +} diff --git a/test/cmd_ut.c b/test/cmd_ut.c index 409c22bfd24..d440da833a9 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -110,6 +110,9 @@ static struct cmd_tbl cmd_ut_sub[] = { #ifdef CONFIG_CMD_LOADM U_BOOT_CMD_MKENT(loadm, CONFIG_SYS_MAXARGS, 1, do_ut_loadm, "", ""), #endif +#ifdef CONFIG_CMD_PCI_MPS + U_BOOT_CMD_MKENT(pci_mps, CONFIG_SYS_MAXARGS, 1, do_ut_pci_mps, "", ""), +#endif #ifdef CONFIG_CMD_SEAMA U_BOOT_CMD_MKENT(seama, CONFIG_SYS_MAXARGS, 1, do_ut_seama, "", ""), #endif @@ -209,6 +212,9 @@ static char ut_help_text[] = #endif #ifdef CONFIG_UT_OVERLAY "\noverlay - device tree overlays" +#endif +#ifdef CONFIG_CMD_PCI_MPS + "\npci_mps - PCI Express Maximum Payload Size" #endif "\nprint - printing things to the console" "\nsetexpr - setexpr command" -- cgit v1.3.1 From e1c97949ee922ccc84c4ef4364c9810aa76f6306 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Fri, 17 Mar 2023 21:12:22 +0100 Subject: gpio: allow passing NULL to gpio_request_by_line_name() to search all gpio controllers The API is more convenient to use if one doesn't have to know upfront which gpio controller has a line with the name one is searching for, and arrange to look that device up somehow. Or implement this loop oneself. Signed-off-by: Rasmus Villemoes Reviewed-by: Simon Glass --- drivers/gpio/gpio-uclass.c | 7 +++++++ include/asm-generic/gpio.h | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index dbebf3a53eb..c8be5a4d668 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -1171,6 +1171,13 @@ int gpio_request_by_line_name(struct udevice *dev, const char *line_name, { int ret; + if (!dev) { + uclass_foreach_dev_probe(UCLASS_GPIO, dev) + if (!gpio_request_by_line_name(dev, line_name, desc, flags)) + return 0; + return -ENOENT; + } + ret = dev_read_stringlist_search(dev, "gpio-line-names", line_name); if (ret < 0) return ret; diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index dd0bdf2315e..c4a7fd28439 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -580,7 +580,8 @@ int gpio_request_by_name(struct udevice *dev, const char *list_name, * This allows boards to implement common behaviours using GPIOs while not * requiring specific GPIO offsets be used. * - * @dev: An instance of a GPIO controller udevice + * @dev: An instance of a GPIO controller udevice, or NULL to search + * all GPIO controller devices * @line_name: The name of the GPIO (e.g. "bmc-secure-boot") * @desc: A GPIO descriptor that is populated with the requested GPIO * upon return -- cgit v1.3.1 From b5f045e12fea0a64a3749c4da1bdfd579530b67e Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Mon, 20 Mar 2023 10:23:43 +1300 Subject: include: kernel.h: port find_closest() from Linux The find_closest() macro can be used to find an element in a sorted array that is closest to an input value. Bring in this macro from Linux v6.3-rc1-2-g8ca09d5fa354. Signed-off-by: Chris Packham Reviewed-by: Simon Glass --- include/linux/kernel.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'include') diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 3e71d61074b..5cd6c9dc821 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -284,4 +284,28 @@ offsetof(struct structure, member) == (offset), \ "`struct " #structure "` offset for `" #member "` is not " #offset) +#define __find_closest(x, a, as, op) \ +({ \ + typeof(as) __fc_i, __fc_as = (as) - 1; \ + typeof(x) __fc_x = (x); \ + typeof(*a) const *__fc_a = (a); \ + for (__fc_i = 0; __fc_i < __fc_as; __fc_i++) { \ + if (__fc_x op DIV_ROUND_CLOSEST(__fc_a[__fc_i] + \ + __fc_a[__fc_i + 1], 2)) \ + break; \ + } \ + (__fc_i); \ +}) + +/** + * find_closest - locate the closest element in a sorted array + * @x: The reference value. + * @a: The array in which to look for the closest element. Must be sorted + * in ascending order. + * @as: Size of 'a'. + * + * Returns the index of the element closest to 'x'. + */ +#define find_closest(x, a, as) __find_closest(x, a, as, <=) + #endif -- cgit v1.3.1 From 26f923c7cff1a46d465efcd3b8f2240523c7ab08 Mon Sep 17 00:00:00 2001 From: Evgeny Bachinin Date: Mon, 20 Mar 2023 11:23:11 +0300 Subject: cli: run_commandf(): small fixups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * vsnprintf() can truncate cmd, hence it makes no sense to launch such command (it's broken). Moreover, it's better to signalize to the caller about such case (for facilitating debugging or bug hunting). * Fix kernel-doc warnings: include/command.h:264: info: Scanning doc for run_commandf include/command.h:268: warning: contents before sections include/command.h:271: warning: No description found for return value of 'run_commandf' * Add printf-like format attribute to validate at compile-time the format string against parameters's type. * Fix compilation error in case of -Wall, -Werror, -Wextra: error: variable ā€˜i’ set but not used [-Werror=unused-but-set-variable] * Drop extra ret variable. Signed-off-by: Evgeny Bachinin Reviewed-by: Simon Glass --- common/cli.c | 25 +++++++++++++++++++------ include/command.h | 13 ++++++++++--- 2 files changed, 29 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/common/cli.c b/common/cli.c index 9451e6a1426..3916a7b10a7 100644 --- a/common/cli.c +++ b/common/cli.c @@ -8,6 +8,8 @@ * JinHua Luo, GuangDong Linux Center, */ +#define pr_fmt(fmt) "cli: %s: " fmt, __func__ + #include #include #include @@ -20,6 +22,7 @@ #include #include #include +#include #ifdef CONFIG_CMDLINE /* @@ -129,16 +132,26 @@ int run_command_list(const char *cmd, int len, int flag) int run_commandf(const char *fmt, ...) { va_list args; - char cmd[128]; - int i, ret; + int nbytes; va_start(args, fmt); - i = vsnprintf(cmd, sizeof(cmd), fmt, args); + /* + * Limit the console_buffer space being used to CONFIG_SYS_CBSIZE, + * because its last byte is used to fit the replacement of \0 by \n\0 + * in underlying hush parser + */ + nbytes = vsnprintf(console_buffer, CONFIG_SYS_CBSIZE, fmt, args); va_end(args); - ret = run_command(cmd, 0); - - return ret; + if (nbytes < 0) { + pr_debug("I/O internal error occurred.\n"); + return -EIO; + } else if (nbytes >= CONFIG_SYS_CBSIZE) { + pr_debug("'fmt' size:%d exceeds the limit(%d)\n", + nbytes, CONFIG_SYS_CBSIZE); + return -ENOSPC; + } + return run_command(console_buffer, 0); } /****************************************************************************/ diff --git a/include/command.h b/include/command.h index 1b018cb98e7..c4e3170967d 100644 --- a/include/command.h +++ b/include/command.h @@ -13,6 +13,8 @@ #include #include +#include + #ifndef NULL #define NULL 0 #endif @@ -260,12 +262,17 @@ int run_command_repeatable(const char *cmd, int flag); /** * run_commandf() - Run a command created by a format string * - * The command cannot be larger than 127 characters - * * @fmt: printf() format string * @...: Arguments to use (flag is always 0) + * + * The command cannot be larger than (CONFIG_SYS_CBSIZE - 1) characters. + * + * Return: + * Returns 0 on success, -EIO if internal output error occurred, -ENOSPC in + * case of 'fmt' string truncation, or != 0 on error, specific for + * run_command(). */ -int run_commandf(const char *fmt, ...); +int run_commandf(const char *fmt, ...) __printf(1, 2); /** * Run a list of commands separated by ; or even \0 -- cgit v1.3.1