From: Mark Brown <broonie@kernel.org>
To: Linus Walleij <linus.walleij@linaro.org>
Cc: Frank Li <Frank.Li@nxp.com>, Josua Mayer <josua@solid-run.com>,
Linus Walleij <linusw@kernel.org>,
Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
Linux Next Mailing List <linux-next@vger.kernel.org>,
Ulf Hansson <ulf.hansson@linaro.org>,
Ulf Hansson <ulfh@kernel.org>
Subject: linux-next: manual merge of the pinctrl tree with the mmc tree
Date: Fri, 10 Apr 2026 14:27:48 +0100 [thread overview]
Message-ID: <adj61MnOca5D8-rA@sirena.co.uk> (raw)
[-- Attachment #1: Type: text/plain, Size: 15409 bytes --]
Hi all,
Today's linux-next merge of the pinctrl tree got extensive and
concerning conflicts in:
include/linux/mux/consumer.h
drivers/mux/core.c
between commit:
993bcaf32c4940 ("mux: Add helper functions for getting optional and selected mux-state")
from the mmc tree and commit:
bb23f1b8c28be9 ("mux: add devm_mux_control_get_from_np() to get mux from child node")
from the pinctrl tree, I'm not convinced that the latter commit is ready
as devm_get_mux_control_from_np() appears to ignore the np parameter.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
This fixup is very quick and hacky, I don't have huge confidence in it.
Indeed since making it I see more failures due to devm_mux_control_get()
not being exported, I have a hard time seeing how exactly
devm_get_mux_control_from_np() is intended to work given that it ignores
the np parameter and is just a straight rename/reprototype of that
function.
diff --cc drivers/mux/core.c
index 23538de2c91b41,9ca16b37d389b2..00000000000000
--- a/drivers/mux/core.c
+++ b/drivers/mux/core.c
@@@ -532,15 -522,15 +532,17 @@@ static struct mux_chip *of_find_mux_chi
* @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.
+ * @node: the device nodes, use dev->of_node if it is NULL.
*
- * Return: A pointer to the mux-control, or an ERR_PTR with a negative errno.
+ * Return: Pointer to the mux-control on success, an ERR_PTR with a negative
+ * errno on error, or NULL if optional is true and mux doesn't exist.
*/
static struct mux_control *mux_get(struct device *dev, const char *mux_name,
- unsigned int *state, bool optional)
- unsigned int *state,
++ unsigned int *state, bool optional,
+ struct device_node *node)
{
- struct device_node *np = dev->of_node;
+ struct device_node *np = node ? node : dev->of_node;
struct of_phandle_args args;
struct mux_chip *mux_chip;
unsigned int controller;
@@@ -635,29 -619,10 +637,29 @@@
*/
struct mux_control *mux_control_get(struct device *dev, const char *mux_name)
{
- struct mux_control *mux = mux_get(dev, mux_name, NULL, false);
- return mux_get(dev, mux_name, NULL, NULL);
++ struct mux_control *mux = mux_get(dev, mux_name, NULL, false, NULL);
+
+ if (!mux)
+ return ERR_PTR(-ENOENT);
+
+ return mux;
}
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: Pointer to the mux-control on success, an ERR_PTR with a negative
+ * errno on error, or NULL if mux doesn't exist.
+ */
+struct mux_control *mux_control_get_optional(struct device *dev, const char *mux_name)
+{
- return mux_get(dev, mux_name, NULL, true);
++ return mux_get(dev, mux_name, NULL, true, NULL);
+}
+EXPORT_SYMBOL_GPL(mux_control_get_optional);
+
/**
* mux_control_put() - Put away the mux-control for good.
* @mux: The mux-control to put away.
@@@ -705,18 -672,18 +709,20 @@@ devm_mux_control_get_from_np(struct dev
return mux;
}
- EXPORT_SYMBOL_GPL(devm_mux_control_get);
+ EXPORT_SYMBOL_GPL(devm_mux_control_get_from_np);
-/*
+/**
* mux_state_get() - Get the mux-state for a device.
* @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.
+ * @np: the device nodes, use dev->of_node if it is NULL.
*
- * Return: A pointer to the mux-state, or an ERR_PTR with a negative errno.
+ * Return: Pointer to the mux-state on success, an ERR_PTR with a negative
+ * errno on error, or NULL if optional is true and mux doesn't exist.
*/
- static struct mux_state *mux_state_get(struct device *dev, const char *mux_name, bool optional)
+ static struct mux_state *
-mux_state_get(struct device *dev, const char *mux_name, struct device_node *np)
++mux_state_get(struct device *dev, const char *mux_name, bool optional, struct device_node *np)
{
struct mux_state *mstate;
@@@ -724,7 -691,7 +730,7 @@@
if (!mstate)
return ERR_PTR(-ENOMEM);
- mstate->mux = mux_get(dev, mux_name, &mstate->state, optional);
- mstate->mux = mux_get(dev, mux_name, &mstate->state, np);
++ mstate->mux = mux_get(dev, mux_name, &mstate->state, optional, np);
if (IS_ERR(mstate->mux)) {
int err = PTR_ERR(mstate->mux);
@@@ -752,139 -716,43 +758,162 @@@ static void mux_state_put(struct mux_st
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;
+ if (devm_state->exit)
+ devm_state->exit(devm_state->mstate);
+
+ mux_state_put(devm_state->mstate);
+}
+
+/**
+ * __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 on success, an ERR_PTR with a negative
+ * errno on error, or NULL if optional is true and mux doesn't exist.
+ */
+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 devm_mux_state_state *devm_state;
+ struct mux_state *mstate;
+ int ret;
+
- mstate = mux_state_get(dev, mux_name, optional);
++ mstate = mux_state_get(dev, mux_name, optional, NULL);
+ if (IS_ERR(mstate))
+ return ERR_CAST(mstate);
+ else if (optional && !mstate)
+ return NULL;
+ else if (!mstate)
+ return ERR_PTR(-ENOENT);
+
+ devm_state = devres_alloc(devm_mux_state_release, sizeof(*devm_state), GFP_KERNEL);
+ if (!devm_state) {
+ ret = -ENOMEM;
+ goto err_devres_alloc;
+ }
+
+ if (init) {
+ ret = init(mstate);
+ if (ret)
+ goto err_mux_state_init;
+ }
+
+ devm_state->mstate = mstate;
+ devm_state->exit = exit;
+ devres_add(dev, devm_state);
+
+ return mstate;
+
+err_mux_state_init:
+ devres_free(devm_state);
+err_devres_alloc:
mux_state_put(mstate);
+ return ERR_PTR(ret);
+}
+
++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);
+ }
+
/**
- * devm_mux_state_get() - Get the mux-state for a device, with resource
- * management.
+ * devm_mux_state_get_from_np() - 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.
+ * @np: the device nodes, use dev->of_node if it is NULL.
*
* 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)
+ struct mux_state *
+ devm_mux_state_get_from_np(struct device *dev, const char *mux_name,
+ struct device_node *np)
{
- return __devm_mux_state_get(dev, mux_name, false, NULL, NULL);
+ struct mux_state **ptr, *mstate;
+
+ ptr = devres_alloc(devm_mux_state_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
- mstate = mux_state_get(dev, mux_name, np);
++ mstate = mux_state_get(dev, mux_name, false, np);
+ if (IS_ERR(mstate)) {
+ devres_free(ptr);
+ return mstate;
+ }
+
+ *ptr = mstate;
+ devres_add(dev, ptr);
+
+ return mstate;
}
- EXPORT_SYMBOL_GPL(devm_mux_state_get);
+ EXPORT_SYMBOL_GPL(devm_mux_state_get_from_np);
+/**
+ * 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 on success, an ERR_PTR with a negative
+ * errno on error, or NULL if mux doesn't exist.
+ *
+ * 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 on success, an ERR_PTR with a negative
+ * errno on error, or NULL if mux doesn't exist.
+ *
+ * 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 --cc include/linux/mux/consumer.h
index a961861a503b33,6300e091035323..00000000000000
--- a/include/linux/mux/consumer.h
+++ b/include/linux/mux/consumer.h
@@@ -55,110 -53,20 +55,118 @@@ static inline int __must_check mux_stat
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);
-void mux_control_put(struct mux_control *mux);
-
+ struct mux_control *
+ devm_mux_control_get_from_np(struct device *dev, const char *mux_name,
+ struct device_node *np);
+
-#define devm_mux_control_get(dev, mux_name) \
- devm_mux_control_get_from_np(dev, mux_name, NULL)
-
+ struct mux_state *
+ devm_mux_state_get_from_np(struct device *dev, const char *mux_name,
+ struct device_node *np);
-#define devm_mux_state_get(dev, mux_name) \
- devm_mux_state_get_from_np(dev, mux_name, NULL)
++
+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_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) {}
+
+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 */
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
next reply other threads:[~2026-04-10 13:27 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-10 13:27 Mark Brown [this message]
2026-04-10 13:31 ` linux-next: manual merge of the pinctrl tree with the mmc tree Mark Brown
2026-04-10 13:36 ` Ulf Hansson
2026-04-10 13:42 ` Mark Brown
2026-04-10 18:10 ` Linus Walleij
-- strict thread matches above, loose matches on Subject: below --
2023-02-16 1:40 Stephen Rothwell
2023-02-23 0:13 ` Stephen Rothwell
2023-02-23 9:58 ` Emil Renner Berthing
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=adj61MnOca5D8-rA@sirena.co.uk \
--to=broonie@kernel.org \
--cc=Frank.Li@nxp.com \
--cc=josua@solid-run.com \
--cc=linus.walleij@linaro.org \
--cc=linusw@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-next@vger.kernel.org \
--cc=ulf.hansson@linaro.org \
--cc=ulfh@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox