diff mbox

[01/10] i2c-mux: add common core data for every mux instance

Message ID 1451920215-29167-2-git-send-email-peda@lysator.liu.se
State Superseded
Headers show

Commit Message

Peter Rosin Jan. 4, 2016, 3:10 p.m. UTC
From: Peter Rosin <peda@axentia.se>

The initial core mux structure starts off small with only the parent
adapter pointer, which all muxes have, and a priv pointer for mux
driver private data.

Add i2c_mux_alloc function to unify the creation of a mux.

Where appropriate, pass around the mux core structure instead of the
parent adapter or the driver private data.

Remove the parent adapter pointer from the driver private data for all
mux drivers.

Signed-off-by: Peter Rosin <peda@axentia.se>
---
 drivers/i2c/i2c-mux.c                      | 35 ++++++++++++++++++++++++-----
 drivers/i2c/muxes/i2c-arb-gpio-challenge.c | 24 +++++++++++---------
 drivers/i2c/muxes/i2c-mux-gpio.c           | 20 +++++++++--------
 drivers/i2c/muxes/i2c-mux-pca9541.c        | 36 ++++++++++++++++--------------
 drivers/i2c/muxes/i2c-mux-pca954x.c        | 22 +++++++++++++-----
 drivers/i2c/muxes/i2c-mux-pinctrl.c        | 24 +++++++++++---------
 drivers/i2c/muxes/i2c-mux-reg.c            | 25 ++++++++++++---------
 include/linux/i2c-mux.h                    | 14 +++++++++++-
 8 files changed, 129 insertions(+), 71 deletions(-)

Comments

Guenter Roeck Jan. 4, 2016, 3:37 p.m. UTC | #1
On 01/04/2016 07:10 AM, Peter Rosin wrote:
> From: Peter Rosin <peda@axentia.se>
>
> The initial core mux structure starts off small with only the parent
> adapter pointer, which all muxes have, and a priv pointer for mux
> driver private data.
>
> Add i2c_mux_alloc function to unify the creation of a mux.
>
> Where appropriate, pass around the mux core structure instead of the
> parent adapter or the driver private data.
>
> Remove the parent adapter pointer from the driver private data for all
> mux drivers.
>
> Signed-off-by: Peter Rosin <peda@axentia.se>
> ---
>   drivers/i2c/i2c-mux.c                      | 35 ++++++++++++++++++++++++-----
>   drivers/i2c/muxes/i2c-arb-gpio-challenge.c | 24 +++++++++++---------
>   drivers/i2c/muxes/i2c-mux-gpio.c           | 20 +++++++++--------
>   drivers/i2c/muxes/i2c-mux-pca9541.c        | 36 ++++++++++++++++--------------
>   drivers/i2c/muxes/i2c-mux-pca954x.c        | 22 +++++++++++++-----
>   drivers/i2c/muxes/i2c-mux-pinctrl.c        | 24 +++++++++++---------
>   drivers/i2c/muxes/i2c-mux-reg.c            | 25 ++++++++++++---------
>   include/linux/i2c-mux.h                    | 14 +++++++++++-
>   8 files changed, 129 insertions(+), 71 deletions(-)
>
> diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
> index 00fc5b1c7b66..99fd9106abc6 100644
> --- a/drivers/i2c/i2c-mux.c
> +++ b/drivers/i2c/i2c-mux.c
> @@ -31,8 +31,8 @@
>   struct i2c_mux_priv {
>   	struct i2c_adapter adap;
>   	struct i2c_algorithm algo;
> +	struct i2c_mux_core *muxc;
>
> -	struct i2c_adapter *parent;
>   	struct device *mux_dev;
>   	void *mux_priv;
>   	u32 chan_id;
> @@ -45,7 +45,8 @@ static int i2c_mux_master_xfer(struct i2c_adapter *adap,
>   			       struct i2c_msg msgs[], int num)
>   {
>   	struct i2c_mux_priv *priv = adap->algo_data;
> -	struct i2c_adapter *parent = priv->parent;
> +	struct i2c_mux_core *muxc = priv->muxc;
> +	struct i2c_adapter *parent = muxc->parent;
>   	int ret;
>
>   	/* Switch to the right mux port and perform the transfer. */
> @@ -65,7 +66,8 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,
>   			      int size, union i2c_smbus_data *data)
>   {
>   	struct i2c_mux_priv *priv = adap->algo_data;
> -	struct i2c_adapter *parent = priv->parent;
> +	struct i2c_mux_core *muxc = priv->muxc;
> +	struct i2c_adapter *parent = muxc->parent;
>   	int ret;
>
>   	/* Select the right mux port and perform the transfer. */
> @@ -84,7 +86,7 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,
>   static u32 i2c_mux_functionality(struct i2c_adapter *adap)
>   {
>   	struct i2c_mux_priv *priv = adap->algo_data;
> -	struct i2c_adapter *parent = priv->parent;
> +	struct i2c_adapter *parent = priv->muxc->parent;
>
>   	return parent->algo->functionality(parent);
>   }
> @@ -102,7 +104,27 @@ static unsigned int i2c_mux_parent_classes(struct i2c_adapter *parent)
>   	return class;
>   }
>
> -struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
> +struct i2c_mux_core *i2c_mux_alloc(struct device *dev, int sizeof_priv)
> +{
> +	struct i2c_mux_core *muxc;
> +
> +	muxc = devm_kzalloc(dev, sizeof(*muxc), GFP_KERNEL);
> +	if (!muxc)
> +		return NULL;
> +	if (sizeof_priv) {
> +		muxc->priv = devm_kzalloc(dev, sizeof_priv, GFP_KERNEL);
> +		if (!muxc->priv)
> +			goto fail;
> +	}

Why not just allocate sizeof(*muxc) + sizeof_priv in a single operation
and then assign muxc->priv to muxc + 1 if sizeof_priv > 0 ?

> +	return muxc;
> +
> +fail:
> +	devm_kfree(dev, muxc);
> +	return NULL;
> +}
> +EXPORT_SYMBOL_GPL(i2c_mux_alloc);
> +
> +struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
>   				struct device *mux_dev,
>   				void *mux_priv, u32 force_nr, u32 chan_id,
>   				unsigned int class,
> @@ -111,6 +133,7 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
>   				int (*deselect) (struct i2c_adapter *,
>   						 void *, u32))
>   {
> +	struct i2c_adapter *parent = muxc->parent;
>   	struct i2c_mux_priv *priv;
>   	char symlink_name[20];
>   	int ret;
> @@ -120,7 +143,7 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
>   		return NULL;
>
>   	/* Set up private adapter data */
> -	priv->parent = parent;
> +	priv->muxc = muxc;
>   	priv->mux_dev = mux_dev;
>   	priv->mux_priv = mux_priv;
>   	priv->chan_id = chan_id;
> diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
> index 402e3a6c671a..dd616c0280ad 100644
> --- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
> +++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
> @@ -42,7 +42,6 @@
>    */
>
>   struct i2c_arbitrator_data {
> -	struct i2c_adapter *parent;
>   	struct i2c_adapter *child;
>   	int our_gpio;
>   	int our_gpio_release;
> @@ -119,6 +118,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
>   	struct device *dev = &pdev->dev;
>   	struct device_node *np = dev->of_node;
>   	struct device_node *parent_np;
> +	struct i2c_mux_core *muxc;
>   	struct i2c_arbitrator_data *arb;
>   	enum of_gpio_flags gpio_flags;
>   	unsigned long out_init;
> @@ -134,13 +134,14 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
>   		return -EINVAL;
>   	}
>
> -	arb = devm_kzalloc(dev, sizeof(*arb), GFP_KERNEL);
> -	if (!arb) {
> -		dev_err(dev, "Cannot allocate i2c_arbitrator_data\n");
> +	muxc = i2c_mux_alloc(dev, sizeof(*arb));
> +	if (!muxc) {
> +		dev_err(dev, "Cannot allocate i2c_mux_core structure\n");

Unnecessary error message.

>   		return -ENOMEM;
>   	}
> -	platform_set_drvdata(pdev, arb);
> +	arb = i2c_mux_priv(muxc);
>
> +	platform_set_drvdata(pdev, muxc);
>   	/* Request GPIOs */
>   	ret = of_get_named_gpio_flags(np, "our-claim-gpio", 0, &gpio_flags);
>   	if (!gpio_is_valid(ret)) {
> @@ -196,21 +197,21 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
>   		dev_err(dev, "Cannot parse i2c-parent\n");
>   		return -EINVAL;
>   	}
> -	arb->parent = of_get_i2c_adapter_by_node(parent_np);
> +	muxc->parent = of_find_i2c_adapter_by_node(parent_np);
>   	of_node_put(parent_np);
> -	if (!arb->parent) {
> +	if (!muxc->parent) {
>   		dev_err(dev, "Cannot find parent bus\n");
>   		return -EPROBE_DEFER;
>   	}
>
>   	/* Actually add the mux adapter */
> -	arb->child = i2c_add_mux_adapter(arb->parent, dev, arb, 0, 0, 0,
> +	arb->child = i2c_add_mux_adapter(muxc, dev, arb, 0, 0, 0,
>   					 i2c_arbitrator_select,
>   					 i2c_arbitrator_deselect);
>   	if (!arb->child) {
>   		dev_err(dev, "Failed to add adapter\n");
>   		ret = -ENODEV;
> -		i2c_put_adapter(arb->parent);
> +		i2c_put_adapter(muxc->parent);
>   	}
>
>   	return ret;
> @@ -218,10 +219,11 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
>
>   static int i2c_arbitrator_remove(struct platform_device *pdev)
>   {
> -	struct i2c_arbitrator_data *arb = platform_get_drvdata(pdev);
> +	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
> +	struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc);
>
>   	i2c_del_mux_adapter(arb->child);
> -	i2c_put_adapter(arb->parent);
> +	i2c_put_adapter(muxc->parent);
>
>   	return 0;
>   }
> diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
> index b8e11c16d98c..3de6dc79c1db 100644
> --- a/drivers/i2c/muxes/i2c-mux-gpio.c
> +++ b/drivers/i2c/muxes/i2c-mux-gpio.c
> @@ -18,7 +18,6 @@
>   #include <linux/of_gpio.h>
>
>   struct gpiomux {
> -	struct i2c_adapter *parent;
>   	struct i2c_adapter **adap; /* child busses */
>   	struct i2c_mux_gpio_platform_data data;
>   	unsigned gpio_base;
> @@ -136,19 +135,21 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
>
>   static int i2c_mux_gpio_probe(struct platform_device *pdev)
>   {
> +	struct i2c_mux_core *muxc;
>   	struct gpiomux *mux;
>   	struct i2c_adapter *parent;
>   	int (*deselect) (struct i2c_adapter *, void *, u32);
>   	unsigned initial_state, gpio_base;
>   	int i, ret;
>
> -	mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
> -	if (!mux) {
> -		dev_err(&pdev->dev, "Cannot allocate gpiomux structure");
> +	muxc = i2c_mux_alloc(&pdev->dev, sizeof(*mux));
> +	if (!muxc) {
> +		dev_err(&pdev->dev, "Cannot allocate i2c_mux_core structure\n");

Unnecessary error message.

>   		return -ENOMEM;
>   	}
> +	mux = i2c_mux_priv(muxc);
>
> -	platform_set_drvdata(pdev, mux);
> +	platform_set_drvdata(pdev, muxc);
>
>   	if (!dev_get_platdata(&pdev->dev)) {
>   		ret = i2c_mux_gpio_probe_dt(mux, pdev);
> @@ -180,7 +181,7 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
>   	if (!parent)
>   		return -EPROBE_DEFER;
>
> -	mux->parent = parent;
> +	muxc->parent = parent;
>   	mux->gpio_base = gpio_base;
>
>   	mux->adap = devm_kzalloc(&pdev->dev,
> @@ -223,7 +224,7 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
>   		u32 nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0;
>   		unsigned int class = mux->data.classes ? mux->data.classes[i] : 0;
>
> -		mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr,
> +		mux->adap[i] = i2c_add_mux_adapter(muxc, &pdev->dev, mux, nr,
>   						   mux->data.values[i], class,
>   						   i2c_mux_gpio_select, deselect);
>   		if (!mux->adap[i]) {
> @@ -253,7 +254,8 @@ alloc_failed:
>
>   static int i2c_mux_gpio_remove(struct platform_device *pdev)
>   {
> -	struct gpiomux *mux = platform_get_drvdata(pdev);
> +	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
> +	struct gpiomux *mux = i2c_mux_priv(muxc);
>   	int i;
>
>   	for (i = 0; i < mux->data.n_values; i++)
> @@ -262,7 +264,7 @@ static int i2c_mux_gpio_remove(struct platform_device *pdev)
>   	for (i = 0; i < mux->data.n_gpios; i++)
>   		gpio_free(mux->gpio_base + mux->data.gpios[i]);
>
> -	i2c_put_adapter(mux->parent);
> +	i2c_put_adapter(muxc->parent);
>
>   	return 0;
>   }
> diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c
> index d0ba424adebc..b2525a772d3b 100644
> --- a/drivers/i2c/muxes/i2c-mux-pca9541.c
> +++ b/drivers/i2c/muxes/i2c-mux-pca9541.c
> @@ -73,6 +73,7 @@
>   #define SELECT_DELAY_LONG	1000
>
>   struct pca9541 {
> +	struct i2c_client *client;
>   	struct i2c_adapter *mux_adap;
>   	unsigned long select_timeout;
>   	unsigned long arb_timeout;
> @@ -217,7 +218,8 @@ static const u8 pca9541_control[16] = {
>    */
>   static int pca9541_arbitrate(struct i2c_client *client)
>   {
> -	struct pca9541 *data = i2c_get_clientdata(client);
> +	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
> +	struct pca9541 *data = i2c_mux_priv(muxc);
>   	int reg;
>
>   	reg = pca9541_reg_read(client, PCA9541_CONTROL);
> @@ -324,20 +326,25 @@ static int pca9541_probe(struct i2c_client *client,
>   {
>   	struct i2c_adapter *adap = client->adapter;
>   	struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev);
> +	struct i2c_mux_core *muxc;
>   	struct pca9541 *data;
>   	int force;
> -	int ret = -ENODEV;
>
>   	if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA))
> -		goto err;
> +		return -ENODEV;
>
> -	data = kzalloc(sizeof(struct pca9541), GFP_KERNEL);
> -	if (!data) {
> -		ret = -ENOMEM;
> -		goto err;
> +	muxc = i2c_mux_alloc(&client->dev, sizeof(*data));
> +	if (!muxc) {
> +		dev_err(&client->dev,
> +			"Cannot allocate i2c_mux_core structure\n");
> +		return -ENOMEM;

Error messages are not needed for memory allocation failures.

>   	}
> +	data = i2c_mux_priv(muxc);
> +
> +	i2c_set_clientdata(client, muxc);
>
> -	i2c_set_clientdata(client, data);
> +	data->client = client;
> +	muxc->parent = adap;
>
>   	/*
>   	 * I2C accesses are unprotected here.
> @@ -352,34 +359,29 @@ static int pca9541_probe(struct i2c_client *client,
>   	force = 0;
>   	if (pdata)
>   		force = pdata->modes[0].adap_id;
> -	data->mux_adap = i2c_add_mux_adapter(adap, &client->dev, client,
> +	data->mux_adap = i2c_add_mux_adapter(muxc, &client->dev, client,
>   					     force, 0, 0,
>   					     pca9541_select_chan,
>   					     pca9541_release_chan);
>
>   	if (data->mux_adap == NULL) {
>   		dev_err(&client->dev, "failed to register master selector\n");
> -		goto exit_free;
> +		return -ENODEV;
>   	}
>
>   	dev_info(&client->dev, "registered master selector for I2C %s\n",
>   		 client->name);
>
>   	return 0;
> -
> -exit_free:
> -	kfree(data);
> -err:
> -	return ret;
>   }
>
>   static int pca9541_remove(struct i2c_client *client)
>   {
> -	struct pca9541 *data = i2c_get_clientdata(client);
> +	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
> +	struct pca9541 *data = i2c_mux_priv(muxc);
>
>   	i2c_del_mux_adapter(data->mux_adap);
>
> -	kfree(data);
>   	return 0;
>   }
>
> diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
> index acfcef3d4068..00eda06a667e 100644
> --- a/drivers/i2c/muxes/i2c-mux-pca954x.c
> +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
> @@ -63,6 +63,7 @@ struct pca954x {
>   	struct i2c_adapter *virt_adaps[PCA954X_MAX_NCHANS];
>
>   	u8 last_chan;		/* last register value */
> +	struct i2c_client *client;
>   };
>
>   struct chip_desc {
> @@ -191,17 +192,23 @@ static int pca954x_probe(struct i2c_client *client,
>   	bool idle_disconnect_dt;
>   	struct gpio_desc *gpio;
>   	int num, force, class;
> +	struct i2c_mux_core *muxc;
>   	struct pca954x *data;
>   	int ret;
>
>   	if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
>   		return -ENODEV;
>
> -	data = devm_kzalloc(&client->dev, sizeof(struct pca954x), GFP_KERNEL);
> -	if (!data)
> +	muxc = i2c_mux_alloc(&client->dev, sizeof(*data));
> +	if (!muxc) {
> +		dev_err(&client->dev,
> +			"Cannot allocate i2c_mux_core structure\n");

Unnecessary error message.

>   		return -ENOMEM;
> +	}
> +	data = i2c_mux_priv(muxc);
>
> -	i2c_set_clientdata(client, data);
> +	i2c_set_clientdata(client, muxc);
> +	data->client = client;
>
>   	/* Get the mux out of reset if a reset GPIO is specified. */
>   	gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW);
> @@ -217,6 +224,7 @@ static int pca954x_probe(struct i2c_client *client,
>   		return -ENODEV;
>   	}
>
> +	muxc->parent = adap;
>   	data->type = id->driver_data;
>   	data->last_chan = 0;		   /* force the first selection */
>
> @@ -241,7 +249,7 @@ static int pca954x_probe(struct i2c_client *client,
>   		}
>
>   		data->virt_adaps[num] =
> -			i2c_add_mux_adapter(adap, &client->dev, client,
> +			i2c_add_mux_adapter(muxc, &client->dev, client,
>   				force, num, class, pca954x_select_chan,
>   				(idle_disconnect_pd || idle_disconnect_dt)
>   					? pca954x_deselect_mux : NULL);
> @@ -270,7 +278,8 @@ virt_reg_failed:
>
>   static int pca954x_remove(struct i2c_client *client)
>   {
> -	struct pca954x *data = i2c_get_clientdata(client);
> +	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
> +	struct pca954x *data = i2c_mux_priv(muxc);
>   	const struct chip_desc *chip = &chips[data->type];
>   	int i;
>
> @@ -287,7 +296,8 @@ static int pca954x_remove(struct i2c_client *client)
>   static int pca954x_resume(struct device *dev)
>   {
>   	struct i2c_client *client = to_i2c_client(dev);
> -	struct pca954x *data = i2c_get_clientdata(client);
> +	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
> +	struct pca954x *data = i2c_mux_priv(muxc);
>
>   	data->last_chan = 0;
>   	return i2c_smbus_write_byte(client, 0);
> diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c
> index b5a982ba8898..cd3b73e208ce 100644
> --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c
> +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c
> @@ -31,7 +31,6 @@ struct i2c_mux_pinctrl {
>   	struct pinctrl *pinctrl;
>   	struct pinctrl_state **states;
>   	struct pinctrl_state *state_idle;
> -	struct i2c_adapter *parent;
>   	struct i2c_adapter **busses;
>   };
>
> @@ -131,17 +130,19 @@ static inline int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
>
>   static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
>   {
> +	struct i2c_mux_core *muxc;
>   	struct i2c_mux_pinctrl *mux;
>   	int (*deselect)(struct i2c_adapter *, void *, u32);
>   	int i, ret;
>
> -	mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
> -	if (!mux) {
> -		dev_err(&pdev->dev, "Cannot allocate i2c_mux_pinctrl\n");
> +	muxc = i2c_mux_alloc(&pdev->dev, sizeof(*mux));
> +	if (!muxc) {
> +		dev_err(&pdev->dev, "Cannot allocate i2c_mux_core structure\n");

Unnecessary.

>   		ret = -ENOMEM;
>   		goto err;
>   	}
> -	platform_set_drvdata(pdev, mux);
> +	mux = i2c_mux_priv(muxc);
> +	platform_set_drvdata(pdev, muxc);
>
>   	mux->dev = &pdev->dev;
>
> @@ -208,8 +209,8 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
>   		deselect = NULL;
>   	}
>
> -	mux->parent = i2c_get_adapter(mux->pdata->parent_bus_num);
> -	if (!mux->parent) {
> +	muxc->parent = i2c_get_adapter(mux->pdata->parent_bus_num);
> +	if (!muxc->parent) {
>   		dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
>   			mux->pdata->parent_bus_num);
>   		ret = -EPROBE_DEFER;
> @@ -220,7 +221,7 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
>   		u32 bus = mux->pdata->base_bus_num ?
>   				(mux->pdata->base_bus_num + i) : 0;
>
> -		mux->busses[i] = i2c_add_mux_adapter(mux->parent, &pdev->dev,
> +		mux->busses[i] = i2c_add_mux_adapter(muxc, &pdev->dev,
>   						     mux, bus, i, 0,
>   						     i2c_mux_pinctrl_select,
>   						     deselect);
> @@ -236,20 +237,21 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
>   err_del_adapter:
>   	for (; i > 0; i--)
>   		i2c_del_mux_adapter(mux->busses[i - 1]);
> -	i2c_put_adapter(mux->parent);
> +	i2c_put_adapter(muxc->parent);
>   err:
>   	return ret;
>   }
>
>   static int i2c_mux_pinctrl_remove(struct platform_device *pdev)
>   {
> -	struct i2c_mux_pinctrl *mux = platform_get_drvdata(pdev);
> +	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
> +	struct i2c_mux_pinctrl *mux = i2c_mux_priv(muxc);
>   	int i;
>
>   	for (i = 0; i < mux->pdata->bus_count; i++)
>   		i2c_del_mux_adapter(mux->busses[i]);
>
> -	i2c_put_adapter(mux->parent);
> +	i2c_put_adapter(muxc->parent);
>
>   	return 0;
>   }
> diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c
> index 5fbd5bd0878f..76244aca154e 100644
> --- a/drivers/i2c/muxes/i2c-mux-reg.c
> +++ b/drivers/i2c/muxes/i2c-mux-reg.c
> @@ -21,7 +21,6 @@
>   #include <linux/slab.h>
>
>   struct regmux {
> -	struct i2c_adapter *parent;
>   	struct i2c_adapter **adap; /* child busses */
>   	struct i2c_mux_reg_platform_data data;
>   };
> @@ -87,6 +86,7 @@ static int i2c_mux_reg_deselect(struct i2c_adapter *adap, void *data,
>   static int i2c_mux_reg_probe_dt(struct regmux *mux,
>   					struct platform_device *pdev)
>   {
> +	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
>   	struct device_node *np = pdev->dev.of_node;
>   	struct device_node *adapter_np, *child;
>   	struct i2c_adapter *adapter;
> @@ -107,7 +107,7 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
>   	if (!adapter)
>   		return -EPROBE_DEFER;
>
> -	mux->parent = adapter;
> +	muxc->parent = adapter;
>   	mux->data.parent = i2c_adapter_id(adapter);
>   	put_device(&adapter->dev);
>
> @@ -169,6 +169,7 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
>
>   static int i2c_mux_reg_probe(struct platform_device *pdev)
>   {
> +	struct i2c_mux_core *muxc;
>   	struct regmux *mux;
>   	struct i2c_adapter *parent;
>   	struct resource *res;
> @@ -176,11 +177,14 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
>   	unsigned int class;
>   	int i, ret, nr;
>
> -	mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
> -	if (!mux)
> +	muxc = i2c_mux_alloc(&pdev->dev, sizeof(*mux));
> +	if (!muxc) {
> +		dev_err(&pdev->dev, "Cannot allocate i2c_mux_core structure\n");

Unnecessary.

>   		return -ENOMEM;
> +	}
> +	mux = i2c_mux_priv(muxc);
>
> -	platform_set_drvdata(pdev, mux);
> +	platform_set_drvdata(pdev, muxc);
>
>   	if (dev_get_platdata(&pdev->dev)) {
>   		memcpy(&mux->data, dev_get_platdata(&pdev->dev),
> @@ -190,7 +194,7 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
>   		if (!parent)
>   			return -EPROBE_DEFER;
>
> -		mux->parent = parent;
> +		muxc->parent = parent;
>   	} else {
>   		ret = i2c_mux_reg_probe_dt(mux, pdev);
>   		if (ret < 0) {
> @@ -232,7 +236,7 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
>   		nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0;
>   		class = mux->data.classes ? mux->data.classes[i] : 0;
>
> -		mux->adap[i] = i2c_add_mux_adapter(mux->parent, &pdev->dev, mux,
> +		mux->adap[i] = i2c_add_mux_adapter(muxc, &pdev->dev, mux,
>   						   nr, mux->data.values[i],
>   						   class, i2c_mux_reg_select,
>   						   deselect);
> @@ -244,7 +248,7 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
>   	}
>
>   	dev_dbg(&pdev->dev, "%d port mux on %s adapter\n",
> -		 mux->data.n_values, mux->parent->name);
> +		 mux->data.n_values, muxc->parent->name);
>
>   	return 0;
>
> @@ -257,13 +261,14 @@ add_adapter_failed:
>
>   static int i2c_mux_reg_remove(struct platform_device *pdev)
>   {
> -	struct regmux *mux = platform_get_drvdata(pdev);
> +	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
> +	struct regmux *mux = i2c_mux_priv(muxc);
>   	int i;
>
>   	for (i = 0; i < mux->data.n_values; i++)
>   		i2c_del_mux_adapter(mux->adap[i]);
>
> -	i2c_put_adapter(mux->parent);
> +	i2c_put_adapter(muxc->parent);
>
>   	return 0;
>   }
> diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h
> index b5f9a007a3ab..3ca1783b86ac 100644
> --- a/include/linux/i2c-mux.h
> +++ b/include/linux/i2c-mux.h
> @@ -27,13 +27,25 @@
>
>   #ifdef __KERNEL__
>
> +struct i2c_mux_core {
> +	struct i2c_adapter *parent;
> +	void *priv;
> +};
> +
> +struct i2c_mux_core *i2c_mux_alloc(struct device *dev, int sizeof_priv);
> +
> +static inline void *i2c_mux_priv(struct i2c_mux_core *muxc)
> +{
> +	return muxc->priv;
> +}
> +
>   /*
>    * Called to create a i2c bus on a multiplexed bus segment.
>    * The mux_dev and chan_id parameters are passed to the select
>    * and deselect callback functions to perform hardware-specific
>    * mux control.
>    */
> -struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
> +struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
>   				struct device *mux_dev,
>   				void *mux_priv, u32 force_nr, u32 chan_id,
>   				unsigned int class,
>

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
kernel test robot Jan. 4, 2016, 3:46 p.m. UTC | #2
Hi Peter,

[auto build test WARNING on wsa/i2c/for-next]
[also build test WARNING on v4.4-rc8 next-20160104]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Peter-Rosin/i2c-mux-cleanup-and-locking-update/20160104-231355
base:   https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux i2c/for-next
config: x86_64-randconfig-i0-201601 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

   drivers/media/dvb-frontends/m88ds3103.c: In function 'm88ds3103_probe':
>> drivers/media/dvb-frontends/m88ds3103.c:1470:41: warning: passing argument 1 of 'i2c_add_mux_adapter' from incompatible pointer type [-Wincompatible-pointer-types]
     dev->i2c_adapter = i2c_add_mux_adapter(client->adapter, &client->dev,
                                            ^
   In file included from drivers/media/dvb-frontends/m88ds3103_priv.h:24:0,
                    from drivers/media/dvb-frontends/m88ds3103.c:17:
   include/linux/i2c-mux.h:48:21: note: expected 'struct i2c_mux_core *' but argument is of type 'struct i2c_adapter *'
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^
--
   drivers/media/dvb-frontends/rtl2830.c: In function 'rtl2830_probe':
>> drivers/media/dvb-frontends/rtl2830.c:868:37: warning: passing argument 1 of 'i2c_add_mux_adapter' from incompatible pointer type [-Wincompatible-pointer-types]
     dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev,
                                        ^
   In file included from drivers/media/dvb-frontends/rtl2830_priv.h:24:0,
                    from drivers/media/dvb-frontends/rtl2830.c:18:
   include/linux/i2c-mux.h:48:21: note: expected 'struct i2c_mux_core *' but argument is of type 'struct i2c_adapter *'
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^

vim +/i2c_add_mux_adapter +1470 drivers/media/dvb-frontends/m88ds3103.c

478932b16 Antti Palosaari 2015-04-16  1454  	ret = regmap_write(dev->regmap, 0x29, utmp);
395d00d1c Antti Palosaari 2013-02-25  1455  	if (ret)
f01919e8f Antti Palosaari 2015-04-16  1456  		goto err_kfree;
395d00d1c Antti Palosaari 2013-02-25  1457  
395d00d1c Antti Palosaari 2013-02-25  1458  	/* sleep */
56ea37da3 Antti Palosaari 2015-10-03  1459  	ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x00);
395d00d1c Antti Palosaari 2013-02-25  1460  	if (ret)
f01919e8f Antti Palosaari 2015-04-16  1461  		goto err_kfree;
56ea37da3 Antti Palosaari 2015-10-03  1462  	ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x01);
395d00d1c Antti Palosaari 2013-02-25  1463  	if (ret)
f01919e8f Antti Palosaari 2015-04-16  1464  		goto err_kfree;
56ea37da3 Antti Palosaari 2015-10-03  1465  	ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x10);
395d00d1c Antti Palosaari 2013-02-25  1466  	if (ret)
f01919e8f Antti Palosaari 2015-04-16  1467  		goto err_kfree;
395d00d1c Antti Palosaari 2013-02-25  1468  
44b9055b4 Antti Palosaari 2013-11-19  1469  	/* create mux i2c adapter for tuner */
f01919e8f Antti Palosaari 2015-04-16 @1470  	dev->i2c_adapter = i2c_add_mux_adapter(client->adapter, &client->dev,
f01919e8f Antti Palosaari 2015-04-16  1471  					       dev, 0, 0, 0, m88ds3103_select,
478932b16 Antti Palosaari 2015-04-16  1472  					       NULL);
4347df6a7 Dan Carpenter   2015-06-02  1473  	if (dev->i2c_adapter == NULL) {
4347df6a7 Dan Carpenter   2015-06-02  1474  		ret = -ENOMEM;
f01919e8f Antti Palosaari 2015-04-16  1475  		goto err_kfree;
4347df6a7 Dan Carpenter   2015-06-02  1476  	}
44b9055b4 Antti Palosaari 2013-11-19  1477  
395d00d1c Antti Palosaari 2013-02-25  1478  	/* create dvb_frontend */

:::::: The code at line 1470 was first introduced by commit
:::::: f01919e8f54f645fb00fdb823fe266e21eebe3b1 [media] m88ds3103: add I2C client binding

:::::: TO: Antti Palosaari <crope@iki.fi>
:::::: CC: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
kernel test robot Jan. 4, 2016, 3:49 p.m. UTC | #3
Hi Peter,

[auto build test WARNING on wsa/i2c/for-next]
[also build test WARNING on v4.4-rc8 next-20160104]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Peter-Rosin/i2c-mux-cleanup-and-locking-update/20160104-231355
base:   https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux i2c/for-next
config: i386-randconfig-i0-01042049 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All warnings (new ones prefixed by >>):

   drivers/iio/imu/inv_mpu6050/inv_mpu_core.c: In function 'inv_mpu_probe':
>> drivers/iio/imu/inv_mpu6050/inv_mpu_core.c:845:40: warning: passing argument 1 of 'i2c_add_mux_adapter' from incompatible pointer type [-Wincompatible-pointer-types]
     st->mux_adapter = i2c_add_mux_adapter(client->adapter,
                                           ^
   In file included from drivers/iio/imu/inv_mpu6050/inv_mpu_core.c:26:0:
   include/linux/i2c-mux.h:48:21: note: expected 'struct i2c_mux_core *' but argument is of type 'struct i2c_adapter *'
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^
--
   drivers/of/unittest.c: In function 'unittest_i2c_mux_probe':
>> drivers/of/unittest.c:1730:38: warning: passing argument 1 of 'i2c_add_mux_adapter' from incompatible pointer type [-Wincompatible-pointer-types]
      stm->adap[i] = i2c_add_mux_adapter(adap, dev, client,
                                         ^
   In file included from drivers/of/unittest.c:24:0:
   include/linux/i2c-mux.h:48:21: note: expected 'struct i2c_mux_core *' but argument is of type 'struct i2c_adapter *'
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^

vim +/i2c_add_mux_adapter +845 drivers/iio/imu/inv_mpu6050/inv_mpu_core.c

452204ae Sachin Kamat        2013-07-30  829  		return result;
09a642b7 Ge Gao              2013-02-02  830  	}
09a642b7 Ge Gao              2013-02-02  831  	result = inv_mpu6050_probe_trigger(indio_dev);
09a642b7 Ge Gao              2013-02-02  832  	if (result) {
09a642b7 Ge Gao              2013-02-02  833  		dev_err(&st->client->dev, "trigger probe fail %d\n", result);
09a642b7 Ge Gao              2013-02-02  834  		goto out_unreg_ring;
09a642b7 Ge Gao              2013-02-02  835  	}
09a642b7 Ge Gao              2013-02-02  836  
09a642b7 Ge Gao              2013-02-02  837  	INIT_KFIFO(st->timestamps);
09a642b7 Ge Gao              2013-02-02  838  	spin_lock_init(&st->time_stamp_lock);
09a642b7 Ge Gao              2013-02-02  839  	result = iio_device_register(indio_dev);
09a642b7 Ge Gao              2013-02-02  840  	if (result) {
09a642b7 Ge Gao              2013-02-02  841  		dev_err(&st->client->dev, "IIO register fail %d\n", result);
09a642b7 Ge Gao              2013-02-02  842  		goto out_remove_trigger;
09a642b7 Ge Gao              2013-02-02  843  	}
09a642b7 Ge Gao              2013-02-02  844  
3a2ecc3d Srinivas Pandruvada 2014-12-05 @845  	st->mux_adapter = i2c_add_mux_adapter(client->adapter,
3a2ecc3d Srinivas Pandruvada 2014-12-05  846  					      &client->dev,
3a2ecc3d Srinivas Pandruvada 2014-12-05  847  					      indio_dev,
3a2ecc3d Srinivas Pandruvada 2014-12-05  848  					      0, 0, 0,
3a2ecc3d Srinivas Pandruvada 2014-12-05  849  					      inv_mpu6050_select_bypass,
3a2ecc3d Srinivas Pandruvada 2014-12-05  850  					      inv_mpu6050_deselect_bypass);
3a2ecc3d Srinivas Pandruvada 2014-12-05  851  	if (!st->mux_adapter) {
3a2ecc3d Srinivas Pandruvada 2014-12-05  852  		result = -ENODEV;
3a2ecc3d Srinivas Pandruvada 2014-12-05  853  		goto out_unreg_device;

:::::: The code at line 845 was first introduced by commit
:::::: 3a2ecc3d2dce6e051b6afc319bb380c829e4e4fd iio: imu: inv_mpu6050: Add i2c mux for by pass

:::::: TO: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
:::::: CC: Jonathan Cameron <jic23@kernel.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Peter Rosin Jan. 5, 2016, 9:05 a.m. UTC | #4
Hi Guenter,

On 2016-01-04 16:37, Guenter Roeck wrote:
> On 01/04/2016 07:10 AM, Peter Rosin wrote:
>> From: Peter Rosin <peda@axentia.se>
>>
>> The initial core mux structure starts off small with only the parent
>> adapter pointer, which all muxes have, and a priv pointer for mux
>> driver private data.
>>
>> Add i2c_mux_alloc function to unify the creation of a mux.
>>
>> Where appropriate, pass around the mux core structure instead of the
>> parent adapter or the driver private data.
>>
>> Remove the parent adapter pointer from the driver private data for all
>> mux drivers.
>>
>> Signed-off-by: Peter Rosin <peda@axentia.se>
>> ---
>>   drivers/i2c/i2c-mux.c                      | 35 ++++++++++++++++++++++++-----
>>   drivers/i2c/muxes/i2c-arb-gpio-challenge.c | 24 +++++++++++---------
>>   drivers/i2c/muxes/i2c-mux-gpio.c           | 20 +++++++++--------
>>   drivers/i2c/muxes/i2c-mux-pca9541.c        | 36 ++++++++++++++++--------------
>>   drivers/i2c/muxes/i2c-mux-pca954x.c        | 22 +++++++++++++-----
>>   drivers/i2c/muxes/i2c-mux-pinctrl.c        | 24 +++++++++++---------
>>   drivers/i2c/muxes/i2c-mux-reg.c            | 25 ++++++++++++---------
>>   include/linux/i2c-mux.h                    | 14 +++++++++++-
>>   8 files changed, 129 insertions(+), 71 deletions(-)
>>

*snip*

>> +struct i2c_mux_core *i2c_mux_alloc(struct device *dev, int sizeof_priv)
>> +{
>> +    struct i2c_mux_core *muxc;
>> +
>> +    muxc = devm_kzalloc(dev, sizeof(*muxc), GFP_KERNEL);
>> +    if (!muxc)
>> +        return NULL;
>> +    if (sizeof_priv) {
>> +        muxc->priv = devm_kzalloc(dev, sizeof_priv, GFP_KERNEL);
>> +        if (!muxc->priv)
>> +            goto fail;
>> +    }
> 
> Why not just allocate sizeof(*muxc) + sizeof_priv in a single operation
> and then assign muxc->priv to muxc + 1 if sizeof_priv > 0 ?

Why indeed, good suggestion.

*snip*

>> @@ -134,13 +134,14 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
>>           return -EINVAL;
>>       }
>>
>> -    arb = devm_kzalloc(dev, sizeof(*arb), GFP_KERNEL);
>> -    if (!arb) {
>> -        dev_err(dev, "Cannot allocate i2c_arbitrator_data\n");
>> +    muxc = i2c_mux_alloc(dev, sizeof(*arb));
>> +    if (!muxc) {
>> +        dev_err(dev, "Cannot allocate i2c_mux_core structure\n");
> 
> Unnecessary error message.
> 

Right, I'll remove that (and the others just like it).

I'll see if I can cook up a v2 that also converts the i2c muxes elsewhere in
drivers/ that I wasn't aware of.

Cheers,
Peter
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index 00fc5b1c7b66..99fd9106abc6 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -31,8 +31,8 @@ 
 struct i2c_mux_priv {
 	struct i2c_adapter adap;
 	struct i2c_algorithm algo;
+	struct i2c_mux_core *muxc;
 
-	struct i2c_adapter *parent;
 	struct device *mux_dev;
 	void *mux_priv;
 	u32 chan_id;
@@ -45,7 +45,8 @@  static int i2c_mux_master_xfer(struct i2c_adapter *adap,
 			       struct i2c_msg msgs[], int num)
 {
 	struct i2c_mux_priv *priv = adap->algo_data;
-	struct i2c_adapter *parent = priv->parent;
+	struct i2c_mux_core *muxc = priv->muxc;
+	struct i2c_adapter *parent = muxc->parent;
 	int ret;
 
 	/* Switch to the right mux port and perform the transfer. */
@@ -65,7 +66,8 @@  static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,
 			      int size, union i2c_smbus_data *data)
 {
 	struct i2c_mux_priv *priv = adap->algo_data;
-	struct i2c_adapter *parent = priv->parent;
+	struct i2c_mux_core *muxc = priv->muxc;
+	struct i2c_adapter *parent = muxc->parent;
 	int ret;
 
 	/* Select the right mux port and perform the transfer. */
@@ -84,7 +86,7 @@  static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,
 static u32 i2c_mux_functionality(struct i2c_adapter *adap)
 {
 	struct i2c_mux_priv *priv = adap->algo_data;
-	struct i2c_adapter *parent = priv->parent;
+	struct i2c_adapter *parent = priv->muxc->parent;
 
 	return parent->algo->functionality(parent);
 }
@@ -102,7 +104,27 @@  static unsigned int i2c_mux_parent_classes(struct i2c_adapter *parent)
 	return class;
 }
 
-struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
+struct i2c_mux_core *i2c_mux_alloc(struct device *dev, int sizeof_priv)
+{
+	struct i2c_mux_core *muxc;
+
+	muxc = devm_kzalloc(dev, sizeof(*muxc), GFP_KERNEL);
+	if (!muxc)
+		return NULL;
+	if (sizeof_priv) {
+		muxc->priv = devm_kzalloc(dev, sizeof_priv, GFP_KERNEL);
+		if (!muxc->priv)
+			goto fail;
+	}
+	return muxc;
+
+fail:
+	devm_kfree(dev, muxc);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(i2c_mux_alloc);
+
+struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
 				struct device *mux_dev,
 				void *mux_priv, u32 force_nr, u32 chan_id,
 				unsigned int class,
@@ -111,6 +133,7 @@  struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
 				int (*deselect) (struct i2c_adapter *,
 						 void *, u32))
 {
+	struct i2c_adapter *parent = muxc->parent;
 	struct i2c_mux_priv *priv;
 	char symlink_name[20];
 	int ret;
@@ -120,7 +143,7 @@  struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
 		return NULL;
 
 	/* Set up private adapter data */
-	priv->parent = parent;
+	priv->muxc = muxc;
 	priv->mux_dev = mux_dev;
 	priv->mux_priv = mux_priv;
 	priv->chan_id = chan_id;
diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
index 402e3a6c671a..dd616c0280ad 100644
--- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
+++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
@@ -42,7 +42,6 @@ 
  */
 
 struct i2c_arbitrator_data {
-	struct i2c_adapter *parent;
 	struct i2c_adapter *child;
 	int our_gpio;
 	int our_gpio_release;
@@ -119,6 +118,7 @@  static int i2c_arbitrator_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
 	struct device_node *parent_np;
+	struct i2c_mux_core *muxc;
 	struct i2c_arbitrator_data *arb;
 	enum of_gpio_flags gpio_flags;
 	unsigned long out_init;
@@ -134,13 +134,14 @@  static int i2c_arbitrator_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	arb = devm_kzalloc(dev, sizeof(*arb), GFP_KERNEL);
-	if (!arb) {
-		dev_err(dev, "Cannot allocate i2c_arbitrator_data\n");
+	muxc = i2c_mux_alloc(dev, sizeof(*arb));
+	if (!muxc) {
+		dev_err(dev, "Cannot allocate i2c_mux_core structure\n");
 		return -ENOMEM;
 	}
-	platform_set_drvdata(pdev, arb);
+	arb = i2c_mux_priv(muxc);
 
+	platform_set_drvdata(pdev, muxc);
 	/* Request GPIOs */
 	ret = of_get_named_gpio_flags(np, "our-claim-gpio", 0, &gpio_flags);
 	if (!gpio_is_valid(ret)) {
@@ -196,21 +197,21 @@  static int i2c_arbitrator_probe(struct platform_device *pdev)
 		dev_err(dev, "Cannot parse i2c-parent\n");
 		return -EINVAL;
 	}
-	arb->parent = of_get_i2c_adapter_by_node(parent_np);
+	muxc->parent = of_find_i2c_adapter_by_node(parent_np);
 	of_node_put(parent_np);
-	if (!arb->parent) {
+	if (!muxc->parent) {
 		dev_err(dev, "Cannot find parent bus\n");
 		return -EPROBE_DEFER;
 	}
 
 	/* Actually add the mux adapter */
-	arb->child = i2c_add_mux_adapter(arb->parent, dev, arb, 0, 0, 0,
+	arb->child = i2c_add_mux_adapter(muxc, dev, arb, 0, 0, 0,
 					 i2c_arbitrator_select,
 					 i2c_arbitrator_deselect);
 	if (!arb->child) {
 		dev_err(dev, "Failed to add adapter\n");
 		ret = -ENODEV;
-		i2c_put_adapter(arb->parent);
+		i2c_put_adapter(muxc->parent);
 	}
 
 	return ret;
@@ -218,10 +219,11 @@  static int i2c_arbitrator_probe(struct platform_device *pdev)
 
 static int i2c_arbitrator_remove(struct platform_device *pdev)
 {
-	struct i2c_arbitrator_data *arb = platform_get_drvdata(pdev);
+	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
+	struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc);
 
 	i2c_del_mux_adapter(arb->child);
-	i2c_put_adapter(arb->parent);
+	i2c_put_adapter(muxc->parent);
 
 	return 0;
 }
diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index b8e11c16d98c..3de6dc79c1db 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -18,7 +18,6 @@ 
 #include <linux/of_gpio.h>
 
 struct gpiomux {
-	struct i2c_adapter *parent;
 	struct i2c_adapter **adap; /* child busses */
 	struct i2c_mux_gpio_platform_data data;
 	unsigned gpio_base;
@@ -136,19 +135,21 @@  static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
 
 static int i2c_mux_gpio_probe(struct platform_device *pdev)
 {
+	struct i2c_mux_core *muxc;
 	struct gpiomux *mux;
 	struct i2c_adapter *parent;
 	int (*deselect) (struct i2c_adapter *, void *, u32);
 	unsigned initial_state, gpio_base;
 	int i, ret;
 
-	mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
-	if (!mux) {
-		dev_err(&pdev->dev, "Cannot allocate gpiomux structure");
+	muxc = i2c_mux_alloc(&pdev->dev, sizeof(*mux));
+	if (!muxc) {
+		dev_err(&pdev->dev, "Cannot allocate i2c_mux_core structure\n");
 		return -ENOMEM;
 	}
+	mux = i2c_mux_priv(muxc);
 
-	platform_set_drvdata(pdev, mux);
+	platform_set_drvdata(pdev, muxc);
 
 	if (!dev_get_platdata(&pdev->dev)) {
 		ret = i2c_mux_gpio_probe_dt(mux, pdev);
@@ -180,7 +181,7 @@  static int i2c_mux_gpio_probe(struct platform_device *pdev)
 	if (!parent)
 		return -EPROBE_DEFER;
 
-	mux->parent = parent;
+	muxc->parent = parent;
 	mux->gpio_base = gpio_base;
 
 	mux->adap = devm_kzalloc(&pdev->dev,
@@ -223,7 +224,7 @@  static int i2c_mux_gpio_probe(struct platform_device *pdev)
 		u32 nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0;
 		unsigned int class = mux->data.classes ? mux->data.classes[i] : 0;
 
-		mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr,
+		mux->adap[i] = i2c_add_mux_adapter(muxc, &pdev->dev, mux, nr,
 						   mux->data.values[i], class,
 						   i2c_mux_gpio_select, deselect);
 		if (!mux->adap[i]) {
@@ -253,7 +254,8 @@  alloc_failed:
 
 static int i2c_mux_gpio_remove(struct platform_device *pdev)
 {
-	struct gpiomux *mux = platform_get_drvdata(pdev);
+	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
+	struct gpiomux *mux = i2c_mux_priv(muxc);
 	int i;
 
 	for (i = 0; i < mux->data.n_values; i++)
@@ -262,7 +264,7 @@  static int i2c_mux_gpio_remove(struct platform_device *pdev)
 	for (i = 0; i < mux->data.n_gpios; i++)
 		gpio_free(mux->gpio_base + mux->data.gpios[i]);
 
-	i2c_put_adapter(mux->parent);
+	i2c_put_adapter(muxc->parent);
 
 	return 0;
 }
diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c
index d0ba424adebc..b2525a772d3b 100644
--- a/drivers/i2c/muxes/i2c-mux-pca9541.c
+++ b/drivers/i2c/muxes/i2c-mux-pca9541.c
@@ -73,6 +73,7 @@ 
 #define SELECT_DELAY_LONG	1000
 
 struct pca9541 {
+	struct i2c_client *client;
 	struct i2c_adapter *mux_adap;
 	unsigned long select_timeout;
 	unsigned long arb_timeout;
@@ -217,7 +218,8 @@  static const u8 pca9541_control[16] = {
  */
 static int pca9541_arbitrate(struct i2c_client *client)
 {
-	struct pca9541 *data = i2c_get_clientdata(client);
+	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+	struct pca9541 *data = i2c_mux_priv(muxc);
 	int reg;
 
 	reg = pca9541_reg_read(client, PCA9541_CONTROL);
@@ -324,20 +326,25 @@  static int pca9541_probe(struct i2c_client *client,
 {
 	struct i2c_adapter *adap = client->adapter;
 	struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev);
+	struct i2c_mux_core *muxc;
 	struct pca9541 *data;
 	int force;
-	int ret = -ENODEV;
 
 	if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA))
-		goto err;
+		return -ENODEV;
 
-	data = kzalloc(sizeof(struct pca9541), GFP_KERNEL);
-	if (!data) {
-		ret = -ENOMEM;
-		goto err;
+	muxc = i2c_mux_alloc(&client->dev, sizeof(*data));
+	if (!muxc) {
+		dev_err(&client->dev,
+			"Cannot allocate i2c_mux_core structure\n");
+		return -ENOMEM;
 	}
+	data = i2c_mux_priv(muxc);
+
+	i2c_set_clientdata(client, muxc);
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
+	muxc->parent = adap;
 
 	/*
 	 * I2C accesses are unprotected here.
@@ -352,34 +359,29 @@  static int pca9541_probe(struct i2c_client *client,
 	force = 0;
 	if (pdata)
 		force = pdata->modes[0].adap_id;
-	data->mux_adap = i2c_add_mux_adapter(adap, &client->dev, client,
+	data->mux_adap = i2c_add_mux_adapter(muxc, &client->dev, client,
 					     force, 0, 0,
 					     pca9541_select_chan,
 					     pca9541_release_chan);
 
 	if (data->mux_adap == NULL) {
 		dev_err(&client->dev, "failed to register master selector\n");
-		goto exit_free;
+		return -ENODEV;
 	}
 
 	dev_info(&client->dev, "registered master selector for I2C %s\n",
 		 client->name);
 
 	return 0;
-
-exit_free:
-	kfree(data);
-err:
-	return ret;
 }
 
 static int pca9541_remove(struct i2c_client *client)
 {
-	struct pca9541 *data = i2c_get_clientdata(client);
+	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+	struct pca9541 *data = i2c_mux_priv(muxc);
 
 	i2c_del_mux_adapter(data->mux_adap);
 
-	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index acfcef3d4068..00eda06a667e 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -63,6 +63,7 @@  struct pca954x {
 	struct i2c_adapter *virt_adaps[PCA954X_MAX_NCHANS];
 
 	u8 last_chan;		/* last register value */
+	struct i2c_client *client;
 };
 
 struct chip_desc {
@@ -191,17 +192,23 @@  static int pca954x_probe(struct i2c_client *client,
 	bool idle_disconnect_dt;
 	struct gpio_desc *gpio;
 	int num, force, class;
+	struct i2c_mux_core *muxc;
 	struct pca954x *data;
 	int ret;
 
 	if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
 		return -ENODEV;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct pca954x), GFP_KERNEL);
-	if (!data)
+	muxc = i2c_mux_alloc(&client->dev, sizeof(*data));
+	if (!muxc) {
+		dev_err(&client->dev,
+			"Cannot allocate i2c_mux_core structure\n");
 		return -ENOMEM;
+	}
+	data = i2c_mux_priv(muxc);
 
-	i2c_set_clientdata(client, data);
+	i2c_set_clientdata(client, muxc);
+	data->client = client;
 
 	/* Get the mux out of reset if a reset GPIO is specified. */
 	gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW);
@@ -217,6 +224,7 @@  static int pca954x_probe(struct i2c_client *client,
 		return -ENODEV;
 	}
 
+	muxc->parent = adap;
 	data->type = id->driver_data;
 	data->last_chan = 0;		   /* force the first selection */
 
@@ -241,7 +249,7 @@  static int pca954x_probe(struct i2c_client *client,
 		}
 
 		data->virt_adaps[num] =
-			i2c_add_mux_adapter(adap, &client->dev, client,
+			i2c_add_mux_adapter(muxc, &client->dev, client,
 				force, num, class, pca954x_select_chan,
 				(idle_disconnect_pd || idle_disconnect_dt)
 					? pca954x_deselect_mux : NULL);
@@ -270,7 +278,8 @@  virt_reg_failed:
 
 static int pca954x_remove(struct i2c_client *client)
 {
-	struct pca954x *data = i2c_get_clientdata(client);
+	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+	struct pca954x *data = i2c_mux_priv(muxc);
 	const struct chip_desc *chip = &chips[data->type];
 	int i;
 
@@ -287,7 +296,8 @@  static int pca954x_remove(struct i2c_client *client)
 static int pca954x_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
-	struct pca954x *data = i2c_get_clientdata(client);
+	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+	struct pca954x *data = i2c_mux_priv(muxc);
 
 	data->last_chan = 0;
 	return i2c_smbus_write_byte(client, 0);
diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c
index b5a982ba8898..cd3b73e208ce 100644
--- a/drivers/i2c/muxes/i2c-mux-pinctrl.c
+++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c
@@ -31,7 +31,6 @@  struct i2c_mux_pinctrl {
 	struct pinctrl *pinctrl;
 	struct pinctrl_state **states;
 	struct pinctrl_state *state_idle;
-	struct i2c_adapter *parent;
 	struct i2c_adapter **busses;
 };
 
@@ -131,17 +130,19 @@  static inline int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
 
 static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
 {
+	struct i2c_mux_core *muxc;
 	struct i2c_mux_pinctrl *mux;
 	int (*deselect)(struct i2c_adapter *, void *, u32);
 	int i, ret;
 
-	mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
-	if (!mux) {
-		dev_err(&pdev->dev, "Cannot allocate i2c_mux_pinctrl\n");
+	muxc = i2c_mux_alloc(&pdev->dev, sizeof(*mux));
+	if (!muxc) {
+		dev_err(&pdev->dev, "Cannot allocate i2c_mux_core structure\n");
 		ret = -ENOMEM;
 		goto err;
 	}
-	platform_set_drvdata(pdev, mux);
+	mux = i2c_mux_priv(muxc);
+	platform_set_drvdata(pdev, muxc);
 
 	mux->dev = &pdev->dev;
 
@@ -208,8 +209,8 @@  static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
 		deselect = NULL;
 	}
 
-	mux->parent = i2c_get_adapter(mux->pdata->parent_bus_num);
-	if (!mux->parent) {
+	muxc->parent = i2c_get_adapter(mux->pdata->parent_bus_num);
+	if (!muxc->parent) {
 		dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
 			mux->pdata->parent_bus_num);
 		ret = -EPROBE_DEFER;
@@ -220,7 +221,7 @@  static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
 		u32 bus = mux->pdata->base_bus_num ?
 				(mux->pdata->base_bus_num + i) : 0;
 
-		mux->busses[i] = i2c_add_mux_adapter(mux->parent, &pdev->dev,
+		mux->busses[i] = i2c_add_mux_adapter(muxc, &pdev->dev,
 						     mux, bus, i, 0,
 						     i2c_mux_pinctrl_select,
 						     deselect);
@@ -236,20 +237,21 @@  static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
 err_del_adapter:
 	for (; i > 0; i--)
 		i2c_del_mux_adapter(mux->busses[i - 1]);
-	i2c_put_adapter(mux->parent);
+	i2c_put_adapter(muxc->parent);
 err:
 	return ret;
 }
 
 static int i2c_mux_pinctrl_remove(struct platform_device *pdev)
 {
-	struct i2c_mux_pinctrl *mux = platform_get_drvdata(pdev);
+	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
+	struct i2c_mux_pinctrl *mux = i2c_mux_priv(muxc);
 	int i;
 
 	for (i = 0; i < mux->pdata->bus_count; i++)
 		i2c_del_mux_adapter(mux->busses[i]);
 
-	i2c_put_adapter(mux->parent);
+	i2c_put_adapter(muxc->parent);
 
 	return 0;
 }
diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c
index 5fbd5bd0878f..76244aca154e 100644
--- a/drivers/i2c/muxes/i2c-mux-reg.c
+++ b/drivers/i2c/muxes/i2c-mux-reg.c
@@ -21,7 +21,6 @@ 
 #include <linux/slab.h>
 
 struct regmux {
-	struct i2c_adapter *parent;
 	struct i2c_adapter **adap; /* child busses */
 	struct i2c_mux_reg_platform_data data;
 };
@@ -87,6 +86,7 @@  static int i2c_mux_reg_deselect(struct i2c_adapter *adap, void *data,
 static int i2c_mux_reg_probe_dt(struct regmux *mux,
 					struct platform_device *pdev)
 {
+	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
 	struct device_node *np = pdev->dev.of_node;
 	struct device_node *adapter_np, *child;
 	struct i2c_adapter *adapter;
@@ -107,7 +107,7 @@  static int i2c_mux_reg_probe_dt(struct regmux *mux,
 	if (!adapter)
 		return -EPROBE_DEFER;
 
-	mux->parent = adapter;
+	muxc->parent = adapter;
 	mux->data.parent = i2c_adapter_id(adapter);
 	put_device(&adapter->dev);
 
@@ -169,6 +169,7 @@  static int i2c_mux_reg_probe_dt(struct regmux *mux,
 
 static int i2c_mux_reg_probe(struct platform_device *pdev)
 {
+	struct i2c_mux_core *muxc;
 	struct regmux *mux;
 	struct i2c_adapter *parent;
 	struct resource *res;
@@ -176,11 +177,14 @@  static int i2c_mux_reg_probe(struct platform_device *pdev)
 	unsigned int class;
 	int i, ret, nr;
 
-	mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
-	if (!mux)
+	muxc = i2c_mux_alloc(&pdev->dev, sizeof(*mux));
+	if (!muxc) {
+		dev_err(&pdev->dev, "Cannot allocate i2c_mux_core structure\n");
 		return -ENOMEM;
+	}
+	mux = i2c_mux_priv(muxc);
 
-	platform_set_drvdata(pdev, mux);
+	platform_set_drvdata(pdev, muxc);
 
 	if (dev_get_platdata(&pdev->dev)) {
 		memcpy(&mux->data, dev_get_platdata(&pdev->dev),
@@ -190,7 +194,7 @@  static int i2c_mux_reg_probe(struct platform_device *pdev)
 		if (!parent)
 			return -EPROBE_DEFER;
 
-		mux->parent = parent;
+		muxc->parent = parent;
 	} else {
 		ret = i2c_mux_reg_probe_dt(mux, pdev);
 		if (ret < 0) {
@@ -232,7 +236,7 @@  static int i2c_mux_reg_probe(struct platform_device *pdev)
 		nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0;
 		class = mux->data.classes ? mux->data.classes[i] : 0;
 
-		mux->adap[i] = i2c_add_mux_adapter(mux->parent, &pdev->dev, mux,
+		mux->adap[i] = i2c_add_mux_adapter(muxc, &pdev->dev, mux,
 						   nr, mux->data.values[i],
 						   class, i2c_mux_reg_select,
 						   deselect);
@@ -244,7 +248,7 @@  static int i2c_mux_reg_probe(struct platform_device *pdev)
 	}
 
 	dev_dbg(&pdev->dev, "%d port mux on %s adapter\n",
-		 mux->data.n_values, mux->parent->name);
+		 mux->data.n_values, muxc->parent->name);
 
 	return 0;
 
@@ -257,13 +261,14 @@  add_adapter_failed:
 
 static int i2c_mux_reg_remove(struct platform_device *pdev)
 {
-	struct regmux *mux = platform_get_drvdata(pdev);
+	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
+	struct regmux *mux = i2c_mux_priv(muxc);
 	int i;
 
 	for (i = 0; i < mux->data.n_values; i++)
 		i2c_del_mux_adapter(mux->adap[i]);
 
-	i2c_put_adapter(mux->parent);
+	i2c_put_adapter(muxc->parent);
 
 	return 0;
 }
diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h
index b5f9a007a3ab..3ca1783b86ac 100644
--- a/include/linux/i2c-mux.h
+++ b/include/linux/i2c-mux.h
@@ -27,13 +27,25 @@ 
 
 #ifdef __KERNEL__
 
+struct i2c_mux_core {
+	struct i2c_adapter *parent;
+	void *priv;
+};
+
+struct i2c_mux_core *i2c_mux_alloc(struct device *dev, int sizeof_priv);
+
+static inline void *i2c_mux_priv(struct i2c_mux_core *muxc)
+{
+	return muxc->priv;
+}
+
 /*
  * Called to create a i2c bus on a multiplexed bus segment.
  * The mux_dev and chan_id parameters are passed to the select
  * and deselect callback functions to perform hardware-specific
  * mux control.
  */
-struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
+struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
 				struct device *mux_dev,
 				void *mux_priv, u32 force_nr, u32 chan_id,
 				unsigned int class,