* Re: [PATCH v5 2/7] mux: Add helper functions for getting optional and selected mux-state
@ 2026-01-18 18:03 kernel test robot
0 siblings, 0 replies; 11+ messages in thread
From: kernel test robot @ 2026-01-18 18:03 UTC (permalink / raw)
To: oe-kbuild; +Cc: lkp, Julia Lawall
BCC: lkp@intel.com
CC: oe-kbuild-all@lists.linux.dev
In-Reply-To: <20260118-rz-sdio-mux-v5-2-3c37e8872683@solid-run.com>
References: <20260118-rz-sdio-mux-v5-2-3c37e8872683@solid-run.com>
TO: Josua Mayer <josua@solid-run.com>
TO: "Marc Kleine-Budde" <mkl@pengutronix.de>
TO: Vincent Mailhol <mailhol@kernel.org>
TO: Vinod Koul <vkoul@kernel.org>
TO: Neil Armstrong <neil.armstrong@linaro.org>
TO: Peter Rosin <peda@axentia.se>
TO: Aaro Koskinen <aaro.koskinen@iki.fi>
TO: Andreas Kemnade <andreas@kemnade.info>
TO: Kevin Hilman <khilman@baylibre.com>
TO: Roger Quadros <rogerq@kernel.org>
TO: Tony Lindgren <tony@atomide.com>
TO: Janusz Krzysztofik <jmkrzyszt@gmail.com>
TO: Vignesh R <vigneshr@ti.com>
TO: Andi Shyti <andi.shyti@kernel.org>
TO: Ulf Hansson <ulf.hansson@linaro.org>
TO: Rob Herring <robh@kernel.org>
TO: Krzysztof Kozlowski <krzk@kernel.org>
TO: Conor Dooley <conor+dt@kernel.org>
TO: Geert Uytterhoeven <geert+renesas@glider.be>
TO: Magnus Damm <magnus.damm@gmail.com>
TO: Wolfram Sang <wsa-dev@sang-engineering.com>
CC: Yazan Shhady <yazan.shhady@solid-run.com>
CC: Jon Nettleton <jon@solid-run.com>
CC: Mikhail Anikin <mikhail.anikin@solid-run.com>
CC: linux-can@vger.kernel.org
CC: linux-phy@lists.infradead.org
CC: linux-kernel@vger.kernel.org
CC: linux-omap@vger.kernel.org
CC: linux-i2c@vger.kernel.org
CC: linux-mmc@vger.kernel.org
CC: devicetree@vger.kernel.org
Hi Josua,
kernel test robot noticed the following build warnings:
[auto build test WARNING on 8f0b4cce4481fb22653697cced8d0d04027cb1e8]
url: https://github.com/intel-lab-lkp/linux/commits/Josua-Mayer/phy-can-transceiver-rename-temporary-helper-function-to-avoid-conflict/20260118-183905
base: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
patch link: https://lore.kernel.org/r/20260118-rz-sdio-mux-v5-2-3c37e8872683%40solid-run.com
patch subject: [PATCH v5 2/7] mux: Add helper functions for getting optional and selected mux-state
:::::: branch date: 7 hours ago
:::::: commit date: 7 hours ago
config: i386-randconfig-054-20260118 (https://download.01.org/0day-ci/archive/20260119/202601190136.Fpl1Voph-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Julia Lawall <julia.lawall@inria.fr>
| Closes: https://lore.kernel.org/r/202601190136.Fpl1Voph-lkp@intel.com/
cocci warnings: (new ones prefixed by >>)
>> drivers/mux/core.c:721:18-24: ERROR: reference preceded by free on line 720
vim +721 drivers/mux/core.c
a3b02a9c6591ce drivers/mux/mux-core.c Peter Rosin 2017-05-14 702
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 703 /*
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 704 * mux_state_get() - Get the mux-state for a device.
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 705 * @dev: The device that needs a mux-state.
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 706 * @mux_name: The name identifying the mux-state.
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 707 *
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 708 * Return: A pointer to the mux-state, or an ERR_PTR with a negative errno.
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 709 */
f7086d2a8ffae3 drivers/mux/core.c Josua Mayer 2026-01-18 710 static struct mux_state *mux_state_get(struct device *dev, const char *mux_name, bool optional)
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 711 {
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 712 struct mux_state *mstate;
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 713
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 714 mstate = kzalloc(sizeof(*mstate), GFP_KERNEL);
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 715 if (!mstate)
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 716 return ERR_PTR(-ENOMEM);
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 717
f7086d2a8ffae3 drivers/mux/core.c Josua Mayer 2026-01-18 718 mstate->mux = mux_get(dev, mux_name, &mstate->state, optional);
f7086d2a8ffae3 drivers/mux/core.c Josua Mayer 2026-01-18 719 if (IS_ERR_OR_NULL(mstate->mux)) {
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 @720 kfree(mstate);
f7086d2a8ffae3 drivers/mux/core.c Josua Mayer 2026-01-18 @721 return ERR_CAST(mstate->mux);
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 722 }
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 723
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 724 return mstate;
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 725 }
6632866df852bd drivers/mux/core.c Peter Rosin 2022-01-07 726
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v5 0/7] mmc: host: renesas_sdhi_core: support configuring an optional sdio mux
@ 2026-01-18 10:28 Josua Mayer
2026-01-18 10:28 ` Josua Mayer
0 siblings, 1 reply; 11+ messages in thread
From: Josua Mayer @ 2026-01-18 10:28 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Vinod Koul, Neil Armstrong,
Peter Rosin, Aaro Koskinen, Andreas Kemnade, Kevin Hilman,
Roger Quadros, Tony Lindgren, Janusz Krzysztofik, Vignesh R,
Andi Shyti, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Geert Uytterhoeven, Magnus Damm, Wolfram Sang
Cc: Yazan Shhady, Jon Nettleton, Mikhail Anikin, linux-can, linux-phy,
linux-kernel, linux-omap, linux-i2c, linux-mmc, devicetree,
linux-renesas-soc, Josua Mayer
Some Renesas SoC based boards mux SD and eMMC on a single sdio
controller, exposing user control by dip switch and software control by
gpio.
Purpose is to simplify development and provisioning by selecting boot
media at power-on, and again before starting linux.
Add binding and driver support for linking a (gpio) mux to renesas sdio
controller.
Introduce generic helper functions for getting managed and selected
mux-state objects, and switch i2c-omap and phy-can-transceiver drivers.
Cc: Yazan Shhady <yazan.shhady@solid-run.com>
Cc: Jon Nettleton <jon@solid-run.com>
Cc: Mikhail Anikin <mikhail.anikin@solid-run.com>
To: Marc Kleine-Budde <mkl@pengutronix.de>
To: Vincent Mailhol <mailhol@kernel.org>
To: Vinod Koul <vkoul@kernel.org>
To: Neil Armstrong <neil.armstrong@linaro.org>
To: Peter Rosin <peda@axentia.se>
To: Aaro Koskinen <aaro.koskinen@iki.fi>
To: Andreas Kemnade <andreas@kemnade.info>
To: Kevin Hilman <khilman@baylibre.com>
To: Roger Quadros <rogerq@kernel.org>
To: Tony Lindgren <tony@atomide.com>
To: Janusz Krzysztofik <jmkrzyszt@gmail.com>
To: Vignesh R <vigneshr@ti.com>
To: Andi Shyti <andi.shyti@kernel.org>
To: Ulf Hansson <ulf.hansson@linaro.org>
To: Rob Herring <robh@kernel.org>
To: Krzysztof Kozlowski <krzk+dt@kernel.org>
To: Conor Dooley <conor+dt@kernel.org>
To: Geert Uytterhoeven <geert+renesas@glider.be>
To: Magnus Damm <magnus.damm@gmail.com>
To: Wolfram Sang <wsa+renesas@sang-engineering.com>
Cc: linux-can@vger.kernel.org
Cc: linux-phy@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-omap@vger.kernel.org
Cc: linux-i2c@vger.kernel.org
Cc: linux-mmc@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
Signed-off-by: Josua Mayer <josua@solid-run.com>
Changes in v5:
- implemented automatic mux deselect for devm_*_selected.
(Reported-by: Wolfram Sang <wsa+renesas@sang-engineering.com>)
- because of semantic changes I dropped reviewed and acks from omap-i2c
patch (Andreas Kemnade / Wolfram Sang).
- fix invalid return value in void function for mux helper stubs
(Reported-by: kernel test robot <lkp@intel.com>)
- Link to v4: https://lore.kernel.org/r/20251229-rz-sdio-mux-v4-0-a023e55758fe@solid-run.com
Changes in v4:
- added MULTIPLEXER Kconfig help text.
- removed "select MULTIPLEXER" from renesas sdhi Kconfig, as it is
not required for all devices using this driver.
- added stubs for all symbols exported by mux core.
(Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>)
- refactored mux core logic to silence ENOENT errors only on optional
code paths, keeping error printing unchanged otherwise.
(Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>)
- picked up various reviewed- and acked-by tags
- Link to v3: https://lore.kernel.org/r/20251210-rz-sdio-mux-v3-0-ca628db56d60@solid-run.com
Changes in v3:
- updated omap-i2c and phy-can-transceiver to use new helpers.
- created generic helper functions for getting managed optional mux-state.
(Reported-by: Rob Herring <robh@kernel.org>)
- picked up binding ack by Rob Herring.
- replaced use of "SDIO" with "SD/SDIO/eMMC" in binding document and
commit descriptions.
(Reported-by: Ulf Hansson <ulf.hansson@linaro.org>)
- Link to v2: https://lore.kernel.org/r/20251201-rz-sdio-mux-v2-0-bcb581b88dd7@solid-run.com
Changes in v2:
- dropped mux-controller node from dt binding example
(Reported-by: Conor Dooley <conor@kernel.org>
- Link to v1: https://lore.kernel.org/r/20251128-rz-sdio-mux-v1-0-1ede318d160f@solid-run.com
Reported-by:
---
Josua Mayer (7):
phy: can-transceiver: rename temporary helper function to avoid conflict
mux: Add helper functions for getting optional and selected mux-state
mux: add help text for MULTIPLEXER config option
phy: can-transceiver: drop temporary helper getting optional mux-state
i2c: omap: switch to new generic helper for getting selected mux-state
dt-bindings: mmc: renesas,sdhi: Add mux-states property
mmc: host: renesas_sdhi_core: support selecting an optional mux
.../devicetree/bindings/mmc/renesas,sdhi.yaml | 6 +
drivers/i2c/busses/i2c-omap.c | 24 +--
drivers/mmc/host/renesas_sdhi_core.c | 6 +
drivers/mux/Kconfig | 8 +
drivers/mux/core.c | 175 +++++++++++++++++----
drivers/phy/phy-can-transceiver.c | 10 --
include/linux/mux/consumer.h | 111 ++++++++++++-
7 files changed, 278 insertions(+), 62 deletions(-)
---
base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
change-id: 20251128-rz-sdio-mux-acc5137f1618
Best regards,
--
Josua Mayer <josua@solid-run.com>
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v5 2/7] mux: Add helper functions for getting optional and selected mux-state 2026-01-18 10:28 [PATCH v5 0/7] mmc: host: renesas_sdhi_core: support configuring an optional sdio mux Josua Mayer @ 2026-01-18 10:28 ` Josua Mayer 0 siblings, 0 replies; 11+ messages in thread From: Josua Mayer @ 2026-01-18 10:28 UTC (permalink / raw) To: Marc Kleine-Budde, Vincent Mailhol, Vinod Koul, Neil Armstrong, Peter Rosin, Aaro Koskinen, Andreas Kemnade, Kevin Hilman, Roger Quadros, Tony Lindgren, Janusz Krzysztofik, Vignesh R, Andi Shyti, Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm, Wolfram Sang Cc: Yazan Shhady, Jon Nettleton, Mikhail Anikin, linux-can, linux-phy, linux-kernel, linux-omap, linux-i2c, linux-mmc, devicetree, linux-renesas-soc, Josua Mayer In-tree phy-can-transceiver driver has already implemented a local version of devm_mux_state_get_optional. The omap-i2c driver gets and selects an optional mux in its probe function without using any helper. Add new helper functions covering both aforementioned use-cases: - mux_control_get_optional: Get a mux-control if specified in dt, return NULL otherwise. - devm_mux_state_get_optional: Get a mux-state if specified in dt, return NULL otherwise. - devm_mux_state_get_selected: Get and select a mux-state specified in dt, return error otherwise. - devm_mux_state_get_optional_selected: Get and select a mux-state if specified in dt, return error or NULL. Existing mux_get helper function is changed to take an extra argument indicating whether the mux is optional. In this case no error is printed, and NULL returned in case of ENOENT. Calling code is adapted to handle NULL return case, and to pass optional argument as required. To support automatic deselect for _selected helper, a new structure is created storing an exit pointer similar to clock core which is called on release. To facilitate code sharing between optional/mandatory/selected helpers, a new internal helper function is added to handle quiet (optional) and verbose (mandatory) errors, as well as storing the correct callback for devm release: __devm_mux_state_get Due to this structure devm_mux_state_get_*_selected can no longer print a useful error message when select fails. Instead callers should print errors where needed. Commit e153fdea9db04 ("phy: can-transceiver: Re-instate "mux-states" property presence check") noted that "mux_get() always prints an error message in case of an error, including when the property is not present, confusing the user." The first error message covers the case that a mux name is not matched in dt. The second error message is based on of_parse_phandle_with_args return value. In optional case no error is printed and NULL is returned. This ensures that the new helper functions will not confuse the user either. With the addition of optional helper functions it became clear that drivers should compile and link even if CONFIG_MULTIPLEXER was not enabled. Add stubs for all symbols exported by mux core. Signed-off-by: Josua Mayer <josua@solid-run.com> --- drivers/mux/core.c | 175 ++++++++++++++++++++++++++++++++++++------- include/linux/mux/consumer.h | 111 ++++++++++++++++++++++++++- 2 files changed, 253 insertions(+), 33 deletions(-) diff --git a/drivers/mux/core.c b/drivers/mux/core.c index a3840fe0995f..df30f96ec076 100644 --- a/drivers/mux/core.c +++ b/drivers/mux/core.c @@ -46,6 +46,16 @@ static const struct class mux_class = { .name = "mux", }; +/* + * struct devm_mux_state_state - Tracks managed resources for mux-state objects. + * @mux: Pointer to a mux state. + * @exit: An optional callback to execte before free. + */ +struct devm_mux_state_state { + struct mux_state *mstate; + int (*exit)(struct mux_state *mstate); +}; + static DEFINE_IDA(mux_ida); static int __init mux_init(void) @@ -522,11 +532,12 @@ static struct mux_chip *of_find_mux_chip_by_node(struct device_node *np) * @mux_name: The name identifying the mux-control. * @state: Pointer to where the requested state is returned, or NULL when * the required multiplexer states are handled by other means. + * @optional: Whether to return NULL and silence errors when mux doesn't exist. * * Return: A pointer to the mux-control, or an ERR_PTR with a negative errno. */ static struct mux_control *mux_get(struct device *dev, const char *mux_name, - unsigned int *state) + unsigned int *state, bool optional) { struct device_node *np = dev->of_node; struct of_phandle_args args; @@ -542,7 +553,9 @@ static struct mux_control *mux_get(struct device *dev, const char *mux_name, else index = of_property_match_string(np, "mux-control-names", mux_name); - if (index < 0) { + if (index < 0 && optional) { + return NULL; + } else if (index < 0) { dev_err(dev, "mux controller '%s' not found\n", mux_name); return ERR_PTR(index); @@ -558,8 +571,12 @@ static struct mux_control *mux_get(struct device *dev, const char *mux_name, "mux-controls", "#mux-control-cells", index, &args); if (ret) { + if (optional && ret == -ENOENT) + return NULL; + dev_err(dev, "%pOF: failed to get mux-%s %s(%i)\n", - np, state ? "state" : "control", mux_name ?: "", index); + np, state ? "state" : "control", + mux_name ?: "", index); return ERR_PTR(ret); } @@ -617,10 +634,23 @@ static struct mux_control *mux_get(struct device *dev, const char *mux_name, */ struct mux_control *mux_control_get(struct device *dev, const char *mux_name) { - return mux_get(dev, mux_name, NULL); + return mux_get(dev, mux_name, NULL, false); } EXPORT_SYMBOL_GPL(mux_control_get); +/** + * mux_control_get_optional() - Get the optional mux-control for a device. + * @dev: The device that needs a mux-control. + * @mux_name: The name identifying the mux-control. + * + * Return: A pointer to the mux-control, an ERR_PTR with a negative errno. + */ +struct mux_control *mux_control_get_optional(struct device *dev, const char *mux_name) +{ + return mux_get(dev, mux_name, NULL, true); +} +EXPORT_SYMBOL_GPL(mux_control_get_optional); + /** * mux_control_put() - Put away the mux-control for good. * @mux: The mux-control to put away. @@ -657,8 +687,8 @@ struct mux_control *devm_mux_control_get(struct device *dev, if (!ptr) return ERR_PTR(-ENOMEM); - mux = mux_control_get(dev, mux_name); - if (IS_ERR(mux)) { + mux = mux_get(dev, mux_name, NULL, false); + if (IS_ERR_OR_NULL(mux)) { devres_free(ptr); return mux; } @@ -677,7 +707,7 @@ EXPORT_SYMBOL_GPL(devm_mux_control_get); * * Return: A pointer to the mux-state, or an ERR_PTR with a negative errno. */ -static struct mux_state *mux_state_get(struct device *dev, const char *mux_name) +static struct mux_state *mux_state_get(struct device *dev, const char *mux_name, bool optional) { struct mux_state *mstate; @@ -685,12 +715,10 @@ static struct mux_state *mux_state_get(struct device *dev, const char *mux_name) if (!mstate) return ERR_PTR(-ENOMEM); - mstate->mux = mux_get(dev, mux_name, &mstate->state); - if (IS_ERR(mstate->mux)) { - int err = PTR_ERR(mstate->mux); - + mstate->mux = mux_get(dev, mux_name, &mstate->state, optional); + if (IS_ERR_OR_NULL(mstate->mux)) { kfree(mstate); - return ERR_PTR(err); + return ERR_CAST(mstate->mux); } return mstate; @@ -710,41 +738,130 @@ static void mux_state_put(struct mux_state *mstate) static void devm_mux_state_release(struct device *dev, void *res) { - struct mux_state *mstate = *(struct mux_state **)res; + struct devm_mux_state_state *devm_state = res; - mux_state_put(mstate); + if (devm_state->exit) + devm_state->exit(devm_state->mstate); + + mux_state_put(devm_state->mstate); } /** - * devm_mux_state_get() - Get the mux-state for a device, with resource - * management. - * @dev: The device that needs a mux-control. - * @mux_name: The name identifying the mux-control. + * __devm_mux_state_get() - Get the optional mux-state for a device, + * with resource management. + * @dev: The device that needs a mux-state. + * @mux_name: The name identifying the mux-state. + * @optional: Whether to return NULL and silence errors when mux doesn't exist. + * @init: Optional function pointer for mux-state object initialisation. + * @exit: Optional function pointer for mux-state object cleanup on release. * * Return: Pointer to the mux-state, or an ERR_PTR with a negative errno. */ -struct mux_state *devm_mux_state_get(struct device *dev, - const char *mux_name) +static struct mux_state *__devm_mux_state_get(struct device *dev, const char *mux_name, + bool optional, + int (*init)(struct mux_state *mstate), + int (*exit)(struct mux_state *mstate)) { - struct mux_state **ptr, *mstate; + struct devm_mux_state_state *devm_state; + struct mux_state *mstate; + int ret; - ptr = devres_alloc(devm_mux_state_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) + devm_state = devres_alloc(devm_mux_state_release, sizeof(*devm_state), GFP_KERNEL); + if (!devm_state) return ERR_PTR(-ENOMEM); - mstate = mux_state_get(dev, mux_name); - if (IS_ERR(mstate)) { - devres_free(ptr); - return mstate; + mstate = mux_state_get(dev, mux_name, optional); + if (IS_ERR_OR_NULL(mstate)) + goto err_mux_state_get; + + if (init) { + ret = init(mstate); + if (ret) + goto err_mux_state_init; } - *ptr = mstate; - devres_add(dev, ptr); + devm_state->mstate = mstate; + devm_state->exit = exit; + devres_add(dev, devm_state); return mstate; + +err_mux_state_init: + mux_state_put(mstate); +err_mux_state_get: + devres_free(devm_state); + return ERR_PTR(ret); +} + +/** + * devm_mux_state_get() - Get the mux-state for a device, with resource + * management. + * @dev: The device that needs a mux-control. + * @mux_name: The name identifying the mux-control. + * + * Return: Pointer to the mux-state, or an ERR_PTR with a negative errno. + * + * The mux-state will automatically be freed on release. + */ +struct mux_state *devm_mux_state_get(struct device *dev, const char *mux_name) +{ + return __devm_mux_state_get(dev, mux_name, false, NULL, NULL); } EXPORT_SYMBOL_GPL(devm_mux_state_get); +/** + * devm_mux_state_get_optional() - Get the optional mux-state for a device, + * with resource management. + * @dev: The device that needs a mux-state. + * @mux_name: The name identifying the mux-state. + * + * Return: Pointer to the mux-state, or an ERR_PTR with a negative errno. + * + * The mux-state will automatically be freed on release. + */ +struct mux_state *devm_mux_state_get_optional(struct device *dev, const char *mux_name) +{ + return __devm_mux_state_get(dev, mux_name, true, NULL, NULL); +} +EXPORT_SYMBOL_GPL(devm_mux_state_get_optional); + +/** + * devm_mux_state_get_selected() - Get the mux-state for a device, with + * resource management. + * @dev: The device that needs a mux-state. + * @mux_name: The name identifying the mux-state. + * + * Return: Pointer to the mux-state, or an ERR_PTR with a negative errno. + * + * The returned mux-state (if valid) is already selected. + * + * The mux-state will automatically be deselected and freed on release. + */ +struct mux_state *devm_mux_state_get_selected(struct device *dev, const char *mux_name) +{ + return __devm_mux_state_get(dev, mux_name, false, mux_state_select, mux_state_deselect); +} +EXPORT_SYMBOL_GPL(devm_mux_state_get_selected); + +/** + * devm_mux_state_get_optional_selected() - Get the optional mux-state for + * a device, with resource management. + * @dev: The device that needs a mux-state. + * @mux_name: The name identifying the mux-state. + * + * Return: Pointer to the mux-state, or an ERR_PTR with a negative errno. + * + * The returned mux-state (if valid) is already selected. + * + * The mux-state will automatically be deselected and freed on release. + */ +struct mux_state *devm_mux_state_get_optional_selected(struct device *dev, + const char *mux_name) +{ + return __devm_mux_state_get(dev, mux_name, true, mux_state_select, mux_state_deselect); +} +EXPORT_SYMBOL_GPL(devm_mux_state_get_optional_selected); + /* * Using subsys_initcall instead of module_init here to try to ensure - for * the non-modular case - that the subsystem is initialized when mux consumers diff --git a/include/linux/mux/consumer.h b/include/linux/mux/consumer.h index 2e25c838f831..7d591be26b64 100644 --- a/include/linux/mux/consumer.h +++ b/include/linux/mux/consumer.h @@ -16,6 +16,8 @@ struct device; struct mux_control; struct mux_state; +#ifdef CONFIG_MULTIPLEXER + unsigned int mux_control_states(struct mux_control *mux); int __must_check mux_control_select_delay(struct mux_control *mux, unsigned int state, @@ -54,11 +56,112 @@ int mux_control_deselect(struct mux_control *mux); int mux_state_deselect(struct mux_state *mstate); struct mux_control *mux_control_get(struct device *dev, const char *mux_name); +struct mux_control *mux_control_get_optional(struct device *dev, const char *mux_name); void mux_control_put(struct mux_control *mux); -struct mux_control *devm_mux_control_get(struct device *dev, - const char *mux_name); -struct mux_state *devm_mux_state_get(struct device *dev, - const char *mux_name); +struct mux_control *devm_mux_control_get(struct device *dev, const char *mux_name); +struct mux_state *devm_mux_state_get(struct device *dev, const char *mux_name); +struct mux_state *devm_mux_state_get_optional(struct device *dev, const char *mux_name); +struct mux_state *devm_mux_state_get_selected(struct device *dev, const char *mux_name); +struct mux_state *devm_mux_state_get_optional_selected(struct device *dev, const char *mux_name); + +#else + +static inline unsigned int mux_control_states(struct mux_control *mux) +{ + return 0; +} +static inline int __must_check mux_control_select_delay(struct mux_control *mux, + unsigned int state, unsigned int delay_us) +{ + return -EOPNOTSUPP; +} +static inline int __must_check mux_state_select_delay(struct mux_state *mstate, + unsigned int delay_us) +{ + return -EOPNOTSUPP; +} +static inline int __must_check mux_control_try_select_delay(struct mux_control *mux, + unsigned int state, + unsigned int delay_us) +{ + return -EOPNOTSUPP; +} +static inline int __must_check mux_state_try_select_delay(struct mux_state *mstate, + unsigned int delay_us) +{ + return -EOPNOTSUPP; +} + +static inline int __must_check mux_control_select(struct mux_control *mux, + unsigned int state) +{ + return -EOPNOTSUPP; +} + +static inline int __must_check mux_state_select(struct mux_state *mstate) +{ + return -EOPNOTSUPP; +} + +static inline int __must_check mux_control_try_select(struct mux_control *mux, + unsigned int state) +{ + return -EOPNOTSUPP; +} + +static inline int __must_check mux_state_try_select(struct mux_state *mstate) +{ + return -EOPNOTSUPP; +} + +static inline int mux_control_deselect(struct mux_control *mux) +{ + return -EOPNOTSUPP; +} +static inline int mux_state_deselect(struct mux_state *mstate) +{ + return -EOPNOTSUPP; +} + +static inline struct mux_control *mux_control_get(struct device *dev, const char *mux_name) +{ + return ERR_PTR(-EOPNOTSUPP); +} +static inline struct mux_control *mux_control_get_optional(struct device *dev, + const char *mux_name) +{ + return NULL; +} +static inline void mux_control_put(struct mux_control *mux) +{ + return; +} + +static inline struct mux_control *devm_mux_control_get(struct device *dev, const char *mux_name) +{ + return ERR_PTR(-EOPNOTSUPP); +} +static inline struct mux_state *devm_mux_state_get(struct device *dev, const char *mux_name) +{ + return ERR_PTR(-EOPNOTSUPP); +} +static inline struct mux_state *devm_mux_state_get_optional(struct device *dev, + const char *mux_name) +{ + return NULL; +} +static inline struct mux_state *devm_mux_state_get_selected(struct device *dev, + const char *mux_name) +{ + return ERR_PTR(-EOPNOTSUPP); +} +static inline struct mux_state *devm_mux_state_get_optional_selected(struct device *dev, + const char *mux_name) +{ + return NULL; +} + +#endif /* CONFIG_MULTIPLEXER */ #endif /* _LINUX_MUX_CONSUMER_H */ -- 2.43.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v5 2/7] mux: Add helper functions for getting optional and selected mux-state @ 2026-01-18 10:28 ` Josua Mayer 0 siblings, 0 replies; 11+ messages in thread From: Josua Mayer @ 2026-01-18 10:28 UTC (permalink / raw) To: Marc Kleine-Budde, Vincent Mailhol, Vinod Koul, Neil Armstrong, Peter Rosin, Aaro Koskinen, Andreas Kemnade, Kevin Hilman, Roger Quadros, Tony Lindgren, Janusz Krzysztofik, Vignesh R, Andi Shyti, Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm, Wolfram Sang Cc: Yazan Shhady, Jon Nettleton, Mikhail Anikin, linux-can, linux-phy, linux-kernel, linux-omap, linux-i2c, linux-mmc, devicetree, linux-renesas-soc, Josua Mayer In-tree phy-can-transceiver driver has already implemented a local version of devm_mux_state_get_optional. The omap-i2c driver gets and selects an optional mux in its probe function without using any helper. Add new helper functions covering both aforementioned use-cases: - mux_control_get_optional: Get a mux-control if specified in dt, return NULL otherwise. - devm_mux_state_get_optional: Get a mux-state if specified in dt, return NULL otherwise. - devm_mux_state_get_selected: Get and select a mux-state specified in dt, return error otherwise. - devm_mux_state_get_optional_selected: Get and select a mux-state if specified in dt, return error or NULL. Existing mux_get helper function is changed to take an extra argument indicating whether the mux is optional. In this case no error is printed, and NULL returned in case of ENOENT. Calling code is adapted to handle NULL return case, and to pass optional argument as required. To support automatic deselect for _selected helper, a new structure is created storing an exit pointer similar to clock core which is called on release. To facilitate code sharing between optional/mandatory/selected helpers, a new internal helper function is added to handle quiet (optional) and verbose (mandatory) errors, as well as storing the correct callback for devm release: __devm_mux_state_get Due to this structure devm_mux_state_get_*_selected can no longer print a useful error message when select fails. Instead callers should print errors where needed. Commit e153fdea9db04 ("phy: can-transceiver: Re-instate "mux-states" property presence check") noted that "mux_get() always prints an error message in case of an error, including when the property is not present, confusing the user." The first error message covers the case that a mux name is not matched in dt. The second error message is based on of_parse_phandle_with_args return value. In optional case no error is printed and NULL is returned. This ensures that the new helper functions will not confuse the user either. With the addition of optional helper functions it became clear that drivers should compile and link even if CONFIG_MULTIPLEXER was not enabled. Add stubs for all symbols exported by mux core. Signed-off-by: Josua Mayer <josua@solid-run.com> --- drivers/mux/core.c | 175 ++++++++++++++++++++++++++++++++++++------- include/linux/mux/consumer.h | 111 ++++++++++++++++++++++++++- 2 files changed, 253 insertions(+), 33 deletions(-) diff --git a/drivers/mux/core.c b/drivers/mux/core.c index a3840fe0995f..df30f96ec076 100644 --- a/drivers/mux/core.c +++ b/drivers/mux/core.c @@ -46,6 +46,16 @@ static const struct class mux_class = { .name = "mux", }; +/* + * struct devm_mux_state_state - Tracks managed resources for mux-state objects. + * @mux: Pointer to a mux state. + * @exit: An optional callback to execte before free. + */ +struct devm_mux_state_state { + struct mux_state *mstate; + int (*exit)(struct mux_state *mstate); +}; + static DEFINE_IDA(mux_ida); static int __init mux_init(void) @@ -522,11 +532,12 @@ static struct mux_chip *of_find_mux_chip_by_node(struct device_node *np) * @mux_name: The name identifying the mux-control. * @state: Pointer to where the requested state is returned, or NULL when * the required multiplexer states are handled by other means. + * @optional: Whether to return NULL and silence errors when mux doesn't exist. * * Return: A pointer to the mux-control, or an ERR_PTR with a negative errno. */ static struct mux_control *mux_get(struct device *dev, const char *mux_name, - unsigned int *state) + unsigned int *state, bool optional) { struct device_node *np = dev->of_node; struct of_phandle_args args; @@ -542,7 +553,9 @@ static struct mux_control *mux_get(struct device *dev, const char *mux_name, else index = of_property_match_string(np, "mux-control-names", mux_name); - if (index < 0) { + if (index < 0 && optional) { + return NULL; + } else if (index < 0) { dev_err(dev, "mux controller '%s' not found\n", mux_name); return ERR_PTR(index); @@ -558,8 +571,12 @@ static struct mux_control *mux_get(struct device *dev, const char *mux_name, "mux-controls", "#mux-control-cells", index, &args); if (ret) { + if (optional && ret == -ENOENT) + return NULL; + dev_err(dev, "%pOF: failed to get mux-%s %s(%i)\n", - np, state ? "state" : "control", mux_name ?: "", index); + np, state ? "state" : "control", + mux_name ?: "", index); return ERR_PTR(ret); } @@ -617,10 +634,23 @@ static struct mux_control *mux_get(struct device *dev, const char *mux_name, */ struct mux_control *mux_control_get(struct device *dev, const char *mux_name) { - return mux_get(dev, mux_name, NULL); + return mux_get(dev, mux_name, NULL, false); } EXPORT_SYMBOL_GPL(mux_control_get); +/** + * mux_control_get_optional() - Get the optional mux-control for a device. + * @dev: The device that needs a mux-control. + * @mux_name: The name identifying the mux-control. + * + * Return: A pointer to the mux-control, an ERR_PTR with a negative errno. + */ +struct mux_control *mux_control_get_optional(struct device *dev, const char *mux_name) +{ + return mux_get(dev, mux_name, NULL, true); +} +EXPORT_SYMBOL_GPL(mux_control_get_optional); + /** * mux_control_put() - Put away the mux-control for good. * @mux: The mux-control to put away. @@ -657,8 +687,8 @@ struct mux_control *devm_mux_control_get(struct device *dev, if (!ptr) return ERR_PTR(-ENOMEM); - mux = mux_control_get(dev, mux_name); - if (IS_ERR(mux)) { + mux = mux_get(dev, mux_name, NULL, false); + if (IS_ERR_OR_NULL(mux)) { devres_free(ptr); return mux; } @@ -677,7 +707,7 @@ EXPORT_SYMBOL_GPL(devm_mux_control_get); * * Return: A pointer to the mux-state, or an ERR_PTR with a negative errno. */ -static struct mux_state *mux_state_get(struct device *dev, const char *mux_name) +static struct mux_state *mux_state_get(struct device *dev, const char *mux_name, bool optional) { struct mux_state *mstate; @@ -685,12 +715,10 @@ static struct mux_state *mux_state_get(struct device *dev, const char *mux_name) if (!mstate) return ERR_PTR(-ENOMEM); - mstate->mux = mux_get(dev, mux_name, &mstate->state); - if (IS_ERR(mstate->mux)) { - int err = PTR_ERR(mstate->mux); - + mstate->mux = mux_get(dev, mux_name, &mstate->state, optional); + if (IS_ERR_OR_NULL(mstate->mux)) { kfree(mstate); - return ERR_PTR(err); + return ERR_CAST(mstate->mux); } return mstate; @@ -710,41 +738,130 @@ static void mux_state_put(struct mux_state *mstate) static void devm_mux_state_release(struct device *dev, void *res) { - struct mux_state *mstate = *(struct mux_state **)res; + struct devm_mux_state_state *devm_state = res; - mux_state_put(mstate); + if (devm_state->exit) + devm_state->exit(devm_state->mstate); + + mux_state_put(devm_state->mstate); } /** - * devm_mux_state_get() - Get the mux-state for a device, with resource - * management. - * @dev: The device that needs a mux-control. - * @mux_name: The name identifying the mux-control. + * __devm_mux_state_get() - Get the optional mux-state for a device, + * with resource management. + * @dev: The device that needs a mux-state. + * @mux_name: The name identifying the mux-state. + * @optional: Whether to return NULL and silence errors when mux doesn't exist. + * @init: Optional function pointer for mux-state object initialisation. + * @exit: Optional function pointer for mux-state object cleanup on release. * * Return: Pointer to the mux-state, or an ERR_PTR with a negative errno. */ -struct mux_state *devm_mux_state_get(struct device *dev, - const char *mux_name) +static struct mux_state *__devm_mux_state_get(struct device *dev, const char *mux_name, + bool optional, + int (*init)(struct mux_state *mstate), + int (*exit)(struct mux_state *mstate)) { - struct mux_state **ptr, *mstate; + struct devm_mux_state_state *devm_state; + struct mux_state *mstate; + int ret; - ptr = devres_alloc(devm_mux_state_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) + devm_state = devres_alloc(devm_mux_state_release, sizeof(*devm_state), GFP_KERNEL); + if (!devm_state) return ERR_PTR(-ENOMEM); - mstate = mux_state_get(dev, mux_name); - if (IS_ERR(mstate)) { - devres_free(ptr); - return mstate; + mstate = mux_state_get(dev, mux_name, optional); + if (IS_ERR_OR_NULL(mstate)) + goto err_mux_state_get; + + if (init) { + ret = init(mstate); + if (ret) + goto err_mux_state_init; } - *ptr = mstate; - devres_add(dev, ptr); + devm_state->mstate = mstate; + devm_state->exit = exit; + devres_add(dev, devm_state); return mstate; + +err_mux_state_init: + mux_state_put(mstate); +err_mux_state_get: + devres_free(devm_state); + return ERR_PTR(ret); +} + +/** + * devm_mux_state_get() - Get the mux-state for a device, with resource + * management. + * @dev: The device that needs a mux-control. + * @mux_name: The name identifying the mux-control. + * + * Return: Pointer to the mux-state, or an ERR_PTR with a negative errno. + * + * The mux-state will automatically be freed on release. + */ +struct mux_state *devm_mux_state_get(struct device *dev, const char *mux_name) +{ + return __devm_mux_state_get(dev, mux_name, false, NULL, NULL); } EXPORT_SYMBOL_GPL(devm_mux_state_get); +/** + * devm_mux_state_get_optional() - Get the optional mux-state for a device, + * with resource management. + * @dev: The device that needs a mux-state. + * @mux_name: The name identifying the mux-state. + * + * Return: Pointer to the mux-state, or an ERR_PTR with a negative errno. + * + * The mux-state will automatically be freed on release. + */ +struct mux_state *devm_mux_state_get_optional(struct device *dev, const char *mux_name) +{ + return __devm_mux_state_get(dev, mux_name, true, NULL, NULL); +} +EXPORT_SYMBOL_GPL(devm_mux_state_get_optional); + +/** + * devm_mux_state_get_selected() - Get the mux-state for a device, with + * resource management. + * @dev: The device that needs a mux-state. + * @mux_name: The name identifying the mux-state. + * + * Return: Pointer to the mux-state, or an ERR_PTR with a negative errno. + * + * The returned mux-state (if valid) is already selected. + * + * The mux-state will automatically be deselected and freed on release. + */ +struct mux_state *devm_mux_state_get_selected(struct device *dev, const char *mux_name) +{ + return __devm_mux_state_get(dev, mux_name, false, mux_state_select, mux_state_deselect); +} +EXPORT_SYMBOL_GPL(devm_mux_state_get_selected); + +/** + * devm_mux_state_get_optional_selected() - Get the optional mux-state for + * a device, with resource management. + * @dev: The device that needs a mux-state. + * @mux_name: The name identifying the mux-state. + * + * Return: Pointer to the mux-state, or an ERR_PTR with a negative errno. + * + * The returned mux-state (if valid) is already selected. + * + * The mux-state will automatically be deselected and freed on release. + */ +struct mux_state *devm_mux_state_get_optional_selected(struct device *dev, + const char *mux_name) +{ + return __devm_mux_state_get(dev, mux_name, true, mux_state_select, mux_state_deselect); +} +EXPORT_SYMBOL_GPL(devm_mux_state_get_optional_selected); + /* * Using subsys_initcall instead of module_init here to try to ensure - for * the non-modular case - that the subsystem is initialized when mux consumers diff --git a/include/linux/mux/consumer.h b/include/linux/mux/consumer.h index 2e25c838f831..7d591be26b64 100644 --- a/include/linux/mux/consumer.h +++ b/include/linux/mux/consumer.h @@ -16,6 +16,8 @@ struct device; struct mux_control; struct mux_state; +#ifdef CONFIG_MULTIPLEXER + unsigned int mux_control_states(struct mux_control *mux); int __must_check mux_control_select_delay(struct mux_control *mux, unsigned int state, @@ -54,11 +56,112 @@ int mux_control_deselect(struct mux_control *mux); int mux_state_deselect(struct mux_state *mstate); struct mux_control *mux_control_get(struct device *dev, const char *mux_name); +struct mux_control *mux_control_get_optional(struct device *dev, const char *mux_name); void mux_control_put(struct mux_control *mux); -struct mux_control *devm_mux_control_get(struct device *dev, - const char *mux_name); -struct mux_state *devm_mux_state_get(struct device *dev, - const char *mux_name); +struct mux_control *devm_mux_control_get(struct device *dev, const char *mux_name); +struct mux_state *devm_mux_state_get(struct device *dev, const char *mux_name); +struct mux_state *devm_mux_state_get_optional(struct device *dev, const char *mux_name); +struct mux_state *devm_mux_state_get_selected(struct device *dev, const char *mux_name); +struct mux_state *devm_mux_state_get_optional_selected(struct device *dev, const char *mux_name); + +#else + +static inline unsigned int mux_control_states(struct mux_control *mux) +{ + return 0; +} +static inline int __must_check mux_control_select_delay(struct mux_control *mux, + unsigned int state, unsigned int delay_us) +{ + return -EOPNOTSUPP; +} +static inline int __must_check mux_state_select_delay(struct mux_state *mstate, + unsigned int delay_us) +{ + return -EOPNOTSUPP; +} +static inline int __must_check mux_control_try_select_delay(struct mux_control *mux, + unsigned int state, + unsigned int delay_us) +{ + return -EOPNOTSUPP; +} +static inline int __must_check mux_state_try_select_delay(struct mux_state *mstate, + unsigned int delay_us) +{ + return -EOPNOTSUPP; +} + +static inline int __must_check mux_control_select(struct mux_control *mux, + unsigned int state) +{ + return -EOPNOTSUPP; +} + +static inline int __must_check mux_state_select(struct mux_state *mstate) +{ + return -EOPNOTSUPP; +} + +static inline int __must_check mux_control_try_select(struct mux_control *mux, + unsigned int state) +{ + return -EOPNOTSUPP; +} + +static inline int __must_check mux_state_try_select(struct mux_state *mstate) +{ + return -EOPNOTSUPP; +} + +static inline int mux_control_deselect(struct mux_control *mux) +{ + return -EOPNOTSUPP; +} +static inline int mux_state_deselect(struct mux_state *mstate) +{ + return -EOPNOTSUPP; +} + +static inline struct mux_control *mux_control_get(struct device *dev, const char *mux_name) +{ + return ERR_PTR(-EOPNOTSUPP); +} +static inline struct mux_control *mux_control_get_optional(struct device *dev, + const char *mux_name) +{ + return NULL; +} +static inline void mux_control_put(struct mux_control *mux) +{ + return; +} + +static inline struct mux_control *devm_mux_control_get(struct device *dev, const char *mux_name) +{ + return ERR_PTR(-EOPNOTSUPP); +} +static inline struct mux_state *devm_mux_state_get(struct device *dev, const char *mux_name) +{ + return ERR_PTR(-EOPNOTSUPP); +} +static inline struct mux_state *devm_mux_state_get_optional(struct device *dev, + const char *mux_name) +{ + return NULL; +} +static inline struct mux_state *devm_mux_state_get_selected(struct device *dev, + const char *mux_name) +{ + return ERR_PTR(-EOPNOTSUPP); +} +static inline struct mux_state *devm_mux_state_get_optional_selected(struct device *dev, + const char *mux_name) +{ + return NULL; +} + +#endif /* CONFIG_MULTIPLEXER */ #endif /* _LINUX_MUX_CONSUMER_H */ -- 2.43.0 -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v5 2/7] mux: Add helper functions for getting optional and selected mux-state 2026-01-18 10:28 ` Josua Mayer @ 2026-01-18 13:28 ` kernel test robot -1 siblings, 0 replies; 11+ messages in thread From: kernel test robot @ 2026-01-18 13:28 UTC (permalink / raw) To: Josua Mayer, Marc Kleine-Budde, Vincent Mailhol, Vinod Koul, Neil Armstrong, Peter Rosin, Aaro Koskinen, Andreas Kemnade, Kevin Hilman, Roger Quadros, Tony Lindgren, Janusz Krzysztofik, Vignesh R, Andi Shyti, Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm, Wolfram Sang Cc: oe-kbuild-all, Yazan Shhady, Jon Nettleton, Mikhail Anikin, linux-can, linux-phy, linux-kernel, linux-omap, linux-i2c, linux-mmc, devicetree Hi Josua, kernel test robot noticed the following build warnings: [auto build test WARNING on 8f0b4cce4481fb22653697cced8d0d04027cb1e8] url: https://github.com/intel-lab-lkp/linux/commits/Josua-Mayer/phy-can-transceiver-rename-temporary-helper-function-to-avoid-conflict/20260118-183905 base: 8f0b4cce4481fb22653697cced8d0d04027cb1e8 patch link: https://lore.kernel.org/r/20260118-rz-sdio-mux-v5-2-3c37e8872683%40solid-run.com patch subject: [PATCH v5 2/7] mux: Add helper functions for getting optional and selected mux-state config: um-randconfig-r071-20260118 (https://download.01.org/0day-ci/archive/20260118/202601182117.l2nFZ5OB-lkp@intel.com/config) compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 9b8addffa70cee5b2acc5454712d9cf78ce45710) smatch version: v0.5.0-8985-g2614ff1a reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260118/202601182117.l2nFZ5OB-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202601182117.l2nFZ5OB-lkp@intel.com/ All warnings (new ones prefixed by >>): >> drivers/mux/core.c:774:6: warning: variable 'ret' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized] 774 | if (IS_ERR_OR_NULL(mstate)) | ^~~~~~~~~~~~~~~~~~~~~~ drivers/mux/core.c:793:17: note: uninitialized use occurs here 793 | return ERR_PTR(ret); | ^~~ drivers/mux/core.c:774:2: note: remove the 'if' if its condition is always false 774 | if (IS_ERR_OR_NULL(mstate)) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~ 775 | goto err_mux_state_get; | ~~~~~~~~~~~~~~~~~~~~~~ drivers/mux/core.c:767:9: note: initialize the variable 'ret' to silence this warning 767 | int ret; | ^ | = 0 1 warning generated. vim +774 drivers/mux/core.c 748 749 /** 750 * __devm_mux_state_get() - Get the optional mux-state for a device, 751 * with resource management. 752 * @dev: The device that needs a mux-state. 753 * @mux_name: The name identifying the mux-state. 754 * @optional: Whether to return NULL and silence errors when mux doesn't exist. 755 * @init: Optional function pointer for mux-state object initialisation. 756 * @exit: Optional function pointer for mux-state object cleanup on release. 757 * 758 * Return: Pointer to the mux-state, or an ERR_PTR with a negative errno. 759 */ 760 static struct mux_state *__devm_mux_state_get(struct device *dev, const char *mux_name, 761 bool optional, 762 int (*init)(struct mux_state *mstate), 763 int (*exit)(struct mux_state *mstate)) 764 { 765 struct devm_mux_state_state *devm_state; 766 struct mux_state *mstate; 767 int ret; 768 769 devm_state = devres_alloc(devm_mux_state_release, sizeof(*devm_state), GFP_KERNEL); 770 if (!devm_state) 771 return ERR_PTR(-ENOMEM); 772 773 mstate = mux_state_get(dev, mux_name, optional); > 774 if (IS_ERR_OR_NULL(mstate)) 775 goto err_mux_state_get; 776 777 if (init) { 778 ret = init(mstate); 779 if (ret) 780 goto err_mux_state_init; 781 } 782 783 devm_state->mstate = mstate; 784 devm_state->exit = exit; 785 devres_add(dev, devm_state); 786 787 return mstate; 788 789 err_mux_state_init: 790 mux_state_put(mstate); 791 err_mux_state_get: 792 devres_free(devm_state); 793 return ERR_PTR(ret); 794 } 795 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v5 2/7] mux: Add helper functions for getting optional and selected mux-state @ 2026-01-18 13:28 ` kernel test robot 0 siblings, 0 replies; 11+ messages in thread From: kernel test robot @ 2026-01-18 13:28 UTC (permalink / raw) To: Josua Mayer, Marc Kleine-Budde, Vincent Mailhol, Vinod Koul, Neil Armstrong, Peter Rosin, Aaro Koskinen, Andreas Kemnade, Kevin Hilman, Roger Quadros, Tony Lindgren, Janusz Krzysztofik, Vignesh R, Andi Shyti, Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm, Wolfram Sang Cc: oe-kbuild-all, Yazan Shhady, Jon Nettleton, Mikhail Anikin, linux-can, linux-phy, linux-kernel, linux-omap, linux-i2c, linux-mmc, devicetree Hi Josua, kernel test robot noticed the following build warnings: [auto build test WARNING on 8f0b4cce4481fb22653697cced8d0d04027cb1e8] url: https://github.com/intel-lab-lkp/linux/commits/Josua-Mayer/phy-can-transceiver-rename-temporary-helper-function-to-avoid-conflict/20260118-183905 base: 8f0b4cce4481fb22653697cced8d0d04027cb1e8 patch link: https://lore.kernel.org/r/20260118-rz-sdio-mux-v5-2-3c37e8872683%40solid-run.com patch subject: [PATCH v5 2/7] mux: Add helper functions for getting optional and selected mux-state config: um-randconfig-r071-20260118 (https://download.01.org/0day-ci/archive/20260118/202601182117.l2nFZ5OB-lkp@intel.com/config) compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 9b8addffa70cee5b2acc5454712d9cf78ce45710) smatch version: v0.5.0-8985-g2614ff1a reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260118/202601182117.l2nFZ5OB-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202601182117.l2nFZ5OB-lkp@intel.com/ All warnings (new ones prefixed by >>): >> drivers/mux/core.c:774:6: warning: variable 'ret' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized] 774 | if (IS_ERR_OR_NULL(mstate)) | ^~~~~~~~~~~~~~~~~~~~~~ drivers/mux/core.c:793:17: note: uninitialized use occurs here 793 | return ERR_PTR(ret); | ^~~ drivers/mux/core.c:774:2: note: remove the 'if' if its condition is always false 774 | if (IS_ERR_OR_NULL(mstate)) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~ 775 | goto err_mux_state_get; | ~~~~~~~~~~~~~~~~~~~~~~ drivers/mux/core.c:767:9: note: initialize the variable 'ret' to silence this warning 767 | int ret; | ^ | = 0 1 warning generated. vim +774 drivers/mux/core.c 748 749 /** 750 * __devm_mux_state_get() - Get the optional mux-state for a device, 751 * with resource management. 752 * @dev: The device that needs a mux-state. 753 * @mux_name: The name identifying the mux-state. 754 * @optional: Whether to return NULL and silence errors when mux doesn't exist. 755 * @init: Optional function pointer for mux-state object initialisation. 756 * @exit: Optional function pointer for mux-state object cleanup on release. 757 * 758 * Return: Pointer to the mux-state, or an ERR_PTR with a negative errno. 759 */ 760 static struct mux_state *__devm_mux_state_get(struct device *dev, const char *mux_name, 761 bool optional, 762 int (*init)(struct mux_state *mstate), 763 int (*exit)(struct mux_state *mstate)) 764 { 765 struct devm_mux_state_state *devm_state; 766 struct mux_state *mstate; 767 int ret; 768 769 devm_state = devres_alloc(devm_mux_state_release, sizeof(*devm_state), GFP_KERNEL); 770 if (!devm_state) 771 return ERR_PTR(-ENOMEM); 772 773 mstate = mux_state_get(dev, mux_name, optional); > 774 if (IS_ERR_OR_NULL(mstate)) 775 goto err_mux_state_get; 776 777 if (init) { 778 ret = init(mstate); 779 if (ret) 780 goto err_mux_state_init; 781 } 782 783 devm_state->mstate = mstate; 784 devm_state->exit = exit; 785 devres_add(dev, devm_state); 786 787 return mstate; 788 789 err_mux_state_init: 790 mux_state_put(mstate); 791 err_mux_state_get: 792 devres_free(devm_state); 793 return ERR_PTR(ret); 794 } 795 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v5 2/7] mux: Add helper functions for getting optional and selected mux-state 2026-01-18 10:28 ` Josua Mayer @ 2026-01-20 9:45 ` Geert Uytterhoeven -1 siblings, 0 replies; 11+ messages in thread From: Geert Uytterhoeven @ 2026-01-20 9:45 UTC (permalink / raw) To: Josua Mayer Cc: Marc Kleine-Budde, Vincent Mailhol, Vinod Koul, Neil Armstrong, Peter Rosin, Aaro Koskinen, Andreas Kemnade, Kevin Hilman, Roger Quadros, Tony Lindgren, Janusz Krzysztofik, Vignesh R, Andi Shyti, Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm, Wolfram Sang, Yazan Shhady, Jon Nettleton, Mikhail Anikin, linux-can, linux-phy, linux-kernel, linux-omap, linux-i2c, linux-mmc, devicetree, linux-renesas-soc Hi Josua, On Sun, 18 Jan 2026 at 11:29, Josua Mayer <josua@solid-run.com> wrote: > In-tree phy-can-transceiver driver has already implemented a local > version of devm_mux_state_get_optional. > > The omap-i2c driver gets and selects an optional mux in its probe > function without using any helper. > > Add new helper functions covering both aforementioned use-cases: > > - mux_control_get_optional: > Get a mux-control if specified in dt, return NULL otherwise. > - devm_mux_state_get_optional: > Get a mux-state if specified in dt, return NULL otherwise. > - devm_mux_state_get_selected: > Get and select a mux-state specified in dt, return error otherwise. > - devm_mux_state_get_optional_selected: > Get and select a mux-state if specified in dt, return error or NULL. > > Existing mux_get helper function is changed to take an extra argument > indicating whether the mux is optional. > In this case no error is printed, and NULL returned in case of ENOENT. > > Calling code is adapted to handle NULL return case, and to pass optional > argument as required. > > To support automatic deselect for _selected helper, a new structure is > created storing an exit pointer similar to clock core which is called on > release. > > To facilitate code sharing between optional/mandatory/selected helpers, > a new internal helper function is added to handle quiet (optional) and > verbose (mandatory) errors, as well as storing the correct callback for > devm release: __devm_mux_state_get > > Due to this structure devm_mux_state_get_*_selected can no longer print > a useful error message when select fails. Instead callers should print > errors where needed. > > Commit e153fdea9db04 ("phy: can-transceiver: Re-instate "mux-states" > property presence check") noted that "mux_get() always prints an error > message in case of an error, including when the property is not present, > confusing the user." > > The first error message covers the case that a mux name is not matched > in dt. The second error message is based on of_parse_phandle_with_args > return value. > > In optional case no error is printed and NULL is returned. > This ensures that the new helper functions will not confuse the user > either. > > With the addition of optional helper functions it became clear that > drivers should compile and link even if CONFIG_MULTIPLEXER was not enabled. > Add stubs for all symbols exported by mux core. > > Signed-off-by: Josua Mayer <josua@solid-run.com> Thanks for your patch! > --- a/drivers/mux/core.c > +++ b/drivers/mux/core.c > @@ -677,7 +707,7 @@ EXPORT_SYMBOL_GPL(devm_mux_control_get); > * > * Return: A pointer to the mux-state, or an ERR_PTR with a negative errno. > */ > -static struct mux_state *mux_state_get(struct device *dev, const char *mux_name) > +static struct mux_state *mux_state_get(struct device *dev, const char *mux_name, bool optional) > { > struct mux_state *mstate; > > @@ -685,12 +715,10 @@ static struct mux_state *mux_state_get(struct device *dev, const char *mux_name) > if (!mstate) > return ERR_PTR(-ENOMEM); > > - mstate->mux = mux_get(dev, mux_name, &mstate->state); > - if (IS_ERR(mstate->mux)) { > - int err = PTR_ERR(mstate->mux); > - > + mstate->mux = mux_get(dev, mux_name, &mstate->state, optional); > + if (IS_ERR_OR_NULL(mstate->mux)) { > kfree(mstate); mstate is freed here... > - return ERR_PTR(err); > + return ERR_CAST(mstate->mux); ... and dereferenced here, leading to a use after free. > } > > return mstate; Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v5 2/7] mux: Add helper functions for getting optional and selected mux-state @ 2026-01-20 9:45 ` Geert Uytterhoeven 0 siblings, 0 replies; 11+ messages in thread From: Geert Uytterhoeven @ 2026-01-20 9:45 UTC (permalink / raw) To: Josua Mayer Cc: Marc Kleine-Budde, Vincent Mailhol, Vinod Koul, Neil Armstrong, Peter Rosin, Aaro Koskinen, Andreas Kemnade, Kevin Hilman, Roger Quadros, Tony Lindgren, Janusz Krzysztofik, Vignesh R, Andi Shyti, Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm, Wolfram Sang, Yazan Shhady, Jon Nettleton, Mikhail Anikin, linux-can, linux-phy, linux-kernel, linux-omap, linux-i2c, linux-mmc, devicetree, linux-renesas-soc Hi Josua, On Sun, 18 Jan 2026 at 11:29, Josua Mayer <josua@solid-run.com> wrote: > In-tree phy-can-transceiver driver has already implemented a local > version of devm_mux_state_get_optional. > > The omap-i2c driver gets and selects an optional mux in its probe > function without using any helper. > > Add new helper functions covering both aforementioned use-cases: > > - mux_control_get_optional: > Get a mux-control if specified in dt, return NULL otherwise. > - devm_mux_state_get_optional: > Get a mux-state if specified in dt, return NULL otherwise. > - devm_mux_state_get_selected: > Get and select a mux-state specified in dt, return error otherwise. > - devm_mux_state_get_optional_selected: > Get and select a mux-state if specified in dt, return error or NULL. > > Existing mux_get helper function is changed to take an extra argument > indicating whether the mux is optional. > In this case no error is printed, and NULL returned in case of ENOENT. > > Calling code is adapted to handle NULL return case, and to pass optional > argument as required. > > To support automatic deselect for _selected helper, a new structure is > created storing an exit pointer similar to clock core which is called on > release. > > To facilitate code sharing between optional/mandatory/selected helpers, > a new internal helper function is added to handle quiet (optional) and > verbose (mandatory) errors, as well as storing the correct callback for > devm release: __devm_mux_state_get > > Due to this structure devm_mux_state_get_*_selected can no longer print > a useful error message when select fails. Instead callers should print > errors where needed. > > Commit e153fdea9db04 ("phy: can-transceiver: Re-instate "mux-states" > property presence check") noted that "mux_get() always prints an error > message in case of an error, including when the property is not present, > confusing the user." > > The first error message covers the case that a mux name is not matched > in dt. The second error message is based on of_parse_phandle_with_args > return value. > > In optional case no error is printed and NULL is returned. > This ensures that the new helper functions will not confuse the user > either. > > With the addition of optional helper functions it became clear that > drivers should compile and link even if CONFIG_MULTIPLEXER was not enabled. > Add stubs for all symbols exported by mux core. > > Signed-off-by: Josua Mayer <josua@solid-run.com> Thanks for your patch! > --- a/drivers/mux/core.c > +++ b/drivers/mux/core.c > @@ -677,7 +707,7 @@ EXPORT_SYMBOL_GPL(devm_mux_control_get); > * > * Return: A pointer to the mux-state, or an ERR_PTR with a negative errno. > */ > -static struct mux_state *mux_state_get(struct device *dev, const char *mux_name) > +static struct mux_state *mux_state_get(struct device *dev, const char *mux_name, bool optional) > { > struct mux_state *mstate; > > @@ -685,12 +715,10 @@ static struct mux_state *mux_state_get(struct device *dev, const char *mux_name) > if (!mstate) > return ERR_PTR(-ENOMEM); > > - mstate->mux = mux_get(dev, mux_name, &mstate->state); > - if (IS_ERR(mstate->mux)) { > - int err = PTR_ERR(mstate->mux); > - > + mstate->mux = mux_get(dev, mux_name, &mstate->state, optional); > + if (IS_ERR_OR_NULL(mstate->mux)) { > kfree(mstate); mstate is freed here... > - return ERR_PTR(err); > + return ERR_CAST(mstate->mux); ... and dereferenced here, leading to a use after free. > } > > return mstate; Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v5 2/7] mux: Add helper functions for getting optional and selected mux-state 2026-01-20 9:45 ` Geert Uytterhoeven @ 2026-01-21 9:00 ` Josua Mayer -1 siblings, 0 replies; 11+ messages in thread From: Josua Mayer @ 2026-01-21 9:00 UTC (permalink / raw) To: Geert Uytterhoeven Cc: Marc Kleine-Budde, Vincent Mailhol, Vinod Koul, Neil Armstrong, Peter Rosin, Aaro Koskinen, Andreas Kemnade, Kevin Hilman, Roger Quadros, Tony Lindgren, Janusz Krzysztofik, Vignesh R, Andi Shyti, Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm, Wolfram Sang, Yazan Shhady, Jon Nettleton, Mikhail Anikin, linux-can@vger.kernel.org, linux-phy@lists.infradead.org, linux-kernel@vger.kernel.org, linux-omap@vger.kernel.org, linux-i2c@vger.kernel.org, linux-mmc@vger.kernel.org, devicetree@vger.kernel.org, linux-renesas-soc@vger.kernel.org On 20/01/2026 11:45, Geert Uytterhoeven wrote: > Hi Josua, > > On Sun, 18 Jan 2026 at 11:29, Josua Mayer <josua@solid-run.com> wrote: >> In-tree phy-can-transceiver driver has already implemented a local >> version of devm_mux_state_get_optional. >> >> The omap-i2c driver gets and selects an optional mux in its probe >> function without using any helper. >> >> Add new helper functions covering both aforementioned use-cases: >> >> - mux_control_get_optional: >> Get a mux-control if specified in dt, return NULL otherwise. >> - devm_mux_state_get_optional: >> Get a mux-state if specified in dt, return NULL otherwise. >> - devm_mux_state_get_selected: >> Get and select a mux-state specified in dt, return error otherwise. >> - devm_mux_state_get_optional_selected: >> Get and select a mux-state if specified in dt, return error or NULL. >> >> Existing mux_get helper function is changed to take an extra argument >> indicating whether the mux is optional. >> In this case no error is printed, and NULL returned in case of ENOENT. >> >> Calling code is adapted to handle NULL return case, and to pass optional >> argument as required. >> >> To support automatic deselect for _selected helper, a new structure is >> created storing an exit pointer similar to clock core which is called on >> release. >> >> To facilitate code sharing between optional/mandatory/selected helpers, >> a new internal helper function is added to handle quiet (optional) and >> verbose (mandatory) errors, as well as storing the correct callback for >> devm release: __devm_mux_state_get >> >> Due to this structure devm_mux_state_get_*_selected can no longer print >> a useful error message when select fails. Instead callers should print >> errors where needed. >> >> Commit e153fdea9db04 ("phy: can-transceiver: Re-instate "mux-states" >> property presence check") noted that "mux_get() always prints an error >> message in case of an error, including when the property is not present, >> confusing the user." >> >> The first error message covers the case that a mux name is not matched >> in dt. The second error message is based on of_parse_phandle_with_args >> return value. >> >> In optional case no error is printed and NULL is returned. >> This ensures that the new helper functions will not confuse the user >> either. >> >> With the addition of optional helper functions it became clear that >> drivers should compile and link even if CONFIG_MULTIPLEXER was not enabled. >> Add stubs for all symbols exported by mux core. >> >> Signed-off-by: Josua Mayer <josua@solid-run.com> > Thanks for your patch! > >> --- a/drivers/mux/core.c >> +++ b/drivers/mux/core.c >> @@ -677,7 +707,7 @@ EXPORT_SYMBOL_GPL(devm_mux_control_get); >> * >> * Return: A pointer to the mux-state, or an ERR_PTR with a negative errno. >> */ >> -static struct mux_state *mux_state_get(struct device *dev, const char *mux_name) >> +static struct mux_state *mux_state_get(struct device *dev, const char *mux_name, bool optional) >> { >> struct mux_state *mstate; >> >> @@ -685,12 +715,10 @@ static struct mux_state *mux_state_get(struct device *dev, const char *mux_name) >> if (!mstate) >> return ERR_PTR(-ENOMEM); >> >> - mstate->mux = mux_get(dev, mux_name, &mstate->state); >> - if (IS_ERR(mstate->mux)) { >> - int err = PTR_ERR(mstate->mux); >> - >> + mstate->mux = mux_get(dev, mux_name, &mstate->state, optional); >> + if (IS_ERR_OR_NULL(mstate->mux)) { >> kfree(mstate); > mstate is freed here... > >> - return ERR_PTR(err); >> + return ERR_CAST(mstate->mux); > ... and dereferenced here, leading to a use after free. Thank you for spotting this, I will resolve it in next version! (along with what the kernel robot found) > >> } >> >> return mstate; > Gr{oetje,eeting}s, > > Geert > ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v5 2/7] mux: Add helper functions for getting optional and selected mux-state @ 2026-01-21 9:00 ` Josua Mayer 0 siblings, 0 replies; 11+ messages in thread From: Josua Mayer @ 2026-01-21 9:00 UTC (permalink / raw) To: Geert Uytterhoeven Cc: Marc Kleine-Budde, Vincent Mailhol, Vinod Koul, Neil Armstrong, Peter Rosin, Aaro Koskinen, Andreas Kemnade, Kevin Hilman, Roger Quadros, Tony Lindgren, Janusz Krzysztofik, Vignesh R, Andi Shyti, Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm, Wolfram Sang, Yazan Shhady, Jon Nettleton, Mikhail Anikin, linux-can@vger.kernel.org, linux-phy@lists.infradead.org, linux-kernel@vger.kernel.org, linux-omap@vger.kernel.org, linux-i2c@vger.kernel.org, linux-mmc@vger.kernel.org, devicetree@vger.kernel.org, linux-renesas-soc@vger.kernel.org On 20/01/2026 11:45, Geert Uytterhoeven wrote: > Hi Josua, > > On Sun, 18 Jan 2026 at 11:29, Josua Mayer <josua@solid-run.com> wrote: >> In-tree phy-can-transceiver driver has already implemented a local >> version of devm_mux_state_get_optional. >> >> The omap-i2c driver gets and selects an optional mux in its probe >> function without using any helper. >> >> Add new helper functions covering both aforementioned use-cases: >> >> - mux_control_get_optional: >> Get a mux-control if specified in dt, return NULL otherwise. >> - devm_mux_state_get_optional: >> Get a mux-state if specified in dt, return NULL otherwise. >> - devm_mux_state_get_selected: >> Get and select a mux-state specified in dt, return error otherwise. >> - devm_mux_state_get_optional_selected: >> Get and select a mux-state if specified in dt, return error or NULL. >> >> Existing mux_get helper function is changed to take an extra argument >> indicating whether the mux is optional. >> In this case no error is printed, and NULL returned in case of ENOENT. >> >> Calling code is adapted to handle NULL return case, and to pass optional >> argument as required. >> >> To support automatic deselect for _selected helper, a new structure is >> created storing an exit pointer similar to clock core which is called on >> release. >> >> To facilitate code sharing between optional/mandatory/selected helpers, >> a new internal helper function is added to handle quiet (optional) and >> verbose (mandatory) errors, as well as storing the correct callback for >> devm release: __devm_mux_state_get >> >> Due to this structure devm_mux_state_get_*_selected can no longer print >> a useful error message when select fails. Instead callers should print >> errors where needed. >> >> Commit e153fdea9db04 ("phy: can-transceiver: Re-instate "mux-states" >> property presence check") noted that "mux_get() always prints an error >> message in case of an error, including when the property is not present, >> confusing the user." >> >> The first error message covers the case that a mux name is not matched >> in dt. The second error message is based on of_parse_phandle_with_args >> return value. >> >> In optional case no error is printed and NULL is returned. >> This ensures that the new helper functions will not confuse the user >> either. >> >> With the addition of optional helper functions it became clear that >> drivers should compile and link even if CONFIG_MULTIPLEXER was not enabled. >> Add stubs for all symbols exported by mux core. >> >> Signed-off-by: Josua Mayer <josua@solid-run.com> > Thanks for your patch! > >> --- a/drivers/mux/core.c >> +++ b/drivers/mux/core.c >> @@ -677,7 +707,7 @@ EXPORT_SYMBOL_GPL(devm_mux_control_get); >> * >> * Return: A pointer to the mux-state, or an ERR_PTR with a negative errno. >> */ >> -static struct mux_state *mux_state_get(struct device *dev, const char *mux_name) >> +static struct mux_state *mux_state_get(struct device *dev, const char *mux_name, bool optional) >> { >> struct mux_state *mstate; >> >> @@ -685,12 +715,10 @@ static struct mux_state *mux_state_get(struct device *dev, const char *mux_name) >> if (!mstate) >> return ERR_PTR(-ENOMEM); >> >> - mstate->mux = mux_get(dev, mux_name, &mstate->state); >> - if (IS_ERR(mstate->mux)) { >> - int err = PTR_ERR(mstate->mux); >> - >> + mstate->mux = mux_get(dev, mux_name, &mstate->state, optional); >> + if (IS_ERR_OR_NULL(mstate->mux)) { >> kfree(mstate); > mstate is freed here... > >> - return ERR_PTR(err); >> + return ERR_CAST(mstate->mux); > ... and dereferenced here, leading to a use after free. Thank you for spotting this, I will resolve it in next version! (along with what the kernel robot found) > >> } >> >> return mstate; > Gr{oetje,eeting}s, > > Geert > -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v5 2/7] mux: Add helper functions for getting optional and selected mux-state 2026-01-18 10:28 ` Josua Mayer @ 2026-01-20 15:57 ` Geert Uytterhoeven -1 siblings, 0 replies; 11+ messages in thread From: Geert Uytterhoeven @ 2026-01-20 15:57 UTC (permalink / raw) To: Josua Mayer Cc: Marc Kleine-Budde, Vincent Mailhol, Vinod Koul, Neil Armstrong, Peter Rosin, Aaro Koskinen, Andreas Kemnade, Kevin Hilman, Roger Quadros, Tony Lindgren, Janusz Krzysztofik, Vignesh R, Andi Shyti, Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm, Wolfram Sang, Yazan Shhady, Jon Nettleton, Mikhail Anikin, linux-can, linux-phy, linux-kernel, linux-omap, linux-i2c, linux-mmc, devicetree, linux-renesas-soc Hi Josua, On Sun, 18 Jan 2026 at 11:29, Josua Mayer <josua@solid-run.com> wrote: > In-tree phy-can-transceiver driver has already implemented a local > version of devm_mux_state_get_optional. > > The omap-i2c driver gets and selects an optional mux in its probe > function without using any helper. > > Add new helper functions covering both aforementioned use-cases: > > - mux_control_get_optional: > Get a mux-control if specified in dt, return NULL otherwise. > - devm_mux_state_get_optional: > Get a mux-state if specified in dt, return NULL otherwise. > - devm_mux_state_get_selected: > Get and select a mux-state specified in dt, return error otherwise. > - devm_mux_state_get_optional_selected: > Get and select a mux-state if specified in dt, return error or NULL. > > Existing mux_get helper function is changed to take an extra argument > indicating whether the mux is optional. > In this case no error is printed, and NULL returned in case of ENOENT. > > Calling code is adapted to handle NULL return case, and to pass optional > argument as required. > > To support automatic deselect for _selected helper, a new structure is > created storing an exit pointer similar to clock core which is called on > release. > > To facilitate code sharing between optional/mandatory/selected helpers, > a new internal helper function is added to handle quiet (optional) and > verbose (mandatory) errors, as well as storing the correct callback for > devm release: __devm_mux_state_get > > Due to this structure devm_mux_state_get_*_selected can no longer print > a useful error message when select fails. Instead callers should print > errors where needed. > > Commit e153fdea9db04 ("phy: can-transceiver: Re-instate "mux-states" > property presence check") noted that "mux_get() always prints an error > message in case of an error, including when the property is not present, > confusing the user." > > The first error message covers the case that a mux name is not matched > in dt. The second error message is based on of_parse_phandle_with_args > return value. > > In optional case no error is printed and NULL is returned. > This ensures that the new helper functions will not confuse the user > either. > > With the addition of optional helper functions it became clear that > drivers should compile and link even if CONFIG_MULTIPLEXER was not enabled. > Add stubs for all symbols exported by mux core. > > Signed-off-by: Josua Mayer <josua@solid-run.com> Thanks for your patch! > --- a/drivers/mux/core.c > +++ b/drivers/mux/core.c > @@ -46,6 +46,16 @@ static const struct class mux_class = { > .name = "mux", > }; > > +/* > + * struct devm_mux_state_state - Tracks managed resources for mux-state objects. Please run scripts/checkpatch.pl: WARNING: please, no space before tabs #80: FILE: drivers/mux/core.c:50: + * struct devm_mux_state_state - ^ITracks managed resources for mux-state objects.$ > + * @mux: Pointer to a mux state. > + * @exit: An optional callback to execte before free. > + */ > +struct devm_mux_state_state { > + struct mux_state *mstate; > + int (*exit)(struct mux_state *mstate); > +}; > + > static DEFINE_IDA(mux_ida); > > static int __init mux_init(void) > --- a/include/linux/mux/consumer.h > +++ b/include/linux/mux/consumer.h > +static inline void mux_control_put(struct mux_control *mux) > +{ > + return; > +} WARNING: void function return statements are not generally useful #441: FILE: include/linux/mux/consumer.h:139: + return; Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v5 2/7] mux: Add helper functions for getting optional and selected mux-state @ 2026-01-20 15:57 ` Geert Uytterhoeven 0 siblings, 0 replies; 11+ messages in thread From: Geert Uytterhoeven @ 2026-01-20 15:57 UTC (permalink / raw) To: Josua Mayer Cc: Marc Kleine-Budde, Vincent Mailhol, Vinod Koul, Neil Armstrong, Peter Rosin, Aaro Koskinen, Andreas Kemnade, Kevin Hilman, Roger Quadros, Tony Lindgren, Janusz Krzysztofik, Vignesh R, Andi Shyti, Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm, Wolfram Sang, Yazan Shhady, Jon Nettleton, Mikhail Anikin, linux-can, linux-phy, linux-kernel, linux-omap, linux-i2c, linux-mmc, devicetree, linux-renesas-soc Hi Josua, On Sun, 18 Jan 2026 at 11:29, Josua Mayer <josua@solid-run.com> wrote: > In-tree phy-can-transceiver driver has already implemented a local > version of devm_mux_state_get_optional. > > The omap-i2c driver gets and selects an optional mux in its probe > function without using any helper. > > Add new helper functions covering both aforementioned use-cases: > > - mux_control_get_optional: > Get a mux-control if specified in dt, return NULL otherwise. > - devm_mux_state_get_optional: > Get a mux-state if specified in dt, return NULL otherwise. > - devm_mux_state_get_selected: > Get and select a mux-state specified in dt, return error otherwise. > - devm_mux_state_get_optional_selected: > Get and select a mux-state if specified in dt, return error or NULL. > > Existing mux_get helper function is changed to take an extra argument > indicating whether the mux is optional. > In this case no error is printed, and NULL returned in case of ENOENT. > > Calling code is adapted to handle NULL return case, and to pass optional > argument as required. > > To support automatic deselect for _selected helper, a new structure is > created storing an exit pointer similar to clock core which is called on > release. > > To facilitate code sharing between optional/mandatory/selected helpers, > a new internal helper function is added to handle quiet (optional) and > verbose (mandatory) errors, as well as storing the correct callback for > devm release: __devm_mux_state_get > > Due to this structure devm_mux_state_get_*_selected can no longer print > a useful error message when select fails. Instead callers should print > errors where needed. > > Commit e153fdea9db04 ("phy: can-transceiver: Re-instate "mux-states" > property presence check") noted that "mux_get() always prints an error > message in case of an error, including when the property is not present, > confusing the user." > > The first error message covers the case that a mux name is not matched > in dt. The second error message is based on of_parse_phandle_with_args > return value. > > In optional case no error is printed and NULL is returned. > This ensures that the new helper functions will not confuse the user > either. > > With the addition of optional helper functions it became clear that > drivers should compile and link even if CONFIG_MULTIPLEXER was not enabled. > Add stubs for all symbols exported by mux core. > > Signed-off-by: Josua Mayer <josua@solid-run.com> Thanks for your patch! > --- a/drivers/mux/core.c > +++ b/drivers/mux/core.c > @@ -46,6 +46,16 @@ static const struct class mux_class = { > .name = "mux", > }; > > +/* > + * struct devm_mux_state_state - Tracks managed resources for mux-state objects. Please run scripts/checkpatch.pl: WARNING: please, no space before tabs #80: FILE: drivers/mux/core.c:50: + * struct devm_mux_state_state - ^ITracks managed resources for mux-state objects.$ > + * @mux: Pointer to a mux state. > + * @exit: An optional callback to execte before free. > + */ > +struct devm_mux_state_state { > + struct mux_state *mstate; > + int (*exit)(struct mux_state *mstate); > +}; > + > static DEFINE_IDA(mux_ida); > > static int __init mux_init(void) > --- a/include/linux/mux/consumer.h > +++ b/include/linux/mux/consumer.h > +static inline void mux_control_put(struct mux_control *mux) > +{ > + return; > +} WARNING: void function return statements are not generally useful #441: FILE: include/linux/mux/consumer.h:139: + return; Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-01-21 9:01 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-01-18 18:03 [PATCH v5 2/7] mux: Add helper functions for getting optional and selected mux-state kernel test robot -- strict thread matches above, loose matches on Subject: below -- 2026-01-18 10:28 [PATCH v5 0/7] mmc: host: renesas_sdhi_core: support configuring an optional sdio mux Josua Mayer 2026-01-18 10:28 ` [PATCH v5 2/7] mux: Add helper functions for getting optional and selected mux-state Josua Mayer 2026-01-18 10:28 ` Josua Mayer 2026-01-18 13:28 ` kernel test robot 2026-01-18 13:28 ` kernel test robot 2026-01-20 9:45 ` Geert Uytterhoeven 2026-01-20 9:45 ` Geert Uytterhoeven 2026-01-21 9:00 ` Josua Mayer 2026-01-21 9:00 ` Josua Mayer 2026-01-20 15:57 ` Geert Uytterhoeven 2026-01-20 15:57 ` Geert Uytterhoeven
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.