public inbox for linux-next@vger.kernel.org
 help / color / mirror / Atom feed
From: Mark Brown <broonie@kernel.org>
To: Linus Walleij <linusw@kernel.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: Re: linux-next: manual merge of the pinctrl tree with the mmc tree
Date: Fri, 10 Apr 2026 14:31:29 +0100	[thread overview]
Message-ID: <adj7sSzHRAPGlVpT@sirena.co.uk> (raw)
In-Reply-To: <adj61MnOca5D8-rA@sirena.co.uk>

[-- Attachment #1: Type: text/plain, Size: 16365 bytes --]

On Fri, Apr 10, 2026 at 02:27:48PM +0100, Mark Brown wrote:
> Hi all,
> 
> Today's linux-next merge of the pinctrl tree got extensive and
> concerning conflicts in:

Replacing Linus' address.

> 
>   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 --]

  reply	other threads:[~2026-04-10 13:31 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-10 13:27 linux-next: manual merge of the pinctrl tree with the mmc tree Mark Brown
2026-04-10 13:31 ` Mark Brown [this message]
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=adj7sSzHRAPGlVpT@sirena.co.uk \
    --to=broonie@kernel.org \
    --cc=Frank.Li@nxp.com \
    --cc=josua@solid-run.com \
    --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