linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/10] i2c mux cleanup and locking update
@ 2016-01-04 15:10 Peter Rosin
  2016-01-04 15:10 ` [PATCH 01/10] i2c-mux: add common core data for every mux instance Peter Rosin
                   ` (9 more replies)
  0 siblings, 10 replies; 22+ messages in thread
From: Peter Rosin @ 2016-01-04 15:10 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Peter Rosin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Peter Korsgaard, Guenter Roeck, linux-i2c,
	devicetree, linux-kernel, Peter Rosin

From: Peter Rosin <peda@axentia.se>

Hi!

I have a pair of boards with this i2c topology:

                       GPIO ---|  ------ BAT1
                        |      v /
   I2C  -----+------B---+---- MUX
             |                   \
           EEPROM                 ------ BAT2

	(B denotes the boundary between the boards)

The problem with this is that the GPIO controller sits on the same i2c bus
that it MUXes. For pca954x devices this is worked around by using unlocked
transfers when updating the MUX. I have no such luck as the GPIO is a general
purpose IO expander and the MUX is just a random bidirectional MUX, unaware
of the fact that it is muxing an i2c bus, and extending unlocked transfers
into the GPIO subsystem is too ugly to even think about. But the general hw
approach is sane in my opinion, with the number of connections between the
two boards minimized. To put is plainly, I need support for it.

So, I observe that while it is needed to have the i2c bus locked during the
actual MUX update in order to avoid random garbage on the slave side, it
is not strictly a must to have it locked over the whole sequence of a full
select-transfer-deselect operation. The MUX itself needs to be locked, so
transfers to clients behind the mux are serialized, and the MUX needs to be
stable during all i2c traffic (otherwise individual mux slave segments
might see garbage).

This series accomplishes this by adding a dt property to i2c-mux-gpio and
i2c-mux-pinctrl that can be used to state that the mux is updated by means
of the muxed master bus, and that the select-transfer-deselect operations
should be locked individually. When this holds, the i2c bus *is* locked
during muxing, since the muxing happens as part of i2c transfers. This
is true even if the MUX is updated with several transfers to the GPIO (at
least as long as *all* MUX changes are using the i2s master bus). A lock
is added to the mux so that transfers through the mux are serialized.

Concerns:
- The locking is perhaps too complex?
- I worry about the priority inheritance aspect of the adapter lock. When
  the transfers behind the mux are divided into select-transfer-deselect all
  locked individually, low priority transfers get more chances to interfere
  with high priority transfers.
- When doing an i2c_transfer() in_atomic() context of with irqs_disabled(),
  there is a higher possibility that the mux is not returned to its idle
  state after a failed (-EAGAIN) transfer due to trylock.

To summarize the series, there's some i2c-mux infrastructure cleanup work
first (I think that part stands by itself as desireable regardless), the
locking changes are in the second half of the series, with the real meat
in 8/10. The tail of the series cleans up the open-coded unlocked i2c-
transfers in the pca9541 and pca954x drivers.

Further work: Looking at i2c_adapter_lock users in drivers/, it seems that
at least some of them are there just so that the driver can work behind an
i2c controlled mux (e.g. media/dvb-frontends/rtl2830.c). Those kind of
kludges can be removed. Other users lump several transfers together to
prevent mishaps, and at least some of those could probably be converted to
lock the i2c segment instead of the master bus adapter, so that the driver
doesn't deadlock even if the device sits behind an i2c controlled mux.

PS. needs a bunch of testing, I do not have access to all the involved hw

Cheers,
Peter

Peter Rosin (10):
  i2c-mux: add common core data for every mux instance
  i2c-mux: move select and deselect ops to i2c_mux_core
  i2c-mux: move the slave side adapter management to i2c_mux_core
  i2c-mux: remove the mux dev pointer from the mux per channel data
  i2c-mux: pinctrl: get rid of the driver private struct device pointer
  i2c: allow adapter drivers to override the adapter locking
  i2c: muxes always lock the parent adapter
  i2c-mux: relax locking of the top i2c adapter during i2c controlled
    muxing
  i2c: pca9541: get rid of the i2c deadlock workaround
  i2c: pca954x: get rid of the i2c deadlock workaround

 .../devicetree/bindings/i2c/i2c-mux-gpio.txt       |   2 +
 .../devicetree/bindings/i2c/i2c-mux-pinctrl.txt    |   4 +
 drivers/i2c/i2c-core.c                             |  59 ++---
 drivers/i2c/i2c-mux.c                              | 279 +++++++++++++++++----
 drivers/i2c/muxes/i2c-arb-gpio-challenge.c         |  46 ++--
 drivers/i2c/muxes/i2c-mux-gpio.c                   |  58 ++---
 drivers/i2c/muxes/i2c-mux-pca9541.c                | 141 ++++-------
 drivers/i2c/muxes/i2c-mux-pca954x.c                | 104 ++++----
 drivers/i2c/muxes/i2c-mux-pinctrl.c                |  85 +++----
 drivers/i2c/muxes/i2c-mux-reg.c                    |  63 ++---
 include/linux/i2c-mux-gpio.h                       |   2 +
 include/linux/i2c-mux-pinctrl.h                    |   2 +
 include/linux/i2c-mux.h                            |  39 ++-
 include/linux/i2c.h                                |  28 ++-
 14 files changed, 524 insertions(+), 388 deletions(-)

-- 
2.1.4


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 01/10] i2c-mux: add common core data for every mux instance
  2016-01-04 15:10 [PATCH 00/10] i2c mux cleanup and locking update Peter Rosin
@ 2016-01-04 15:10 ` Peter Rosin
  2016-01-04 15:37   ` Guenter Roeck
                     ` (2 more replies)
  2016-01-04 15:10 ` [PATCH 02/10] i2c-mux: move select and deselect ops to i2c_mux_core Peter Rosin
                   ` (8 subsequent siblings)
  9 siblings, 3 replies; 22+ messages in thread
From: Peter Rosin @ 2016-01-04 15:10 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Peter Rosin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Peter Korsgaard, Guenter Roeck, linux-i2c,
	devicetree, linux-kernel, Peter Rosin

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;
+	}
+	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,
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 02/10] i2c-mux: move select and deselect ops to i2c_mux_core
  2016-01-04 15:10 [PATCH 00/10] i2c mux cleanup and locking update Peter Rosin
  2016-01-04 15:10 ` [PATCH 01/10] i2c-mux: add common core data for every mux instance Peter Rosin
@ 2016-01-04 15:10 ` Peter Rosin
  2016-01-04 15:54   ` kbuild test robot
                     ` (3 more replies)
  2016-01-04 15:10 ` [PATCH 03/10] i2c-mux: move the slave side adapter management " Peter Rosin
                   ` (7 subsequent siblings)
  9 siblings, 4 replies; 22+ messages in thread
From: Peter Rosin @ 2016-01-04 15:10 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Peter Rosin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Peter Korsgaard, Guenter Roeck, linux-i2c,
	devicetree, linux-kernel, Peter Rosin

From: Peter Rosin <peda@axentia.se>

The mux select and deselect ops are common to the mux most of the time,
so store the ops in the mux core.

Change the select and deselect op to work in terms of the mux core instead
of the child adapter. No driver uses the child adapter anyway, and if it
is needed in a future mux driver it can be worked out from the channel id.

i2c-arb-gpio-challenge is special in that it needs the mux device pointer
in the select op, so store that device pointer in the mux core as well.
This pointer is going to get further use in later commits.

i2c-mux-pca954x is special since it does not add its deselect op to all
its child adapters, handle this by adding a mask that makes the deselect
op a no-operation for child adapters not wishing to deselect the mux.

Signed-off-by: Peter Rosin <peda@axentia.se>
---
 drivers/i2c/i2c-mux.c                      | 31 ++++++++++--------------------
 drivers/i2c/muxes/i2c-arb-gpio-challenge.c | 18 ++++++++---------
 drivers/i2c/muxes/i2c-mux-gpio.c           | 19 +++++++++---------
 drivers/i2c/muxes/i2c-mux-pca9541.c        | 18 +++++++++--------
 drivers/i2c/muxes/i2c-mux-pca954x.c        | 30 +++++++++++++++++------------
 drivers/i2c/muxes/i2c-mux-pinctrl.c        | 20 ++++++++-----------
 drivers/i2c/muxes/i2c-mux-reg.c            | 21 +++++++++-----------
 include/linux/i2c-mux.h                    | 15 ++++++++-------
 8 files changed, 81 insertions(+), 91 deletions(-)

diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index 99fd9106abc6..00ffbdba2cf8 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -32,13 +32,8 @@ struct i2c_mux_priv {
 	struct i2c_adapter adap;
 	struct i2c_algorithm algo;
 	struct i2c_mux_core *muxc;
-
 	struct device *mux_dev;
-	void *mux_priv;
 	u32 chan_id;
-
-	int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
-	int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
 };
 
 static int i2c_mux_master_xfer(struct i2c_adapter *adap,
@@ -51,11 +46,11 @@ static int i2c_mux_master_xfer(struct i2c_adapter *adap,
 
 	/* Switch to the right mux port and perform the transfer. */
 
-	ret = priv->select(parent, priv->mux_priv, priv->chan_id);
+	ret = muxc->select(muxc, priv->chan_id);
 	if (ret >= 0)
 		ret = __i2c_transfer(parent, msgs, num);
-	if (priv->deselect)
-		priv->deselect(parent, priv->mux_priv, priv->chan_id);
+	if (muxc->deselect)
+		muxc->deselect(muxc, priv->chan_id);
 
 	return ret;
 }
@@ -72,12 +67,12 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,
 
 	/* Select the right mux port and perform the transfer. */
 
-	ret = priv->select(parent, priv->mux_priv, priv->chan_id);
+	ret = muxc->select(muxc, priv->chan_id);
 	if (ret >= 0)
 		ret = parent->algo->smbus_xfer(parent, addr, flags,
 					read_write, command, size, data);
-	if (priv->deselect)
-		priv->deselect(parent, priv->mux_priv, priv->chan_id);
+	if (muxc->deselect)
+		muxc->deselect(muxc, priv->chan_id);
 
 	return ret;
 }
@@ -116,6 +111,7 @@ struct i2c_mux_core *i2c_mux_alloc(struct device *dev, int sizeof_priv)
 		if (!muxc->priv)
 			goto fail;
 	}
+	muxc->dev = dev;
 	return muxc;
 
 fail:
@@ -125,13 +121,9 @@ fail:
 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,
-				int (*select) (struct i2c_adapter *,
-					       void *, u32),
-				int (*deselect) (struct i2c_adapter *,
-						 void *, u32))
+					struct device *mux_dev,
+					u32 force_nr, u32 chan_id,
+					unsigned int class)
 {
 	struct i2c_adapter *parent = muxc->parent;
 	struct i2c_mux_priv *priv;
@@ -145,10 +137,7 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
 	/* Set up private adapter data */
 	priv->muxc = muxc;
 	priv->mux_dev = mux_dev;
-	priv->mux_priv = mux_priv;
 	priv->chan_id = chan_id;
-	priv->select = select;
-	priv->deselect = deselect;
 
 	/* Need to do algo dynamically because we don't know ahead
 	 * of time what sort of physical adapter we'll be dealing with.
diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
index dd616c0280ad..1c4741cf290f 100644
--- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
+++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
@@ -58,9 +58,9 @@ struct i2c_arbitrator_data {
  *
  * Use the GPIO-based signalling protocol; return -EBUSY if we fail.
  */
-static int i2c_arbitrator_select(struct i2c_adapter *adap, void *data, u32 chan)
+static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan)
 {
-	const struct i2c_arbitrator_data *arb = data;
+	const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc);
 	unsigned long stop_retry, stop_time;
 
 	/* Start a round of trying to claim the bus */
@@ -92,7 +92,7 @@ static int i2c_arbitrator_select(struct i2c_adapter *adap, void *data, u32 chan)
 	/* Give up, release our claim */
 	gpio_set_value(arb->our_gpio, arb->our_gpio_release);
 	udelay(arb->slew_delay_us);
-	dev_err(&adap->dev, "Could not claim bus, timeout\n");
+	dev_err(muxc->dev, "Could not claim bus, timeout\n");
 	return -EBUSY;
 }
 
@@ -101,10 +101,9 @@ static int i2c_arbitrator_select(struct i2c_adapter *adap, void *data, u32 chan)
  *
  * Release the I2C bus using the GPIO-based signalling protocol.
  */
-static int i2c_arbitrator_deselect(struct i2c_adapter *adap, void *data,
-				   u32 chan)
+static int i2c_arbitrator_deselect(struct i2c_mux_core *muxc, u32 chan)
 {
-	const struct i2c_arbitrator_data *arb = data;
+	const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc);
 
 	/* Release the bus and wait for the other master to notice */
 	gpio_set_value(arb->our_gpio, arb->our_gpio_release);
@@ -142,6 +141,9 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
 	arb = i2c_mux_priv(muxc);
 
 	platform_set_drvdata(pdev, muxc);
+
+	muxc->select = i2c_arbitrator_select,
+	muxc->deselect = i2c_arbitrator_deselect;
 	/* Request GPIOs */
 	ret = of_get_named_gpio_flags(np, "our-claim-gpio", 0, &gpio_flags);
 	if (!gpio_is_valid(ret)) {
@@ -205,9 +207,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
 	}
 
 	/* Actually add the mux adapter */
-	arb->child = i2c_add_mux_adapter(muxc, dev, arb, 0, 0, 0,
-					 i2c_arbitrator_select,
-					 i2c_arbitrator_deselect);
+	arb->child = i2c_add_mux_adapter(muxc, dev, 0, 0, 0);
 	if (!arb->child) {
 		dev_err(dev, "Failed to add adapter\n");
 		ret = -ENODEV;
diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index 3de6dc79c1db..bd000406e160 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -32,18 +32,18 @@ static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val)
 					val & (1 << i));
 }
 
-static int i2c_mux_gpio_select(struct i2c_adapter *adap, void *data, u32 chan)
+static int i2c_mux_gpio_select(struct i2c_mux_core *muxc, u32 chan)
 {
-	struct gpiomux *mux = data;
+	struct gpiomux *mux = i2c_mux_priv(muxc);
 
 	i2c_mux_gpio_set(mux, chan);
 
 	return 0;
 }
 
-static int i2c_mux_gpio_deselect(struct i2c_adapter *adap, void *data, u32 chan)
+static int i2c_mux_gpio_deselect(struct i2c_mux_core *muxc, u32 chan)
 {
-	struct gpiomux *mux = data;
+	struct gpiomux *mux = i2c_mux_priv(muxc);
 
 	i2c_mux_gpio_set(mux, mux->data.idle);
 
@@ -138,7 +138,6 @@ 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;
 
@@ -182,6 +181,7 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
 		return -EPROBE_DEFER;
 
 	muxc->parent = parent;
+	muxc->select = i2c_mux_gpio_select;
 	mux->gpio_base = gpio_base;
 
 	mux->adap = devm_kzalloc(&pdev->dev,
@@ -195,10 +195,10 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
 
 	if (mux->data.idle != I2C_MUX_GPIO_NO_IDLE) {
 		initial_state = mux->data.idle;
-		deselect = i2c_mux_gpio_deselect;
+		muxc->deselect = i2c_mux_gpio_deselect;
 	} else {
 		initial_state = mux->data.values[0];
-		deselect = NULL;
+		muxc->deselect = NULL;
 	}
 
 	for (i = 0; i < mux->data.n_gpios; i++) {
@@ -224,9 +224,8 @@ 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(muxc, &pdev->dev, mux, nr,
-						   mux->data.values[i], class,
-						   i2c_mux_gpio_select, deselect);
+		mux->adap[i] = i2c_add_mux_adapter(muxc, &pdev->dev, nr,
+						   mux->data.values[i], class);
 		if (!mux->adap[i]) {
 			ret = -ENODEV;
 			dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c
index b2525a772d3b..178c22981636 100644
--- a/drivers/i2c/muxes/i2c-mux-pca9541.c
+++ b/drivers/i2c/muxes/i2c-mux-pca9541.c
@@ -287,9 +287,10 @@ static int pca9541_arbitrate(struct i2c_client *client)
 	return 0;
 }
 
-static int pca9541_select_chan(struct i2c_adapter *adap, void *client, u32 chan)
+static int pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan)
 {
-	struct pca9541 *data = i2c_get_clientdata(client);
+	struct pca9541 *data = i2c_mux_priv(muxc);
+	struct i2c_client *client = data->client;
 	int ret;
 	unsigned long timeout = jiffies + ARB2_TIMEOUT;
 		/* give up after this time */
@@ -311,9 +312,11 @@ static int pca9541_select_chan(struct i2c_adapter *adap, void *client, u32 chan)
 	return -ETIMEDOUT;
 }
 
-static int pca9541_release_chan(struct i2c_adapter *adap,
-				void *client, u32 chan)
+static int pca9541_release_chan(struct i2c_mux_core *muxc, u32 chan)
 {
+	struct pca9541 *data = i2c_mux_priv(muxc);
+	struct i2c_client *client = data->client;
+
 	pca9541_release_bus(client);
 	return 0;
 }
@@ -345,6 +348,8 @@ static int pca9541_probe(struct i2c_client *client,
 
 	data->client = client;
 	muxc->parent = adap;
+	muxc->select = pca9541_select_chan;
+	muxc->deselect = pca9541_release_chan;
 
 	/*
 	 * I2C accesses are unprotected here.
@@ -359,10 +364,7 @@ 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(muxc, &client->dev, client,
-					     force, 0, 0,
-					     pca9541_select_chan,
-					     pca9541_release_chan);
+	data->mux_adap = i2c_add_mux_adapter(muxc, &client->dev, force, 0, 0);
 
 	if (data->mux_adap == NULL) {
 		dev_err(&client->dev, "failed to register master selector\n");
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index 00eda06a667e..edc6693ffea9 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 */
+	u8 deselect;
 	struct i2c_client *client;
 };
 
@@ -147,10 +148,10 @@ static int pca954x_reg_write(struct i2c_adapter *adap,
 	return ret;
 }
 
-static int pca954x_select_chan(struct i2c_adapter *adap,
-			       void *client, u32 chan)
+static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
 {
-	struct pca954x *data = i2c_get_clientdata(client);
+	struct pca954x *data = i2c_mux_priv(muxc);
+	struct i2c_client *client = data->client;
 	const struct chip_desc *chip = &chips[data->type];
 	u8 regval;
 	int ret = 0;
@@ -163,21 +164,24 @@ static int pca954x_select_chan(struct i2c_adapter *adap,
 
 	/* Only select the channel if its different from the last channel */
 	if (data->last_chan != regval) {
-		ret = pca954x_reg_write(adap, client, regval);
+		ret = pca954x_reg_write(muxc->parent, client, regval);
 		data->last_chan = regval;
 	}
 
 	return ret;
 }
 
-static int pca954x_deselect_mux(struct i2c_adapter *adap,
-				void *client, u32 chan)
+static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan)
 {
-	struct pca954x *data = i2c_get_clientdata(client);
+	struct pca954x *data = i2c_mux_priv(muxc);
+	struct i2c_client *client = data->client;
+
+	if (!(data->deselect & (1 << chan)))
+		return 0;
 
 	/* Deselect active channel */
 	data->last_chan = 0;
-	return pca954x_reg_write(adap, client, data->last_chan);
+	return pca954x_reg_write(muxc->parent, client, data->last_chan);
 }
 
 /*
@@ -225,6 +229,8 @@ static int pca954x_probe(struct i2c_client *client,
 	}
 
 	muxc->parent = adap;
+	muxc->select = pca954x_select_chan;
+	muxc->deselect = pca954x_deselect_mux;
 	data->type = id->driver_data;
 	data->last_chan = 0;		   /* force the first selection */
 
@@ -246,13 +252,13 @@ static int pca954x_probe(struct i2c_client *client,
 				/* discard unconfigured channels */
 				break;
 			idle_disconnect_pd = pdata->modes[num].deselect_on_exit;
+			data->deselect |= (idle_disconnect_pd
+					   || idle_disconnect_dt) << num;
 		}
 
 		data->virt_adaps[num] =
-			i2c_add_mux_adapter(muxc, &client->dev, client,
-				force, num, class, pca954x_select_chan,
-				(idle_disconnect_pd || idle_disconnect_dt)
-					? pca954x_deselect_mux : NULL);
+			i2c_add_mux_adapter(muxc, &client->dev,
+					    force, num, class);
 
 		if (data->virt_adaps[num] == NULL) {
 			ret = -ENODEV;
diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c
index cd3b73e208ce..79bd1ea75444 100644
--- a/drivers/i2c/muxes/i2c-mux-pinctrl.c
+++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c
@@ -34,18 +34,16 @@ struct i2c_mux_pinctrl {
 	struct i2c_adapter **busses;
 };
 
-static int i2c_mux_pinctrl_select(struct i2c_adapter *adap, void *data,
-				  u32 chan)
+static int i2c_mux_pinctrl_select(struct i2c_mux_core *muxc, u32 chan)
 {
-	struct i2c_mux_pinctrl *mux = data;
+	struct i2c_mux_pinctrl *mux = i2c_mux_priv(muxc);
 
 	return pinctrl_select_state(mux->pinctrl, mux->states[chan]);
 }
 
-static int i2c_mux_pinctrl_deselect(struct i2c_adapter *adap, void *data,
-				    u32 chan)
+static int i2c_mux_pinctrl_deselect(struct i2c_mux_core *muxc, u32 chan)
 {
-	struct i2c_mux_pinctrl *mux = data;
+	struct i2c_mux_pinctrl *mux = i2c_mux_priv(muxc);
 
 	return pinctrl_select_state(mux->pinctrl, mux->state_idle);
 }
@@ -132,7 +130,6 @@ 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;
 
 	muxc = i2c_mux_alloc(&pdev->dev, sizeof(*mux));
@@ -204,10 +201,11 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
 			goto err;
 		}
 
-		deselect = i2c_mux_pinctrl_deselect;
+		muxc->deselect = i2c_mux_pinctrl_deselect;
 	} else {
-		deselect = NULL;
+		muxc->deselect = NULL;
 	}
+	muxc->select = i2c_mux_pinctrl_select;
 
 	muxc->parent = i2c_get_adapter(mux->pdata->parent_bus_num);
 	if (!muxc->parent) {
@@ -222,9 +220,7 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
 				(mux->pdata->base_bus_num + i) : 0;
 
 		mux->busses[i] = i2c_add_mux_adapter(muxc, &pdev->dev,
-						     mux, bus, i, 0,
-						     i2c_mux_pinctrl_select,
-						     deselect);
+						     bus, i, 0);
 		if (!mux->busses[i]) {
 			ret = -ENODEV;
 			dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c
index 76244aca154e..d85879c46d90 100644
--- a/drivers/i2c/muxes/i2c-mux-reg.c
+++ b/drivers/i2c/muxes/i2c-mux-reg.c
@@ -63,18 +63,16 @@ static int i2c_mux_reg_set(const struct regmux *mux, unsigned int chan_id)
 	return 0;
 }
 
-static int i2c_mux_reg_select(struct i2c_adapter *adap, void *data,
-			      unsigned int chan)
+static int i2c_mux_reg_select(struct i2c_mux_core *muxc, u32 chan)
 {
-	struct regmux *mux = data;
+	struct regmux *mux = i2c_mux_priv(muxc);
 
 	return i2c_mux_reg_set(mux, chan);
 }
 
-static int i2c_mux_reg_deselect(struct i2c_adapter *adap, void *data,
-				unsigned int chan)
+static int i2c_mux_reg_deselect(struct i2c_mux_core *muxc, u32 chan)
 {
-	struct regmux *mux = data;
+	struct regmux *mux = i2c_mux_priv(muxc);
 
 	if (mux->data.idle_in_use)
 		return i2c_mux_reg_set(mux, mux->data.idle);
@@ -173,7 +171,6 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
 	struct regmux *mux;
 	struct i2c_adapter *parent;
 	struct resource *res;
-	int (*deselect)(struct i2c_adapter *, void *, u32);
 	unsigned int class;
 	int i, ret, nr;
 
@@ -227,19 +224,19 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
+	muxc->select = i2c_mux_reg_select;
 	if (mux->data.idle_in_use)
-		deselect = i2c_mux_reg_deselect;
+		muxc->deselect = i2c_mux_reg_deselect;
 	else
-		deselect = NULL;
+		muxc->deselect = NULL;
 
 	for (i = 0; i < mux->data.n_values; i++) {
 		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(muxc, &pdev->dev, mux,
+		mux->adap[i] = i2c_add_mux_adapter(muxc, &pdev->dev,
 						   nr, mux->data.values[i],
-						   class, i2c_mux_reg_select,
-						   deselect);
+						   class);
 		if (!mux->adap[i]) {
 			ret = -ENODEV;
 			dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h
index 3ca1783b86ac..5cd6e1e664e0 100644
--- a/include/linux/i2c-mux.h
+++ b/include/linux/i2c-mux.h
@@ -29,7 +29,12 @@
 
 struct i2c_mux_core {
 	struct i2c_adapter *parent;
+	struct device *dev;
+
 	void *priv;
+
+	int (*select)(struct i2c_mux_core *, u32 chan_id);
+	int (*deselect)(struct i2c_mux_core *, u32 chan_id);
 };
 
 struct i2c_mux_core *i2c_mux_alloc(struct device *dev, int sizeof_priv);
@@ -46,13 +51,9 @@ static inline void *i2c_mux_priv(struct i2c_mux_core *muxc)
  * mux control.
  */
 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,
-				int (*select) (struct i2c_adapter *,
-					       void *mux_dev, u32 chan_id),
-				int (*deselect) (struct i2c_adapter *,
-						 void *mux_dev, u32 chan_id));
+					struct device *mux_dev,
+					u32 force_nr, u32 chan_id,
+					unsigned int class);
 
 void i2c_del_mux_adapter(struct i2c_adapter *adap);
 
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 03/10] i2c-mux: move the slave side adapter management to i2c_mux_core
  2016-01-04 15:10 [PATCH 00/10] i2c mux cleanup and locking update Peter Rosin
  2016-01-04 15:10 ` [PATCH 01/10] i2c-mux: add common core data for every mux instance Peter Rosin
  2016-01-04 15:10 ` [PATCH 02/10] i2c-mux: move select and deselect ops to i2c_mux_core Peter Rosin
@ 2016-01-04 15:10 ` Peter Rosin
  2016-01-04 16:02   ` kbuild test robot
  2016-01-04 15:10 ` [PATCH 04/10] i2c-mux: remove the mux dev pointer from the mux per channel data Peter Rosin
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 22+ messages in thread
From: Peter Rosin @ 2016-01-04 15:10 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Peter Rosin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Peter Korsgaard, Guenter Roeck, linux-i2c,
	devicetree, linux-kernel, Peter Rosin

From: Peter Rosin <peda@axentia.se>

All muxes have slave side adapters, many have some arbitrary number of
them. Handle this in the mux core, so that drivers are simplified.

Add i2c_mux_reserve_adapter that can be used when it is known in advance
how many child adapters that is to be added. This avoids reallocating
memory.

Drop i2c_del_mux_adapter and replace it with i2c_del_mux_adapters, since
no mux driver is dynamically deleting individual child adapters anyway.

Signed-off-by: Peter Rosin <peda@axentia.se>
---
 drivers/i2c/i2c-mux.c                      | 71 +++++++++++++++++++++++-------
 drivers/i2c/muxes/i2c-arb-gpio-challenge.c | 10 ++---
 drivers/i2c/muxes/i2c-mux-gpio.c           | 23 ++++------
 drivers/i2c/muxes/i2c-mux-pca9541.c        | 13 +++---
 drivers/i2c/muxes/i2c-mux-pca954x.c        | 29 +++++-------
 drivers/i2c/muxes/i2c-mux-pinctrl.c        | 27 ++++--------
 drivers/i2c/muxes/i2c-mux-reg.c            | 26 ++++-------
 include/linux/i2c-mux.h                    | 15 ++++---
 8 files changed, 110 insertions(+), 104 deletions(-)

diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index 00ffbdba2cf8..84169a1c9c1b 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -99,6 +99,29 @@ static unsigned int i2c_mux_parent_classes(struct i2c_adapter *parent)
 	return class;
 }
 
+int i2c_mux_reserve_adapters(struct i2c_mux_core *muxc, int adapters)
+{
+	struct i2c_adapter **adapter;
+
+	if (adapters <= muxc->max_adapters)
+		return 0;
+
+	adapter = devm_kmalloc_array(muxc->dev,
+				     adapters, sizeof(*adapter),
+				     GFP_KERNEL);
+	if (!adapter)
+		return -ENOMEM;
+
+	memcpy(adapter, muxc->adapter,
+	       muxc->max_adapters * sizeof(*adapter));
+
+	devm_kfree(muxc->dev, muxc->adapter);
+	muxc->adapter = adapter;
+	muxc->max_adapters = adapters;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(i2c_mux_reserve_adapters);
+
 struct i2c_mux_core *i2c_mux_alloc(struct device *dev, int sizeof_priv)
 {
 	struct i2c_mux_core *muxc;
@@ -120,19 +143,29 @@ fail:
 }
 EXPORT_SYMBOL_GPL(i2c_mux_alloc);
 
-struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
-					struct device *mux_dev,
-					u32 force_nr, u32 chan_id,
-					unsigned int class)
+int i2c_add_mux_adapter(struct i2c_mux_core *muxc,
+			struct device *mux_dev,
+			u32 force_nr, u32 chan_id,
+			unsigned int class)
 {
 	struct i2c_adapter *parent = muxc->parent;
 	struct i2c_mux_priv *priv;
 	char symlink_name[20];
 	int ret;
 
+	if (muxc->adapters >= muxc->max_adapters) {
+		int new_max = 2 * muxc->max_adapters;
+
+		if (!new_max)
+			new_max = 1;
+		ret = i2c_mux_reserve_adapters(muxc, new_max);
+		if (ret)
+			return ret;
+	}
+
 	priv = kzalloc(sizeof(struct i2c_mux_priv), GFP_KERNEL);
 	if (!priv)
-		return NULL;
+		return -ENOMEM;
 
 	/* Set up private adapter data */
 	priv->muxc = muxc;
@@ -204,7 +237,7 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
 			"failed to add mux-adapter (error=%d)\n",
 			ret);
 		kfree(priv);
-		return NULL;
+		return ret;
 	}
 
 	WARN(sysfs_create_link(&priv->adap.dev.kobj, &mux_dev->kobj, "mux_device"),
@@ -216,23 +249,31 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
 	dev_info(&parent->dev, "Added multiplexed i2c bus %d\n",
 		 i2c_adapter_id(&priv->adap));
 
-	return &priv->adap;
+	muxc->adapter[muxc->adapters++] = &priv->adap;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(i2c_add_mux_adapter);
 
-void i2c_del_mux_adapter(struct i2c_adapter *adap)
+void i2c_del_mux_adapters(struct i2c_mux_core *muxc)
 {
-	struct i2c_mux_priv *priv = adap->algo_data;
 	char symlink_name[20];
 
-	snprintf(symlink_name, sizeof(symlink_name), "channel-%u", priv->chan_id);
-	sysfs_remove_link(&priv->mux_dev->kobj, symlink_name);
+	while (muxc->adapters) {
+		struct i2c_adapter *adap = muxc->adapter[--muxc->adapters];
+		struct i2c_mux_priv *priv = adap->algo_data;
 
-	sysfs_remove_link(&priv->adap.dev.kobj, "mux_device");
-	i2c_del_adapter(adap);
-	kfree(priv);
+		muxc->adapter[muxc->adapters] = NULL;
+
+		snprintf(symlink_name, sizeof(symlink_name),
+			 "channel-%u", priv->chan_id);
+		sysfs_remove_link(&priv->mux_dev->kobj, symlink_name);
+
+		sysfs_remove_link(&priv->adap.dev.kobj, "mux_device");
+		i2c_del_adapter(adap);
+		kfree(priv);
+	}
 }
-EXPORT_SYMBOL_GPL(i2c_del_mux_adapter);
+EXPORT_SYMBOL_GPL(i2c_del_mux_adapters);
 
 MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
 MODULE_DESCRIPTION("I2C driver for multiplexed I2C busses");
diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
index 1c4741cf290f..49aca5f26ebb 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 *child;
 	int our_gpio;
 	int our_gpio_release;
 	int their_gpio;
@@ -207,10 +206,9 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
 	}
 
 	/* Actually add the mux adapter */
-	arb->child = i2c_add_mux_adapter(muxc, dev, 0, 0, 0);
-	if (!arb->child) {
+	ret = i2c_add_mux_adapter(muxc, dev, 0, 0, 0);
+	if (ret) {
 		dev_err(dev, "Failed to add adapter\n");
-		ret = -ENODEV;
 		i2c_put_adapter(muxc->parent);
 	}
 
@@ -220,11 +218,9 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
 static int i2c_arbitrator_remove(struct platform_device *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_del_mux_adapters(muxc);
 	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 bd000406e160..49b8d83fbc22 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 **adap; /* child busses */
 	struct i2c_mux_gpio_platform_data data;
 	unsigned gpio_base;
 };
@@ -184,12 +183,9 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
 	muxc->select = i2c_mux_gpio_select;
 	mux->gpio_base = gpio_base;
 
-	mux->adap = devm_kzalloc(&pdev->dev,
-				 sizeof(*mux->adap) * mux->data.n_values,
-				 GFP_KERNEL);
-	if (!mux->adap) {
-		dev_err(&pdev->dev, "Cannot allocate i2c_adapter structure");
-		ret = -ENOMEM;
+	ret = i2c_mux_reserve_adapters(muxc, mux->data.n_values);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot allocate i2c_adapter structures\n");
 		goto alloc_failed;
 	}
 
@@ -224,10 +220,9 @@ 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(muxc, &pdev->dev, nr,
-						   mux->data.values[i], class);
-		if (!mux->adap[i]) {
-			ret = -ENODEV;
+		ret = i2c_add_mux_adapter(muxc, &pdev->dev, nr,
+					  mux->data.values[i], class);
+		if (ret) {
 			dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
 			goto add_adapter_failed;
 		}
@@ -239,8 +234,7 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
 	return 0;
 
 add_adapter_failed:
-	for (; i > 0; i--)
-		i2c_del_mux_adapter(mux->adap[i - 1]);
+	i2c_del_mux_adapters(muxc);
 	i = mux->data.n_gpios;
 err_request_gpio:
 	for (; i > 0; i--)
@@ -257,8 +251,7 @@ static int i2c_mux_gpio_remove(struct platform_device *pdev)
 	struct gpiomux *mux = i2c_mux_priv(muxc);
 	int i;
 
-	for (i = 0; i < mux->data.n_values; i++)
-		i2c_del_mux_adapter(mux->adap[i]);
+	i2c_del_mux_adapters(muxc);
 
 	for (i = 0; i < mux->data.n_gpios; i++)
 		gpio_free(mux->gpio_base + mux->data.gpios[i]);
diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c
index 178c22981636..791efe1d3dbc 100644
--- a/drivers/i2c/muxes/i2c-mux-pca9541.c
+++ b/drivers/i2c/muxes/i2c-mux-pca9541.c
@@ -74,7 +74,6 @@
 
 struct pca9541 {
 	struct i2c_client *client;
-	struct i2c_adapter *mux_adap;
 	unsigned long select_timeout;
 	unsigned long arb_timeout;
 };
@@ -332,6 +331,7 @@ static int pca9541_probe(struct i2c_client *client,
 	struct i2c_mux_core *muxc;
 	struct pca9541 *data;
 	int force;
+	int ret;
 
 	if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
@@ -364,11 +364,10 @@ 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(muxc, &client->dev, force, 0, 0);
-
-	if (data->mux_adap == NULL) {
+	ret = i2c_add_mux_adapter(muxc, &client->dev, force, 0, 0);
+	if (ret) {
 		dev_err(&client->dev, "failed to register master selector\n");
-		return -ENODEV;
+		return ret;
 	}
 
 	dev_info(&client->dev, "registered master selector for I2C %s\n",
@@ -380,10 +379,8 @@ static int pca9541_probe(struct i2c_client *client,
 static int pca9541_remove(struct i2c_client *client)
 {
 	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
-	struct pca9541 *data = i2c_mux_priv(muxc);
-
-	i2c_del_mux_adapter(data->mux_adap);
 
+	i2c_del_mux_adapters(muxc);
 	return 0;
 }
 
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index edc6693ffea9..e3219ba9307c 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -60,7 +60,6 @@ enum pca_type {
 
 struct pca954x {
 	enum pca_type type;
-	struct i2c_adapter *virt_adaps[PCA954X_MAX_NCHANS];
 
 	u8 last_chan;		/* last register value */
 	u8 deselect;
@@ -234,6 +233,13 @@ static int pca954x_probe(struct i2c_client *client,
 	data->type = id->driver_data;
 	data->last_chan = 0;		   /* force the first selection */
 
+	ret = i2c_mux_reserve_adapters(muxc, chips[data->type].nchans);
+	if (ret) {
+		dev_err(&client->dev,
+			"Cannot allocate i2c_adapter structures\n");
+		return ret;
+	}
+
 	idle_disconnect_dt = of_node &&
 		of_property_read_bool(of_node, "i2c-mux-idle-disconnect");
 
@@ -256,12 +262,10 @@ static int pca954x_probe(struct i2c_client *client,
 					   || idle_disconnect_dt) << num;
 		}
 
-		data->virt_adaps[num] =
-			i2c_add_mux_adapter(muxc, &client->dev,
-					    force, num, class);
+		ret = i2c_add_mux_adapter(muxc, &client->dev,
+					  force, num, class);
 
-		if (data->virt_adaps[num] == NULL) {
-			ret = -ENODEV;
+		if (ret) {
 			dev_err(&client->dev,
 				"failed to register multiplexed adapter"
 				" %d as bus %d\n", num, force);
@@ -277,24 +281,15 @@ static int pca954x_probe(struct i2c_client *client,
 	return 0;
 
 virt_reg_failed:
-	for (num--; num >= 0; num--)
-		i2c_del_mux_adapter(data->virt_adaps[num]);
+	i2c_del_mux_adapters(muxc);
 	return ret;
 }
 
 static int pca954x_remove(struct i2c_client *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;
-
-	for (i = 0; i < chip->nchans; ++i)
-		if (data->virt_adaps[i]) {
-			i2c_del_mux_adapter(data->virt_adaps[i]);
-			data->virt_adaps[i] = NULL;
-		}
 
+	i2c_del_mux_adapters(muxc);
 	return 0;
 }
 
diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c
index 79bd1ea75444..23792a1b2b3c 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 **busses;
 };
 
 static int i2c_mux_pinctrl_select(struct i2c_mux_core *muxc, u32 chan)
@@ -164,12 +163,9 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
 		goto err;
 	}
 
-	mux->busses = devm_kzalloc(&pdev->dev,
-				   sizeof(*mux->busses) * mux->pdata->bus_count,
-				   GFP_KERNEL);
-	if (!mux->busses) {
-		dev_err(&pdev->dev, "Cannot allocate busses\n");
-		ret = -ENOMEM;
+	ret = i2c_mux_reserve_adapters(muxc, mux->pdata->bus_count);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot reserve adapters\n");
 		goto err;
 	}
 
@@ -219,10 +215,9 @@ 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(muxc, &pdev->dev,
-						     bus, i, 0);
-		if (!mux->busses[i]) {
-			ret = -ENODEV;
+		ret = i2c_add_mux_adapter(muxc, &pdev->dev,
+					  bus, i, 0);
+		if (ret) {
 			dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
 			goto err_del_adapter;
 		}
@@ -231,8 +226,7 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
 	return 0;
 
 err_del_adapter:
-	for (; i > 0; i--)
-		i2c_del_mux_adapter(mux->busses[i - 1]);
+	i2c_del_mux_adapters(muxc);
 	i2c_put_adapter(muxc->parent);
 err:
 	return ret;
@@ -241,14 +235,9 @@ err:
 static int i2c_mux_pinctrl_remove(struct platform_device *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_del_mux_adapters(muxc);
 	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 d85879c46d90..73de562b7731 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 **adap; /* child busses */
 	struct i2c_mux_reg_platform_data data;
 };
 
@@ -216,11 +215,9 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	mux->adap = devm_kzalloc(&pdev->dev,
-				 sizeof(*mux->adap) * mux->data.n_values,
-				 GFP_KERNEL);
-	if (!mux->adap) {
-		dev_err(&pdev->dev, "Cannot allocate i2c_adapter structure");
+	ret = i2c_mux_reserve_adapters(muxc, mux->data.n_values);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot allocate i2c_adapter structures\n");
 		return -ENOMEM;
 	}
 
@@ -234,11 +231,9 @@ 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(muxc, &pdev->dev,
-						   nr, mux->data.values[i],
-						   class);
-		if (!mux->adap[i]) {
-			ret = -ENODEV;
+		ret = i2c_add_mux_adapter(muxc, &pdev->dev, nr,
+					  mux->data.values[i], class);
+		if (ret) {
 			dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
 			goto add_adapter_failed;
 		}
@@ -250,8 +245,7 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
 	return 0;
 
 add_adapter_failed:
-	for (; i > 0; i--)
-		i2c_del_mux_adapter(mux->adap[i - 1]);
+	i2c_del_mux_adapters(muxc);
 
 	return ret;
 }
@@ -259,12 +253,8 @@ add_adapter_failed:
 static int i2c_mux_reg_remove(struct platform_device *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_del_mux_adapters(muxc);
 	i2c_put_adapter(muxc->parent);
 
 	return 0;
diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h
index 5cd6e1e664e0..bfcdcc46f2a6 100644
--- a/include/linux/i2c-mux.h
+++ b/include/linux/i2c-mux.h
@@ -29,6 +29,9 @@
 
 struct i2c_mux_core {
 	struct i2c_adapter *parent;
+	struct i2c_adapter **adapter;
+	int adapters;
+	int max_adapters;
 	struct device *dev;
 
 	void *priv;
@@ -44,18 +47,20 @@ static inline void *i2c_mux_priv(struct i2c_mux_core *muxc)
 	return muxc->priv;
 }
 
+int i2c_mux_reserve_adapters(struct i2c_mux_core *muxc, int adapters);
+
 /*
  * 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_mux_core *muxc,
-					struct device *mux_dev,
-					u32 force_nr, u32 chan_id,
-					unsigned int class);
+int i2c_add_mux_adapter(struct i2c_mux_core *muxc,
+			struct device *mux_dev,
+			u32 force_nr, u32 chan_id,
+			unsigned int class);
 
-void i2c_del_mux_adapter(struct i2c_adapter *adap);
+void i2c_del_mux_adapters(struct i2c_mux_core *muxc);
 
 #endif /* __KERNEL__ */
 
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 04/10] i2c-mux: remove the mux dev pointer from the mux per channel data
  2016-01-04 15:10 [PATCH 00/10] i2c mux cleanup and locking update Peter Rosin
                   ` (2 preceding siblings ...)
  2016-01-04 15:10 ` [PATCH 03/10] i2c-mux: move the slave side adapter management " Peter Rosin
@ 2016-01-04 15:10 ` Peter Rosin
  2016-01-04 15:10 ` [PATCH 05/10] i2c-mux: pinctrl: get rid of the driver private struct device pointer Peter Rosin
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Peter Rosin @ 2016-01-04 15:10 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Peter Rosin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Peter Korsgaard, Guenter Roeck, linux-i2c,
	devicetree, linux-kernel, Peter Rosin

From: Peter Rosin <peda@axentia.se>

The dev pointer is readily available in the mux core struct, no point in
keeping multiple copies around.

Signed-off-by: Peter Rosin <peda@axentia.se>
---
 drivers/i2c/i2c-mux.c                      | 24 ++++++++++++------------
 drivers/i2c/muxes/i2c-arb-gpio-challenge.c |  2 +-
 drivers/i2c/muxes/i2c-mux-gpio.c           |  3 +--
 drivers/i2c/muxes/i2c-mux-pca9541.c        |  2 +-
 drivers/i2c/muxes/i2c-mux-pca954x.c        |  3 +--
 drivers/i2c/muxes/i2c-mux-pinctrl.c        |  3 +--
 drivers/i2c/muxes/i2c-mux-reg.c            |  3 +--
 include/linux/i2c-mux.h                    |  1 -
 8 files changed, 18 insertions(+), 23 deletions(-)

diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index 84169a1c9c1b..b507a799f222 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -32,7 +32,6 @@ struct i2c_mux_priv {
 	struct i2c_adapter adap;
 	struct i2c_algorithm algo;
 	struct i2c_mux_core *muxc;
-	struct device *mux_dev;
 	u32 chan_id;
 };
 
@@ -144,7 +143,6 @@ fail:
 EXPORT_SYMBOL_GPL(i2c_mux_alloc);
 
 int i2c_add_mux_adapter(struct i2c_mux_core *muxc,
-			struct device *mux_dev,
 			u32 force_nr, u32 chan_id,
 			unsigned int class)
 {
@@ -169,7 +167,6 @@ int i2c_add_mux_adapter(struct i2c_mux_core *muxc,
 
 	/* Set up private adapter data */
 	priv->muxc = muxc;
-	priv->mux_dev = mux_dev;
 	priv->chan_id = chan_id;
 
 	/* Need to do algo dynamically because we don't know ahead
@@ -204,11 +201,11 @@ int i2c_add_mux_adapter(struct i2c_mux_core *muxc,
 	 * Try to populate the mux adapter's of_node, expands to
 	 * nothing if !CONFIG_OF.
 	 */
-	if (mux_dev->of_node) {
+	if (muxc->dev->of_node) {
 		struct device_node *child;
 		u32 reg;
 
-		for_each_child_of_node(mux_dev->of_node, child) {
+		for_each_child_of_node(muxc->dev->of_node, child) {
 			ret = of_property_read_u32(child, "reg", &reg);
 			if (ret)
 				continue;
@@ -222,8 +219,9 @@ int i2c_add_mux_adapter(struct i2c_mux_core *muxc,
 	/*
 	 * Associate the mux channel with an ACPI node.
 	 */
-	if (has_acpi_companion(mux_dev))
-		acpi_preset_companion(&priv->adap.dev, ACPI_COMPANION(mux_dev),
+	if (has_acpi_companion(muxc->dev))
+		acpi_preset_companion(&priv->adap.dev,
+				      ACPI_COMPANION(muxc->dev),
 				      chan_id);
 
 	if (force_nr) {
@@ -240,12 +238,14 @@ int i2c_add_mux_adapter(struct i2c_mux_core *muxc,
 		return ret;
 	}
 
-	WARN(sysfs_create_link(&priv->adap.dev.kobj, &mux_dev->kobj, "mux_device"),
-			       "can't create symlink to mux device\n");
+	WARN(sysfs_create_link(&priv->adap.dev.kobj, &muxc->dev->kobj,
+			       "mux_device"),
+	     "can't create symlink to mux device\n");
 
 	snprintf(symlink_name, sizeof(symlink_name), "channel-%u", chan_id);
-	WARN(sysfs_create_link(&mux_dev->kobj, &priv->adap.dev.kobj, symlink_name),
-			       "can't create symlink for channel %u\n", chan_id);
+	WARN(sysfs_create_link(&muxc->dev->kobj, &priv->adap.dev.kobj,
+			       symlink_name),
+	     "can't create symlink for channel %u\n", chan_id);
 	dev_info(&parent->dev, "Added multiplexed i2c bus %d\n",
 		 i2c_adapter_id(&priv->adap));
 
@@ -266,7 +266,7 @@ void i2c_del_mux_adapters(struct i2c_mux_core *muxc)
 
 		snprintf(symlink_name, sizeof(symlink_name),
 			 "channel-%u", priv->chan_id);
-		sysfs_remove_link(&priv->mux_dev->kobj, symlink_name);
+		sysfs_remove_link(&muxc->dev->kobj, symlink_name);
 
 		sysfs_remove_link(&priv->adap.dev.kobj, "mux_device");
 		i2c_del_adapter(adap);
diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
index 49aca5f26ebb..13379762d91a 100644
--- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
+++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
@@ -206,7 +206,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
 	}
 
 	/* Actually add the mux adapter */
-	ret = i2c_add_mux_adapter(muxc, dev, 0, 0, 0);
+	ret = i2c_add_mux_adapter(muxc, 0, 0, 0);
 	if (ret) {
 		dev_err(dev, "Failed to add adapter\n");
 		i2c_put_adapter(muxc->parent);
diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index 49b8d83fbc22..4641ea0da516 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -220,8 +220,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;
 
-		ret = i2c_add_mux_adapter(muxc, &pdev->dev, nr,
-					  mux->data.values[i], class);
+		ret = i2c_add_mux_adapter(muxc, nr, mux->data.values[i], class);
 		if (ret) {
 			dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
 			goto add_adapter_failed;
diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c
index 791efe1d3dbc..9ee0d8b70283 100644
--- a/drivers/i2c/muxes/i2c-mux-pca9541.c
+++ b/drivers/i2c/muxes/i2c-mux-pca9541.c
@@ -364,7 +364,7 @@ static int pca9541_probe(struct i2c_client *client,
 	force = 0;
 	if (pdata)
 		force = pdata->modes[0].adap_id;
-	ret = i2c_add_mux_adapter(muxc, &client->dev, force, 0, 0);
+	ret = i2c_add_mux_adapter(muxc, force, 0, 0);
 	if (ret) {
 		dev_err(&client->dev, "failed to register master selector\n");
 		return ret;
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index e3219ba9307c..bd89da42b417 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -262,8 +262,7 @@ static int pca954x_probe(struct i2c_client *client,
 					   || idle_disconnect_dt) << num;
 		}
 
-		ret = i2c_add_mux_adapter(muxc, &client->dev,
-					  force, num, class);
+		ret = i2c_add_mux_adapter(muxc, force, num, class);
 
 		if (ret) {
 			dev_err(&client->dev,
diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c
index 23792a1b2b3c..24c8f218760f 100644
--- a/drivers/i2c/muxes/i2c-mux-pinctrl.c
+++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c
@@ -215,8 +215,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;
 
-		ret = i2c_add_mux_adapter(muxc, &pdev->dev,
-					  bus, i, 0);
+		ret = i2c_add_mux_adapter(muxc, bus, i, 0);
 		if (ret) {
 			dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
 			goto err_del_adapter;
diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c
index 73de562b7731..3624635f70ff 100644
--- a/drivers/i2c/muxes/i2c-mux-reg.c
+++ b/drivers/i2c/muxes/i2c-mux-reg.c
@@ -231,8 +231,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;
 
-		ret = i2c_add_mux_adapter(muxc, &pdev->dev, nr,
-					  mux->data.values[i], class);
+		ret = i2c_add_mux_adapter(muxc, nr, mux->data.values[i], class);
 		if (ret) {
 			dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
 			goto add_adapter_failed;
diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h
index bfcdcc46f2a6..d88e0a3b6768 100644
--- a/include/linux/i2c-mux.h
+++ b/include/linux/i2c-mux.h
@@ -56,7 +56,6 @@ int i2c_mux_reserve_adapters(struct i2c_mux_core *muxc, int adapters);
  * mux control.
  */
 int i2c_add_mux_adapter(struct i2c_mux_core *muxc,
-			struct device *mux_dev,
 			u32 force_nr, u32 chan_id,
 			unsigned int class);
 
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 05/10] i2c-mux: pinctrl: get rid of the driver private struct device pointer
  2016-01-04 15:10 [PATCH 00/10] i2c mux cleanup and locking update Peter Rosin
                   ` (3 preceding siblings ...)
  2016-01-04 15:10 ` [PATCH 04/10] i2c-mux: remove the mux dev pointer from the mux per channel data Peter Rosin
@ 2016-01-04 15:10 ` Peter Rosin
  2016-01-04 15:10 ` [PATCH 06/10] i2c: allow adapter drivers to override the adapter locking Peter Rosin
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Peter Rosin @ 2016-01-04 15:10 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Peter Rosin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Peter Korsgaard, Guenter Roeck, linux-i2c,
	devicetree, linux-kernel, Peter Rosin

From: Peter Rosin <peda@axentia.se>

There is a copy of the device pointer in the mux core.

Signed-off-by: Peter Rosin <peda@axentia.se>
---
 drivers/i2c/muxes/i2c-mux-pinctrl.c | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c
index 24c8f218760f..e27f66bf5341 100644
--- a/drivers/i2c/muxes/i2c-mux-pinctrl.c
+++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c
@@ -26,7 +26,6 @@
 #include <linux/of.h>
 
 struct i2c_mux_pinctrl {
-	struct device *dev;
 	struct i2c_mux_pinctrl_platform_data *pdata;
 	struct pinctrl *pinctrl;
 	struct pinctrl_state **states;
@@ -51,6 +50,7 @@ static int i2c_mux_pinctrl_deselect(struct i2c_mux_core *muxc, u32 chan)
 static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
 				struct platform_device *pdev)
 {
+	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
 	struct device_node *np = pdev->dev.of_node;
 	int num_names, i, ret;
 	struct device_node *adapter_np;
@@ -61,14 +61,14 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
 
 	mux->pdata = devm_kzalloc(&pdev->dev, sizeof(*mux->pdata), GFP_KERNEL);
 	if (!mux->pdata) {
-		dev_err(mux->dev,
+		dev_err(muxc->dev,
 			"Cannot allocate i2c_mux_pinctrl_platform_data\n");
 		return -ENOMEM;
 	}
 
 	num_names = of_property_count_strings(np, "pinctrl-names");
 	if (num_names < 0) {
-		dev_err(mux->dev, "Cannot parse pinctrl-names: %d\n",
+		dev_err(muxc->dev, "Cannot parse pinctrl-names: %d\n",
 			num_names);
 		return num_names;
 	}
@@ -77,7 +77,7 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
 		sizeof(*mux->pdata->pinctrl_states) * num_names,
 		GFP_KERNEL);
 	if (!mux->pdata->pinctrl_states) {
-		dev_err(mux->dev, "Cannot allocate pinctrl_states\n");
+		dev_err(muxc->dev, "Cannot allocate pinctrl_states\n");
 		return -ENOMEM;
 	}
 
@@ -85,14 +85,14 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
 		ret = of_property_read_string_index(np, "pinctrl-names", i,
 			&mux->pdata->pinctrl_states[mux->pdata->bus_count]);
 		if (ret < 0) {
-			dev_err(mux->dev, "Cannot parse pinctrl-names: %d\n",
+			dev_err(muxc->dev, "Cannot parse pinctrl-names: %d\n",
 				ret);
 			return ret;
 		}
 		if (!strcmp(mux->pdata->pinctrl_states[mux->pdata->bus_count],
 			    "idle")) {
 			if (i != num_names - 1) {
-				dev_err(mux->dev, "idle state must be last\n");
+				dev_err(muxc->dev, "idle state must be last\n");
 				return -EINVAL;
 			}
 			mux->pdata->pinctrl_state_idle = "idle";
@@ -103,13 +103,13 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
 
 	adapter_np = of_parse_phandle(np, "i2c-parent", 0);
 	if (!adapter_np) {
-		dev_err(mux->dev, "Cannot parse i2c-parent\n");
+		dev_err(muxc->dev, "Cannot parse i2c-parent\n");
 		return -ENODEV;
 	}
 	adapter = of_find_i2c_adapter_by_node(adapter_np);
 	of_node_put(adapter_np);
 	if (!adapter) {
-		dev_err(mux->dev, "Cannot find parent bus\n");
+		dev_err(muxc->dev, "Cannot find parent bus\n");
 		return -EPROBE_DEFER;
 	}
 	mux->pdata->parent_bus_num = i2c_adapter_id(adapter);
@@ -140,8 +140,6 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
 	mux = i2c_mux_priv(muxc);
 	platform_set_drvdata(pdev, muxc);
 
-	mux->dev = &pdev->dev;
-
 	mux->pdata = dev_get_platdata(&pdev->dev);
 	if (!mux->pdata) {
 		ret = i2c_mux_pinctrl_parse_dt(mux, pdev);
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 06/10] i2c: allow adapter drivers to override the adapter locking
  2016-01-04 15:10 [PATCH 00/10] i2c mux cleanup and locking update Peter Rosin
                   ` (4 preceding siblings ...)
  2016-01-04 15:10 ` [PATCH 05/10] i2c-mux: pinctrl: get rid of the driver private struct device pointer Peter Rosin
@ 2016-01-04 15:10 ` Peter Rosin
  2016-01-04 15:10 ` [PATCH 07/10] i2c: muxes always lock the parent adapter Peter Rosin
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Peter Rosin @ 2016-01-04 15:10 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Peter Rosin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Peter Korsgaard, Guenter Roeck, linux-i2c,
	devicetree, linux-kernel, Peter Rosin

From: Peter Rosin <peda@axentia.se>

Add i2c_lock_bus() and i2c_unlock_bus(), which call the new lock_bus and
unlock_bus ops in the adapter. These funcs/ops take an additional flags
argument that indicates for what purpose the adapter is locked.

There are two flags, I2C_LOCK_ADAPTER and I2C_LOCK_SEGMENT, but they are
both implemented the same. For now. Locking the adapter means that the
whole bus is locked, locking the segment means that only the current bus
segment is locked (i.e. i2c traffic on the parent side of mux is still
allowed even if the child side of the mux is locked.

Also support a trylock_bus op (but no function to call it, as it is not
expected to be needed outside of the i2c core).

Implement i2c_lock_adapter/i2c_unlock_adapter in terms of the new locking
scheme (i.e. lock with the I2C_LOCK_ADAPTER flag).

Annotate some of the locking with explicit I2C_LOCK_SEGMENT flags.

Signed-off-by: Peter Rosin <peda@axentia.se>
---
 drivers/i2c/i2c-core.c | 40 ++++++++++++++++++++++------------------
 include/linux/i2c.h    | 28 ++++++++++++++++++++++++++--
 2 files changed, 48 insertions(+), 20 deletions(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index ba8eb087f224..34a7748b4652 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -958,10 +958,10 @@ static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr)
 }
 
 /**
- * i2c_lock_adapter - Get exclusive access to an I2C bus segment
+ * i2c_adapter_lock_bus - Get exclusive access to an I2C bus segment
  * @adapter: Target I2C bus segment
  */
-void i2c_lock_adapter(struct i2c_adapter *adapter)
+static void i2c_adapter_lock_bus(struct i2c_adapter *adapter, int flags)
 {
 	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
 
@@ -970,27 +970,26 @@ void i2c_lock_adapter(struct i2c_adapter *adapter)
 	else
 		rt_mutex_lock(&adapter->bus_lock);
 }
-EXPORT_SYMBOL_GPL(i2c_lock_adapter);
 
 /**
- * i2c_trylock_adapter - Try to get exclusive access to an I2C bus segment
+ * i2c_adapter_trylock_bus - Try to get exclusive access to an I2C bus segment
  * @adapter: Target I2C bus segment
  */
-static int i2c_trylock_adapter(struct i2c_adapter *adapter)
+static int i2c_adapter_trylock_bus(struct i2c_adapter *adapter, int flags)
 {
 	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
 
 	if (parent)
-		return i2c_trylock_adapter(parent);
+		return parent->trylock_bus(parent, flags);
 	else
 		return rt_mutex_trylock(&adapter->bus_lock);
 }
 
 /**
- * i2c_unlock_adapter - Release exclusive access to an I2C bus segment
+ * i2c_adapter_unlock_bus - Release exclusive access to an I2C bus segment
  * @adapter: Target I2C bus segment
  */
-void i2c_unlock_adapter(struct i2c_adapter *adapter)
+static void i2c_adapter_unlock_bus(struct i2c_adapter *adapter, int flags)
 {
 	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
 
@@ -999,7 +998,6 @@ void i2c_unlock_adapter(struct i2c_adapter *adapter)
 	else
 		rt_mutex_unlock(&adapter->bus_lock);
 }
-EXPORT_SYMBOL_GPL(i2c_unlock_adapter);
 
 static void i2c_dev_set_name(struct i2c_adapter *adap,
 			     struct i2c_client *client)
@@ -1545,6 +1543,12 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
 		return -EINVAL;
 	}
 
+	if (!adap->lock_bus) {
+		adap->lock_bus = i2c_adapter_lock_bus;
+		adap->trylock_bus = i2c_adapter_trylock_bus;
+		adap->unlock_bus = i2c_adapter_unlock_bus;
+	}
+
 	rt_mutex_init(&adap->bus_lock);
 	mutex_init(&adap->userspace_clients_lock);
 	INIT_LIST_HEAD(&adap->userspace_clients);
@@ -2254,16 +2258,16 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 #endif
 
 		if (in_atomic() || irqs_disabled()) {
-			ret = i2c_trylock_adapter(adap);
+			ret = adap->trylock_bus(adap, I2C_LOCK_SEGMENT);
 			if (!ret)
 				/* I2C activity is ongoing. */
 				return -EAGAIN;
 		} else {
-			i2c_lock_adapter(adap);
+			i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
 		}
 
 		ret = __i2c_transfer(adap, msgs, num);
-		i2c_unlock_adapter(adap);
+		i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
 
 		return ret;
 	} else {
@@ -3038,7 +3042,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
 	flags &= I2C_M_TEN | I2C_CLIENT_PEC | I2C_CLIENT_SCCB;
 
 	if (adapter->algo->smbus_xfer) {
-		i2c_lock_adapter(adapter);
+		i2c_lock_bus(adapter, I2C_LOCK_SEGMENT);
 
 		/* Retry automatically on arbitration loss */
 		orig_jiffies = jiffies;
@@ -3052,7 +3056,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
 				       orig_jiffies + adapter->timeout))
 				break;
 		}
-		i2c_unlock_adapter(adapter);
+		i2c_unlock_bus(adapter, I2C_LOCK_SEGMENT);
 
 		if (res != -EOPNOTSUPP || !adapter->algo->master_xfer)
 			goto trace;
@@ -3163,9 +3167,9 @@ int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)
 
 	client->slave_cb = slave_cb;
 
-	i2c_lock_adapter(client->adapter);
+	i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
 	ret = client->adapter->algo->reg_slave(client);
-	i2c_unlock_adapter(client->adapter);
+	i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
 
 	if (ret) {
 		client->slave_cb = NULL;
@@ -3185,9 +3189,9 @@ int i2c_slave_unregister(struct i2c_client *client)
 		return -EOPNOTSUPP;
 	}
 
-	i2c_lock_adapter(client->adapter);
+	i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
 	ret = client->adapter->algo->unreg_slave(client);
-	i2c_unlock_adapter(client->adapter);
+	i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
 
 	if (ret == 0)
 		client->slave_cb = NULL;
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 768063baafbf..8040b48aef75 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -520,6 +520,10 @@ struct i2c_adapter {
 
 	struct i2c_bus_recovery_info *bus_recovery_info;
 	const struct i2c_adapter_quirks *quirks;
+
+	void (*lock_bus)(struct i2c_adapter *, int flags);
+	int (*trylock_bus)(struct i2c_adapter *, int flags);
+	void (*unlock_bus)(struct i2c_adapter *, int flags);
 };
 #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
 
@@ -549,8 +553,28 @@ i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter)
 int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *));
 
 /* Adapter locking functions, exported for shared pin cases */
-void i2c_lock_adapter(struct i2c_adapter *);
-void i2c_unlock_adapter(struct i2c_adapter *);
+#define I2C_LOCK_ADAPTER 0x01
+#define I2C_LOCK_SEGMENT 0x02
+static inline void
+i2c_lock_bus(struct i2c_adapter *adapter, int flags)
+{
+	adapter->lock_bus(adapter, flags);
+}
+static inline void
+i2c_unlock_bus(struct i2c_adapter *adapter, int flags)
+{
+	adapter->unlock_bus(adapter, flags);
+}
+static inline void
+i2c_lock_adapter(struct i2c_adapter *adapter)
+{
+	i2c_lock_bus(adapter, I2C_LOCK_ADAPTER);
+}
+static inline void
+i2c_unlock_adapter(struct i2c_adapter *adapter)
+{
+	i2c_unlock_bus(adapter, I2C_LOCK_ADAPTER);
+}
 
 /*flags for the client struct: */
 #define I2C_CLIENT_PEC		0x04	/* Use Packet Error Checking */
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 07/10] i2c: muxes always lock the parent adapter
  2016-01-04 15:10 [PATCH 00/10] i2c mux cleanup and locking update Peter Rosin
                   ` (5 preceding siblings ...)
  2016-01-04 15:10 ` [PATCH 06/10] i2c: allow adapter drivers to override the adapter locking Peter Rosin
@ 2016-01-04 15:10 ` Peter Rosin
  2016-01-04 15:10 ` [PATCH 08/10] i2c-mux: relax locking of the top i2c adapter during i2c controlled muxing Peter Rosin
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Peter Rosin @ 2016-01-04 15:10 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Peter Rosin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Peter Korsgaard, Guenter Roeck, linux-i2c,
	devicetree, linux-kernel, Peter Rosin

From: Peter Rosin <peda@axentia.se>

Instead of checking for i2c parent adapters for every lock/unlock, simply
override the locking for muxes to always lock/unlock the parent adapter
directly.

Signed-off-by: Peter Rosin <peda@axentia.se>
---
 drivers/i2c/i2c-core.c | 21 +++------------------
 drivers/i2c/i2c-mux.c  | 27 +++++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 18 deletions(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 34a7748b4652..4683777f81ca 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -963,12 +963,7 @@ static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr)
  */
 static void i2c_adapter_lock_bus(struct i2c_adapter *adapter, int flags)
 {
-	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
-
-	if (parent)
-		i2c_lock_adapter(parent);
-	else
-		rt_mutex_lock(&adapter->bus_lock);
+	rt_mutex_lock(&adapter->bus_lock);
 }
 
 /**
@@ -977,12 +972,7 @@ static void i2c_adapter_lock_bus(struct i2c_adapter *adapter, int flags)
  */
 static int i2c_adapter_trylock_bus(struct i2c_adapter *adapter, int flags)
 {
-	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
-
-	if (parent)
-		return parent->trylock_bus(parent, flags);
-	else
-		return rt_mutex_trylock(&adapter->bus_lock);
+	return rt_mutex_trylock(&adapter->bus_lock);
 }
 
 /**
@@ -991,12 +981,7 @@ static int i2c_adapter_trylock_bus(struct i2c_adapter *adapter, int flags)
  */
 static void i2c_adapter_unlock_bus(struct i2c_adapter *adapter, int flags)
 {
-	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
-
-	if (parent)
-		i2c_unlock_adapter(parent);
-	else
-		rt_mutex_unlock(&adapter->bus_lock);
+	rt_mutex_unlock(&adapter->bus_lock);
 }
 
 static void i2c_dev_set_name(struct i2c_adapter *adap,
diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index b507a799f222..605333757a5e 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -98,6 +98,30 @@ static unsigned int i2c_mux_parent_classes(struct i2c_adapter *parent)
 	return class;
 }
 
+static void i2c_parent_lock_bus(struct i2c_adapter *adapter, int flags)
+{
+	struct i2c_mux_priv *priv = adapter->algo_data;
+	struct i2c_adapter *parent = priv->muxc->parent;
+
+	parent->lock_bus(parent, flags);
+}
+
+static int i2c_parent_trylock_bus(struct i2c_adapter *adapter, int flags)
+{
+	struct i2c_mux_priv *priv = adapter->algo_data;
+	struct i2c_adapter *parent = priv->muxc->parent;
+
+	return parent->trylock_bus(parent, flags);
+}
+
+static void i2c_parent_unlock_bus(struct i2c_adapter *adapter, int flags)
+{
+	struct i2c_mux_priv *priv = adapter->algo_data;
+	struct i2c_adapter *parent = priv->muxc->parent;
+
+	parent->unlock_bus(parent, flags);
+}
+
 int i2c_mux_reserve_adapters(struct i2c_mux_core *muxc, int adapters)
 {
 	struct i2c_adapter **adapter;
@@ -188,6 +212,9 @@ int i2c_add_mux_adapter(struct i2c_mux_core *muxc,
 	priv->adap.retries = parent->retries;
 	priv->adap.timeout = parent->timeout;
 	priv->adap.quirks = parent->quirks;
+	priv->adap.lock_bus = i2c_parent_lock_bus;
+	priv->adap.trylock_bus = i2c_parent_trylock_bus;
+	priv->adap.unlock_bus = i2c_parent_unlock_bus;
 
 	/* Sanity check on class */
 	if (i2c_mux_parent_classes(parent) & class)
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 08/10] i2c-mux: relax locking of the top i2c adapter during i2c controlled muxing
  2016-01-04 15:10 [PATCH 00/10] i2c mux cleanup and locking update Peter Rosin
                   ` (6 preceding siblings ...)
  2016-01-04 15:10 ` [PATCH 07/10] i2c: muxes always lock the parent adapter Peter Rosin
@ 2016-01-04 15:10 ` Peter Rosin
  2016-01-04 15:10 ` [PATCH 09/10] i2c: pca9541: get rid of the i2c deadlock workaround Peter Rosin
  2016-01-04 15:10 ` [PATCH 10/10] i2c: pca954x: " Peter Rosin
  9 siblings, 0 replies; 22+ messages in thread
From: Peter Rosin @ 2016-01-04 15:10 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Peter Rosin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Peter Korsgaard, Guenter Roeck, linux-i2c,
	devicetree, linux-kernel, Peter Rosin

From: Peter Rosin <peda@axentia.se>

With a i2c topology like the following

                       GPIO ---|  ------ BAT1
                        |      v /
   I2C  -----+----------+---- MUX
             |                   \
           EEPROM                 ------ BAT2

there is a locking problem with the GPIO controller since it is a client
on the same i2c bus that it muxes. Transfers to the mux clients (e.g. BAT1)
will lock the whole i2c bus prior to attempting to switch the mux to the
correct i2c segment. In the above case, the GPIO device is an I/O expander
with an i2c interface, and since the GPIO subsystem knows nothing (and
rightfully so) about the lockless needs of the i2c mux code, this results
in a deadlock when the GPIO driver issues i2c transfers to modify the
mux.

So, observing that while it is needed to have the i2c bus locked during the
actual MUX update in order to avoid random garbage on the slave side, it
is not strictly a must to have it locked over the whole sequence of a full
select-transfer-deselect mux client operation. The mux itself needs to be
locked, so transfers to clients behind the mux are serialized, and the mux
needs to be stable during all i2c traffic (otherwise individual mux slave
segments might see garbage, or worse).

Add devive tree properties (bool named i2c-controlled) to i2c-mux-gpio and
i2c-mux-pinctrl that asserts that the the gpio/pinctrl is controlled via
the same i2c bus that it muxes.

Modify the i2c mux locking so that muxes that are "i2c-controlled" locks
the mux instead of the whole i2c bus when there is a transfer to the slave
side of the mux. This lock serializes transfers to the slave side of the
mux.

Modify the select-transfer-deselect code for "i2c-controlled" muxes so
that each of the select-transfer-deselect ops locks the mux parent
adapter individually.

Signed-off-by: Peter Rosin <peda@axentia.se>
---
 .../devicetree/bindings/i2c/i2c-mux-gpio.txt       |   2 +
 .../devicetree/bindings/i2c/i2c-mux-pinctrl.txt    |   4 +
 drivers/i2c/i2c-mux.c                              | 109 +++++++++++++++++++--
 drivers/i2c/muxes/i2c-mux-gpio.c                   |   3 +
 drivers/i2c/muxes/i2c-mux-pinctrl.c                |   3 +
 include/linux/i2c-mux-gpio.h                       |   2 +
 include/linux/i2c-mux-pinctrl.h                    |   2 +
 include/linux/i2c-mux.h                            |   2 +
 8 files changed, 120 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt b/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt
index 66709a825541..17670b997d81 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt
@@ -28,6 +28,8 @@ Required properties:
 Optional properties:
 - idle-state: value to set the muxer to when idle. When no value is
   given, it defaults to the last value used.
+- i2c-controlled: The muxed I2C bus is also used to control all the gpios
+  used for muxing.
 
 For each i2c child node, an I2C child bus will be created. They will
 be numbered based on their order in the device tree.
diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt b/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt
index ae8af1694e95..8374a1f7a709 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt
@@ -23,6 +23,10 @@ Required properties:
 - i2c-parent: The phandle of the I2C bus that this multiplexer's master-side
   port is connected to.
 
+Optional properties:
+- i2c-controlled: The muxed I2C bus is also used to control all the pinctrl
+  pins used for muxing.
+
 Also required are:
 
 * Standard pinctrl properties that specify the pin mux state for each child
diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index 605333757a5e..91066cfe5a95 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -54,6 +54,25 @@ static int i2c_mux_master_xfer(struct i2c_adapter *adap,
 	return ret;
 }
 
+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_mux_core *muxc = priv->muxc;
+	struct i2c_adapter *parent = muxc->parent;
+	int ret;
+
+	/* Switch to the right mux port and perform the transfer. */
+
+	ret = muxc->select(muxc, priv->chan_id);
+	if (ret >= 0)
+		ret = i2c_transfer(parent, msgs, num);
+	if (muxc->deselect)
+		muxc->deselect(muxc, priv->chan_id);
+
+	return ret;
+}
+
 static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,
 			      u16 addr, unsigned short flags,
 			      char read_write, u8 command,
@@ -76,6 +95,28 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,
 	return ret;
 }
 
+static int __i2c_mux_smbus_xfer(struct i2c_adapter *adap,
+				u16 addr, unsigned short flags,
+				char read_write, u8 command,
+				int size, union i2c_smbus_data *data)
+{
+	struct i2c_mux_priv *priv = adap->algo_data;
+	struct i2c_mux_core *muxc = priv->muxc;
+	struct i2c_adapter *parent = muxc->parent;
+	int ret;
+
+	/* Select the right mux port and perform the transfer. */
+
+	ret = muxc->select(muxc, priv->chan_id);
+	if (ret >= 0)
+		ret = i2c_smbus_xfer(parent, addr, flags,
+				     read_write, command, size, data);
+	if (muxc->deselect)
+		muxc->deselect(muxc, priv->chan_id);
+
+	return ret;
+}
+
 /* Return the parent's functionality */
 static u32 i2c_mux_functionality(struct i2c_adapter *adap)
 {
@@ -98,6 +139,45 @@ static unsigned int i2c_mux_parent_classes(struct i2c_adapter *parent)
 	return class;
 }
 
+static void i2c_mux_lock_bus(struct i2c_adapter *adapter, int flags)
+{
+	struct i2c_mux_priv *priv = adapter->algo_data;
+	struct i2c_mux_core *muxc = priv->muxc;
+	struct i2c_adapter *parent = muxc->parent;
+
+	rt_mutex_lock(&muxc->bus_lock);
+	if (!(flags & I2C_LOCK_ADAPTER))
+		return;
+	i2c_lock_bus(parent, flags);
+}
+
+static int i2c_mux_trylock_bus(struct i2c_adapter *adapter, int flags)
+{
+	struct i2c_mux_priv *priv = adapter->algo_data;
+	struct i2c_mux_core *muxc = priv->muxc;
+	struct i2c_adapter *parent = muxc->parent;
+
+	if (!rt_mutex_trylock(&muxc->bus_lock))
+		return 0;
+	if (!(flags & I2C_LOCK_ADAPTER))
+		return 1;
+	if (parent->trylock_bus(parent, flags))
+		return 1;
+	rt_mutex_unlock(&muxc->bus_lock);
+	return 0;
+}
+
+static void i2c_mux_unlock_bus(struct i2c_adapter *adapter, int flags)
+{
+	struct i2c_mux_priv *priv = adapter->algo_data;
+	struct i2c_mux_core *muxc = priv->muxc;
+	struct i2c_adapter *parent = muxc->parent;
+
+	if (flags & I2C_LOCK_ADAPTER)
+		i2c_unlock_bus(parent, flags);
+	rt_mutex_unlock(&muxc->bus_lock);
+}
+
 static void i2c_parent_lock_bus(struct i2c_adapter *adapter, int flags)
 {
 	struct i2c_mux_priv *priv = adapter->algo_data;
@@ -158,6 +238,7 @@ struct i2c_mux_core *i2c_mux_alloc(struct device *dev, int sizeof_priv)
 			goto fail;
 	}
 	muxc->dev = dev;
+	rt_mutex_init(&muxc->bus_lock);
 	return muxc;
 
 fail:
@@ -196,10 +277,18 @@ int i2c_add_mux_adapter(struct i2c_mux_core *muxc,
 	/* Need to do algo dynamically because we don't know ahead
 	 * of time what sort of physical adapter we'll be dealing with.
 	 */
-	if (parent->algo->master_xfer)
-		priv->algo.master_xfer = i2c_mux_master_xfer;
-	if (parent->algo->smbus_xfer)
-		priv->algo.smbus_xfer = i2c_mux_smbus_xfer;
+	if (parent->algo->master_xfer) {
+		if (muxc->i2c_controlled)
+			priv->algo.master_xfer = __i2c_mux_master_xfer;
+		else
+			priv->algo.master_xfer = i2c_mux_master_xfer;
+	}
+	if (parent->algo->smbus_xfer) {
+		if (muxc->i2c_controlled)
+			priv->algo.smbus_xfer = __i2c_mux_smbus_xfer;
+		else
+			priv->algo.smbus_xfer = i2c_mux_smbus_xfer;
+	}
 	priv->algo.functionality = i2c_mux_functionality;
 
 	/* Now fill out new adapter structure */
@@ -212,9 +301,15 @@ int i2c_add_mux_adapter(struct i2c_mux_core *muxc,
 	priv->adap.retries = parent->retries;
 	priv->adap.timeout = parent->timeout;
 	priv->adap.quirks = parent->quirks;
-	priv->adap.lock_bus = i2c_parent_lock_bus;
-	priv->adap.trylock_bus = i2c_parent_trylock_bus;
-	priv->adap.unlock_bus = i2c_parent_unlock_bus;
+	if (muxc->i2c_controlled) {
+		priv->adap.lock_bus = i2c_mux_lock_bus;
+		priv->adap.trylock_bus = i2c_mux_trylock_bus;
+		priv->adap.unlock_bus = i2c_mux_unlock_bus;
+	} else {
+		priv->adap.lock_bus = i2c_parent_lock_bus;
+		priv->adap.trylock_bus = i2c_parent_trylock_bus;
+		priv->adap.unlock_bus = i2c_parent_unlock_bus;
+	}
 
 	/* Sanity check on class */
 	if (i2c_mux_parent_classes(parent) & class)
diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index 4641ea0da516..af984d438fe1 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -68,6 +68,8 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
 	if (!np)
 		return -ENODEV;
 
+	mux->data.i2c_controlled = of_property_read_bool(np,
+							 "i2c-controlled");
 	adapter_np = of_parse_phandle(np, "i2c-parent", 0);
 	if (!adapter_np) {
 		dev_err(&pdev->dev, "Cannot parse i2c-parent\n");
@@ -179,6 +181,7 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
 	if (!parent)
 		return -EPROBE_DEFER;
 
+	muxc->i2c_controlled = mux->data.i2c_controlled;
 	muxc->parent = parent;
 	muxc->select = i2c_mux_gpio_select;
 	mux->gpio_base = gpio_base;
diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c
index e27f66bf5341..541c17567dbf 100644
--- a/drivers/i2c/muxes/i2c-mux-pinctrl.c
+++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c
@@ -101,6 +101,8 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
 		}
 	}
 
+	mux->pdata->i2c_controlled = of_property_read_bool(np,
+							   "i2c-controlled");
 	adapter_np = of_parse_phandle(np, "i2c-parent", 0);
 	if (!adapter_np) {
 		dev_err(muxc->dev, "Cannot parse i2c-parent\n");
@@ -201,6 +203,7 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
 	}
 	muxc->select = i2c_mux_pinctrl_select;
 
+	muxc->i2c_controlled = mux->pdata->i2c_controlled;
 	muxc->parent = i2c_get_adapter(mux->pdata->parent_bus_num);
 	if (!muxc->parent) {
 		dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
diff --git a/include/linux/i2c-mux-gpio.h b/include/linux/i2c-mux-gpio.h
index 4406108201fe..8fb19380bb03 100644
--- a/include/linux/i2c-mux-gpio.h
+++ b/include/linux/i2c-mux-gpio.h
@@ -27,6 +27,7 @@
  * @gpios: Array of GPIO numbers used to control MUX
  * @n_gpios: Number of GPIOs used to control MUX
  * @idle: Bitmask to write to MUX when idle or GPIO_I2CMUX_NO_IDLE if not used
+ * @i2c_controlled: Set if the parent i2c bus is used to control the gpio.
  */
 struct i2c_mux_gpio_platform_data {
 	int parent;
@@ -38,6 +39,7 @@ struct i2c_mux_gpio_platform_data {
 	const unsigned *gpios;
 	int n_gpios;
 	unsigned idle;
+	bool i2c_controlled;
 };
 
 #endif /* _LINUX_I2C_MUX_GPIO_H */
diff --git a/include/linux/i2c-mux-pinctrl.h b/include/linux/i2c-mux-pinctrl.h
index a65c86429e84..fb95cb7c45c5 100644
--- a/include/linux/i2c-mux-pinctrl.h
+++ b/include/linux/i2c-mux-pinctrl.h
@@ -29,6 +29,7 @@
  * @pinctrl_state_idle: The pinctrl state to select when no child bus is being
  *	accessed. If NULL, the most recently used pinctrl state will be left
  *	selected.
+ * @i2c_controlled: Set if the parent i2c bus is used to control the pinctrl.
  */
 struct i2c_mux_pinctrl_platform_data {
 	int parent_bus_num;
@@ -36,6 +37,7 @@ struct i2c_mux_pinctrl_platform_data {
 	int bus_count;
 	const char **pinctrl_states;
 	const char *pinctrl_state_idle;
+	bool i2c_controlled;
 };
 
 #endif
diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h
index d88e0a3b6768..b73d14c45121 100644
--- a/include/linux/i2c-mux.h
+++ b/include/linux/i2c-mux.h
@@ -33,6 +33,8 @@ struct i2c_mux_core {
 	int adapters;
 	int max_adapters;
 	struct device *dev;
+	struct rt_mutex bus_lock;
+	bool i2c_controlled;
 
 	void *priv;
 
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 09/10] i2c: pca9541: get rid of the i2c deadlock workaround
  2016-01-04 15:10 [PATCH 00/10] i2c mux cleanup and locking update Peter Rosin
                   ` (7 preceding siblings ...)
  2016-01-04 15:10 ` [PATCH 08/10] i2c-mux: relax locking of the top i2c adapter during i2c controlled muxing Peter Rosin
@ 2016-01-04 15:10 ` Peter Rosin
  2016-01-04 15:10 ` [PATCH 10/10] i2c: pca954x: " Peter Rosin
  9 siblings, 0 replies; 22+ messages in thread
From: Peter Rosin @ 2016-01-04 15:10 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Peter Rosin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Peter Korsgaard, Guenter Roeck, linux-i2c,
	devicetree, linux-kernel, Peter Rosin

From: Peter Rosin <peda@axentia.se>

Signed-off-by: Peter Rosin <peda@axentia.se>
---
 drivers/i2c/muxes/i2c-mux-pca9541.c | 82 +++++++------------------------------
 1 file changed, 15 insertions(+), 67 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c
index 9ee0d8b70283..7d2e5dbd8617 100644
--- a/drivers/i2c/muxes/i2c-mux-pca9541.c
+++ b/drivers/i2c/muxes/i2c-mux-pca9541.c
@@ -85,81 +85,28 @@ static const struct i2c_device_id pca9541_id[] = {
 
 MODULE_DEVICE_TABLE(i2c, pca9541_id);
 
-/*
- * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
- * as they will try to lock the adapter a second time.
- */
 static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val)
 {
-	struct i2c_adapter *adap = client->adapter;
-	int ret;
-
-	if (adap->algo->master_xfer) {
-		struct i2c_msg msg;
-		char buf[2];
-
-		msg.addr = client->addr;
-		msg.flags = 0;
-		msg.len = 2;
-		buf[0] = command;
-		buf[1] = val;
-		msg.buf = buf;
-		ret = __i2c_transfer(adap, &msg, 1);
-	} else {
-		union i2c_smbus_data data;
-
-		data.byte = val;
-		ret = adap->algo->smbus_xfer(adap, client->addr,
-					     client->flags,
-					     I2C_SMBUS_WRITE,
-					     command,
-					     I2C_SMBUS_BYTE_DATA, &data);
-	}
+	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+	union i2c_smbus_data data;
 
-	return ret;
+	data.byte = val;
+	return i2c_smbus_xfer(muxc->parent, client->addr, client->flags,
+			      I2C_SMBUS_WRITE, command,
+			      I2C_SMBUS_BYTE_DATA, &data);
 }
 
-/*
- * Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
- * as they will try to lock adapter a second time.
- */
 static int pca9541_reg_read(struct i2c_client *client, u8 command)
 {
-	struct i2c_adapter *adap = client->adapter;
+	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+	union i2c_smbus_data data;
 	int ret;
-	u8 val;
-
-	if (adap->algo->master_xfer) {
-		struct i2c_msg msg[2] = {
-			{
-				.addr = client->addr,
-				.flags = 0,
-				.len = 1,
-				.buf = &command
-			},
-			{
-				.addr = client->addr,
-				.flags = I2C_M_RD,
-				.len = 1,
-				.buf = &val
-			}
-		};
-		ret = __i2c_transfer(adap, msg, 2);
-		if (ret == 2)
-			ret = val;
-		else if (ret >= 0)
-			ret = -EIO;
-	} else {
-		union i2c_smbus_data data;
-
-		ret = adap->algo->smbus_xfer(adap, client->addr,
-					     client->flags,
-					     I2C_SMBUS_READ,
-					     command,
-					     I2C_SMBUS_BYTE_DATA, &data);
-		if (!ret)
-			ret = data.byte;
-	}
+
+	ret = i2c_smbus_xfer(muxc->parent, client->addr, client->flags,
+			     I2C_SMBUS_READ, command,
+			     I2C_SMBUS_BYTE_DATA, &data);
+	if (!ret)
+		ret = data.byte;
 	return ret;
 }
 
@@ -347,6 +294,7 @@ static int pca9541_probe(struct i2c_client *client,
 	i2c_set_clientdata(client, muxc);
 
 	data->client = client;
+	muxc->i2c_controlled = true;
 	muxc->parent = adap;
 	muxc->select = pca9541_select_chan;
 	muxc->deselect = pca9541_release_chan;
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 10/10] i2c: pca954x: get rid of the i2c deadlock workaround
  2016-01-04 15:10 [PATCH 00/10] i2c mux cleanup and locking update Peter Rosin
                   ` (8 preceding siblings ...)
  2016-01-04 15:10 ` [PATCH 09/10] i2c: pca9541: get rid of the i2c deadlock workaround Peter Rosin
@ 2016-01-04 15:10 ` Peter Rosin
  2016-01-04 15:19   ` Lars-Peter Clausen
  9 siblings, 1 reply; 22+ messages in thread
From: Peter Rosin @ 2016-01-04 15:10 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Peter Rosin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Peter Korsgaard, Guenter Roeck, linux-i2c,
	devicetree, linux-kernel, Peter Rosin

From: Peter Rosin <peda@axentia.se>

Signed-off-by: Peter Rosin <peda@axentia.se>
---
 drivers/i2c/muxes/i2c-mux-pca954x.c | 32 ++++++++++----------------------
 1 file changed, 10 insertions(+), 22 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index bd89da42b417..929ce28bc657 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -119,32 +119,19 @@ static const struct i2c_device_id pca954x_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, pca954x_id);
 
-/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer()
-   for this as they will try to lock adapter a second time */
 static int pca954x_reg_write(struct i2c_adapter *adap,
 			     struct i2c_client *client, u8 val)
 {
-	int ret = -ENODEV;
-
-	if (adap->algo->master_xfer) {
-		struct i2c_msg msg;
-		char buf[1];
-
-		msg.addr = client->addr;
-		msg.flags = 0;
-		msg.len = 1;
-		buf[0] = val;
-		msg.buf = buf;
-		ret = __i2c_transfer(adap, &msg, 1);
-	} else {
-		union i2c_smbus_data data;
-		ret = adap->algo->smbus_xfer(adap, client->addr,
-					     client->flags,
-					     I2C_SMBUS_WRITE,
-					     val, I2C_SMBUS_BYTE, &data);
-	}
+	union i2c_smbus_data data;
 
-	return ret;
+	if (i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK))
+		return i2c_smbus_xfer(adap, client->addr, client->flags,
+				      I2C_SMBUS_WRITE, val,
+				      I2C_SMBUS_QUICK, NULL);
+	else
+		return i2c_smbus_xfer(adap, client->addr, client->flags,
+				      I2C_SMBUS_WRITE, val,
+				      I2C_SMBUS_BYTE, &data);
 }
 
 static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
@@ -227,6 +214,7 @@ static int pca954x_probe(struct i2c_client *client,
 		return -ENODEV;
 	}
 
+	muxc->i2c_controlled = true;
 	muxc->parent = adap;
 	muxc->select = pca954x_select_chan;
 	muxc->deselect = pca954x_deselect_mux;
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH 10/10] i2c: pca954x: get rid of the i2c deadlock workaround
  2016-01-04 15:10 ` [PATCH 10/10] i2c: pca954x: " Peter Rosin
@ 2016-01-04 15:19   ` Lars-Peter Clausen
  2016-01-04 15:45     ` Peter Rosin
  0 siblings, 1 reply; 22+ messages in thread
From: Lars-Peter Clausen @ 2016-01-04 15:19 UTC (permalink / raw)
  To: Peter Rosin, Wolfram Sang
  Cc: Peter Rosin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Peter Korsgaard, Guenter Roeck, linux-i2c,
	devicetree, linux-kernel

On 01/04/2016 04:10 PM, Peter Rosin wrote:
> From: Peter Rosin <peda@axentia.se>
> 
> Signed-off-by: Peter Rosin <peda@axentia.se>

It would be quite good if the commit messaged said why it is now safe to
remove the workaround.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 01/10] i2c-mux: add common core data for every mux instance
  2016-01-04 15:10 ` [PATCH 01/10] i2c-mux: add common core data for every mux instance Peter Rosin
@ 2016-01-04 15:37   ` Guenter Roeck
  2016-01-05  9:05     ` Peter Rosin
  2016-01-04 15:46   ` kbuild test robot
  2016-01-04 15:49   ` kbuild test robot
  2 siblings, 1 reply; 22+ messages in thread
From: Guenter Roeck @ 2016-01-04 15:37 UTC (permalink / raw)
  To: Peter Rosin, Wolfram Sang
  Cc: Peter Rosin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Peter Korsgaard, linux-i2c, devicetree, linux-kernel

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


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 10/10] i2c: pca954x: get rid of the i2c deadlock workaround
  2016-01-04 15:19   ` Lars-Peter Clausen
@ 2016-01-04 15:45     ` Peter Rosin
  0 siblings, 0 replies; 22+ messages in thread
From: Peter Rosin @ 2016-01-04 15:45 UTC (permalink / raw)
  To: Lars-Peter Clausen, Wolfram Sang
  Cc: Peter Rosin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Peter Korsgaard, Guenter Roeck, linux-i2c,
	devicetree, linux-kernel

On 2016-01-04 16:19, Lars-Peter Clausen wrote:
> On 01/04/2016 04:10 PM, Peter Rosin wrote:
>> From: Peter Rosin <peda@axentia.se>
>>
>> Signed-off-by: Peter Rosin <peda@axentia.se>
> 
> It would be quite good if the commit messaged said why it is now safe to
> remove the workaround.

Right, hmm, the two last patches seemed obvious at the time I wrote them,
but now I see a problem.

E.g. if two pca954x devices that depends on being idle when client devices
are not accessed happen to sit on the same bus (perhaps because the muxes
are used to hide a bunch of identical devices), it is indeed not safe to
make this change.

Thanks for making my think, and consider 9/10 and 10/10 dropped.

Cheers,
Peter

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 01/10] i2c-mux: add common core data for every mux instance
  2016-01-04 15:10 ` [PATCH 01/10] i2c-mux: add common core data for every mux instance Peter Rosin
  2016-01-04 15:37   ` Guenter Roeck
@ 2016-01-04 15:46   ` kbuild test robot
  2016-01-04 15:49   ` kbuild test robot
  2 siblings, 0 replies; 22+ messages in thread
From: kbuild test robot @ 2016-01-04 15:46 UTC (permalink / raw)
  To: Peter Rosin
  Cc: kbuild-all, Wolfram Sang, Peter Rosin, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Peter Korsgaard,
	Guenter Roeck, linux-i2c, devicetree, linux-kernel, Peter Rosin

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

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

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 23798 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 01/10] i2c-mux: add common core data for every mux instance
  2016-01-04 15:10 ` [PATCH 01/10] i2c-mux: add common core data for every mux instance Peter Rosin
  2016-01-04 15:37   ` Guenter Roeck
  2016-01-04 15:46   ` kbuild test robot
@ 2016-01-04 15:49   ` kbuild test robot
  2 siblings, 0 replies; 22+ messages in thread
From: kbuild test robot @ 2016-01-04 15:49 UTC (permalink / raw)
  To: Peter Rosin
  Cc: kbuild-all, Wolfram Sang, Peter Rosin, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Peter Korsgaard,
	Guenter Roeck, linux-i2c, devicetree, linux-kernel, Peter Rosin

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

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

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 23016 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 02/10] i2c-mux: move select and deselect ops to i2c_mux_core
  2016-01-04 15:10 ` [PATCH 02/10] i2c-mux: move select and deselect ops to i2c_mux_core Peter Rosin
@ 2016-01-04 15:54   ` kbuild test robot
  2016-01-04 15:56   ` kbuild test robot
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 22+ messages in thread
From: kbuild test robot @ 2016-01-04 15:54 UTC (permalink / raw)
  To: Peter Rosin
  Cc: kbuild-all, Wolfram Sang, Peter Rosin, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Peter Korsgaard,
	Guenter Roeck, linux-i2c, devicetree, linux-kernel, Peter Rosin

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

Hi Peter,

[auto build test ERROR on wsa/i2c/for-next]
[also build test ERROR 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 error/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:53: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/m88ds3103.c:1471:13: warning: passing argument 3 of 'i2c_add_mux_adapter' makes integer from pointer without a cast [-Wint-conversion]
                dev, 0, 0, 0, m88ds3103_select,
                ^
   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:53:21: note: expected 'u32 {aka unsigned int}' but argument is of type 'struct m88ds3103_dev *'
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^
>> drivers/media/dvb-frontends/m88ds3103.c:1470:21: error: too many arguments to function 'i2c_add_mux_adapter'
     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:53:21: note: declared here
    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:53: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:869:4: warning: passing argument 3 of 'i2c_add_mux_adapter' makes integer from pointer without a cast [-Wint-conversion]
       client, 0, 0, 0, rtl2830_select, NULL);
       ^
   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:53:21: note: expected 'u32 {aka unsigned int}' but argument is of type 'struct i2c_client *'
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^
>> drivers/media/dvb-frontends/rtl2830.c:868:17: error: too many arguments to function 'i2c_add_mux_adapter'
     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:53:21: note: declared here
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^

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

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;

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

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 23798 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 02/10] i2c-mux: move select and deselect ops to i2c_mux_core
  2016-01-04 15:10 ` [PATCH 02/10] i2c-mux: move select and deselect ops to i2c_mux_core Peter Rosin
  2016-01-04 15:54   ` kbuild test robot
@ 2016-01-04 15:56   ` kbuild test robot
  2016-01-04 16:01   ` kbuild test robot
  2016-01-04 16:02   ` kbuild test robot
  3 siblings, 0 replies; 22+ messages in thread
From: kbuild test robot @ 2016-01-04 15:56 UTC (permalink / raw)
  To: Peter Rosin
  Cc: kbuild-all, Wolfram Sang, Peter Rosin, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Peter Korsgaard,
	Guenter Roeck, linux-i2c, devicetree, linux-kernel, Peter Rosin

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

Hi Peter,

[auto build test ERROR on wsa/i2c/for-next]
[also build test ERROR 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 error/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:53: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/iio/imu/inv_mpu6050/inv_mpu_core.c:847:12: warning: passing argument 3 of 'i2c_add_mux_adapter' makes integer from pointer without a cast [-Wint-conversion]
               indio_dev,
               ^
   In file included from drivers/iio/imu/inv_mpu6050/inv_mpu_core.c:26:0:
   include/linux/i2c-mux.h:53:21: note: expected 'u32 {aka unsigned int}' but argument is of type 'struct iio_dev *'
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^
>> drivers/iio/imu/inv_mpu6050/inv_mpu_core.c:845:20: error: too many arguments to function 'i2c_add_mux_adapter'
     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:53:21: note: declared here
    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:53: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:1730:49: warning: passing argument 3 of 'i2c_add_mux_adapter' makes integer from pointer without a cast [-Wint-conversion]
      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:53:21: note: expected 'u32 {aka unsigned int}' but argument is of type 'struct i2c_client *'
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^
>> drivers/of/unittest.c:1730:18: error: too many arguments to function 'i2c_add_mux_adapter'
      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:53:21: note: declared here
    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

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);

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

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 23016 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 02/10] i2c-mux: move select and deselect ops to i2c_mux_core
  2016-01-04 15:10 ` [PATCH 02/10] i2c-mux: move select and deselect ops to i2c_mux_core Peter Rosin
  2016-01-04 15:54   ` kbuild test robot
  2016-01-04 15:56   ` kbuild test robot
@ 2016-01-04 16:01   ` kbuild test robot
  2016-01-04 16:02   ` kbuild test robot
  3 siblings, 0 replies; 22+ messages in thread
From: kbuild test robot @ 2016-01-04 16:01 UTC (permalink / raw)
  To: Peter Rosin
  Cc: kbuild-all, Wolfram Sang, Peter Rosin, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Peter Korsgaard,
	Guenter Roeck, linux-i2c, devicetree, linux-kernel, Peter Rosin

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

Hi Peter,

[auto build test ERROR on wsa/i2c/for-next]
[also build test ERROR 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-s4-01042328 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All error/warnings (new ones prefixed by >>):

   drivers/media/dvb-frontends/si2168.c: In function 'si2168_probe':
   drivers/media/dvb-frontends/si2168.c:712: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/si2168_priv.h:23:0,
                    from drivers/media/dvb-frontends/si2168.c:17:
   include/linux/i2c-mux.h:53: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/si2168.c:713:4: warning: passing argument 3 of 'i2c_add_mux_adapter' makes integer from pointer without a cast [-Wint-conversion]
       client, 0, 0, 0, si2168_select, si2168_deselect);
       ^
   In file included from drivers/media/dvb-frontends/si2168_priv.h:23:0,
                    from drivers/media/dvb-frontends/si2168.c:17:
   include/linux/i2c-mux.h:53:21: note: expected 'u32 {aka unsigned int}' but argument is of type 'struct i2c_client *'
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^
>> drivers/media/dvb-frontends/si2168.c:712:17: error: too many arguments to function 'i2c_add_mux_adapter'
     dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev,
                    ^
   In file included from drivers/media/dvb-frontends/si2168_priv.h:23:0,
                    from drivers/media/dvb-frontends/si2168.c:17:
   include/linux/i2c-mux.h:53:21: note: declared here
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^

vim +/i2c_add_mux_adapter +712 drivers/media/dvb-frontends/si2168.c

845f3505 Antti Palosaari 2014-04-10  706  		ret = -ENOMEM;
37b4e43d Olli Salonen    2014-08-05  707  		dev_err(&client->dev, "kzalloc() failed\n");
1ee5e7dd Antti Palosaari 2014-12-05  708  		goto err;
845f3505 Antti Palosaari 2014-04-10  709  	}
845f3505 Antti Palosaari 2014-04-10  710  
845f3505 Antti Palosaari 2014-04-10  711  	/* create mux i2c adapter for tuner */
6307b560 Antti Palosaari 2014-11-25 @712  	dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev,
6307b560 Antti Palosaari 2014-11-25 @713  			client, 0, 0, 0, si2168_select, si2168_deselect);
bd01c766 Antti Palosaari 2014-11-25  714  	if (dev->adapter == NULL) {
4d6efc7a Luis Alves      2014-07-17  715  		ret = -ENODEV;
346d4900 Antti Palosaari 2014-12-05  716  		goto err_kfree;

:::::: The code at line 712 was first introduced by commit
:::::: 6307b560800fd92b915a851186653317460039ad [media] si2168: carry pointer to client instead of state

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

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 22271 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 03/10] i2c-mux: move the slave side adapter management to i2c_mux_core
  2016-01-04 15:10 ` [PATCH 03/10] i2c-mux: move the slave side adapter management " Peter Rosin
@ 2016-01-04 16:02   ` kbuild test robot
  0 siblings, 0 replies; 22+ messages in thread
From: kbuild test robot @ 2016-01-04 16:02 UTC (permalink / raw)
  To: Peter Rosin
  Cc: kbuild-all, Wolfram Sang, Peter Rosin, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Peter Korsgaard,
	Guenter Roeck, linux-i2c, devicetree, linux-kernel, Peter Rosin

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

Hi Peter,

[auto build test ERROR on wsa/i2c/for-next]
[also build test ERROR 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 error/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:58:5: note: expected 'struct i2c_mux_core *' but argument is of type 'struct i2c_adapter *'
    int i2c_add_mux_adapter(struct i2c_mux_core *muxc,
        ^
   drivers/media/dvb-frontends/m88ds3103.c:1471:13: warning: passing argument 3 of 'i2c_add_mux_adapter' makes integer from pointer without a cast [-Wint-conversion]
                dev, 0, 0, 0, m88ds3103_select,
                ^
   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:58:5: note: expected 'u32 {aka unsigned int}' but argument is of type 'struct m88ds3103_dev *'
    int i2c_add_mux_adapter(struct i2c_mux_core *muxc,
        ^
   drivers/media/dvb-frontends/m88ds3103.c:1470:21: error: too many arguments to function 'i2c_add_mux_adapter'
     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:58:5: note: declared here
    int i2c_add_mux_adapter(struct i2c_mux_core *muxc,
        ^
>> drivers/media/dvb-frontends/m88ds3103.c:1470:19: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
     dev->i2c_adapter = i2c_add_mux_adapter(client->adapter, &client->dev,
                      ^
   drivers/media/dvb-frontends/m88ds3103.c: In function 'm88ds3103_remove':
>> drivers/media/dvb-frontends/m88ds3103.c:1505:2: error: implicit declaration of function 'i2c_del_mux_adapter' [-Werror=implicit-function-declaration]
     i2c_del_mux_adapter(dev->i2c_adapter);
     ^
   cc1: some warnings being treated as errors
--
   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:58:5: note: expected 'struct i2c_mux_core *' but argument is of type 'struct i2c_adapter *'
    int i2c_add_mux_adapter(struct i2c_mux_core *muxc,
        ^
   drivers/media/dvb-frontends/rtl2830.c:869:4: warning: passing argument 3 of 'i2c_add_mux_adapter' makes integer from pointer without a cast [-Wint-conversion]
       client, 0, 0, 0, rtl2830_select, NULL);
       ^
   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:58:5: note: expected 'u32 {aka unsigned int}' but argument is of type 'struct i2c_client *'
    int i2c_add_mux_adapter(struct i2c_mux_core *muxc,
        ^
   drivers/media/dvb-frontends/rtl2830.c:868:17: error: too many arguments to function 'i2c_add_mux_adapter'
     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:58:5: note: declared here
    int i2c_add_mux_adapter(struct i2c_mux_core *muxc,
        ^
>> drivers/media/dvb-frontends/rtl2830.c:868:15: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
     dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev,
                  ^
   drivers/media/dvb-frontends/rtl2830.c: In function 'rtl2830_remove':
>> drivers/media/dvb-frontends/rtl2830.c:903:2: error: implicit declaration of function 'i2c_del_mux_adapter' [-Werror=implicit-function-declaration]
     i2c_del_mux_adapter(dev->adapter);
     ^
   cc1: some warnings being treated as errors

vim +/i2c_del_mux_adapter +1505 drivers/media/dvb-frontends/m88ds3103.c

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 */
f01919e8f Antti Palosaari 2015-04-16  1479  	memcpy(&dev->fe.ops, &m88ds3103_ops, sizeof(struct dvb_frontend_ops));
f01919e8f Antti Palosaari 2015-04-16  1480  	if (dev->chip_id == M88RS6000_CHIP_ID)
7978b8a1b Antti Palosaari 2015-04-16  1481  		strncpy(dev->fe.ops.info.name, "Montage Technology M88RS6000",
7978b8a1b Antti Palosaari 2015-04-16  1482  			sizeof(dev->fe.ops.info.name));
f01919e8f Antti Palosaari 2015-04-16  1483  	if (!pdata->attach_in_use)
f01919e8f Antti Palosaari 2015-04-16  1484  		dev->fe.ops.release = NULL;
f01919e8f Antti Palosaari 2015-04-16  1485  	dev->fe.demodulator_priv = dev;
f01919e8f Antti Palosaari 2015-04-16  1486  	i2c_set_clientdata(client, dev);
f01919e8f Antti Palosaari 2015-04-16  1487  
f01919e8f Antti Palosaari 2015-04-16  1488  	/* setup callbacks */
f01919e8f Antti Palosaari 2015-04-16  1489  	pdata->get_dvb_frontend = m88ds3103_get_dvb_frontend;
f01919e8f Antti Palosaari 2015-04-16  1490  	pdata->get_i2c_adapter = m88ds3103_get_i2c_adapter;
f01919e8f Antti Palosaari 2015-04-16  1491  	return 0;
f01919e8f Antti Palosaari 2015-04-16  1492  err_kfree:
f01919e8f Antti Palosaari 2015-04-16  1493  	kfree(dev);
395d00d1c Antti Palosaari 2013-02-25  1494  err:
f01919e8f Antti Palosaari 2015-04-16  1495  	dev_dbg(&client->dev, "failed=%d\n", ret);
f01919e8f Antti Palosaari 2015-04-16  1496  	return ret;
395d00d1c Antti Palosaari 2013-02-25  1497  }
395d00d1c Antti Palosaari 2013-02-25  1498  
f01919e8f Antti Palosaari 2015-04-16  1499  static int m88ds3103_remove(struct i2c_client *client)
f01919e8f Antti Palosaari 2015-04-16  1500  {
7978b8a1b Antti Palosaari 2015-04-16  1501  	struct m88ds3103_dev *dev = i2c_get_clientdata(client);
395d00d1c Antti Palosaari 2013-02-25  1502  
f01919e8f Antti Palosaari 2015-04-16  1503  	dev_dbg(&client->dev, "\n");
395d00d1c Antti Palosaari 2013-02-25  1504  
f01919e8f Antti Palosaari 2015-04-16 @1505  	i2c_del_mux_adapter(dev->i2c_adapter);
395d00d1c Antti Palosaari 2013-02-25  1506  
f01919e8f Antti Palosaari 2015-04-16  1507  	kfree(dev);
f01919e8f Antti Palosaari 2015-04-16  1508  	return 0;

:::::: The code at line 1505 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

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 23798 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 02/10] i2c-mux: move select and deselect ops to i2c_mux_core
  2016-01-04 15:10 ` [PATCH 02/10] i2c-mux: move select and deselect ops to i2c_mux_core Peter Rosin
                     ` (2 preceding siblings ...)
  2016-01-04 16:01   ` kbuild test robot
@ 2016-01-04 16:02   ` kbuild test robot
  3 siblings, 0 replies; 22+ messages in thread
From: kbuild test robot @ 2016-01-04 16:02 UTC (permalink / raw)
  To: Peter Rosin
  Cc: kbuild-all, Wolfram Sang, Peter Rosin, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Peter Korsgaard,
	Guenter Roeck, linux-i2c, devicetree, linux-kernel, Peter Rosin

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
reproduce:
        # apt-get install sparse
        make ARCH=x86_64 allmodconfig
        make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

   include/linux/compiler.h:228:8: sparse: attribute 'no_sanitize_address': unknown attribute
>> drivers/iio/imu/inv_mpu6050/inv_mpu_core.c:845:46: sparse: too many arguments for function i2c_add_mux_adapter
   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:53: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/iio/imu/inv_mpu6050/inv_mpu_core.c:847:12: warning: passing argument 3 of 'i2c_add_mux_adapter' makes integer from pointer without a cast [-Wint-conversion]
               indio_dev,
               ^
   In file included from drivers/iio/imu/inv_mpu6050/inv_mpu_core.c:26:0:
   include/linux/i2c-mux.h:53:21: note: expected 'u32 {aka unsigned int}' but argument is of type 'struct iio_dev *'
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^
   drivers/iio/imu/inv_mpu6050/inv_mpu_core.c:845:20: error: too many arguments to function 'i2c_add_mux_adapter'
     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:53:21: note: declared here
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^
--
   include/linux/compiler.h:228:8: sparse: attribute 'no_sanitize_address': unknown attribute
>> drivers/media/dvb-frontends/si2168.c:712:43: sparse: too many arguments for function i2c_add_mux_adapter
   drivers/media/dvb-frontends/si2168.c: In function 'si2168_probe':
   drivers/media/dvb-frontends/si2168.c:712: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/si2168_priv.h:23:0,
                    from drivers/media/dvb-frontends/si2168.c:17:
   include/linux/i2c-mux.h:53: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/si2168.c:713:4: warning: passing argument 3 of 'i2c_add_mux_adapter' makes integer from pointer without a cast [-Wint-conversion]
       client, 0, 0, 0, si2168_select, si2168_deselect);
       ^
   In file included from drivers/media/dvb-frontends/si2168_priv.h:23:0,
                    from drivers/media/dvb-frontends/si2168.c:17:
   include/linux/i2c-mux.h:53:21: note: expected 'u32 {aka unsigned int}' but argument is of type 'struct i2c_client *'
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^
   drivers/media/dvb-frontends/si2168.c:712:17: error: too many arguments to function 'i2c_add_mux_adapter'
     dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev,
                    ^
   In file included from drivers/media/dvb-frontends/si2168_priv.h:23:0,
                    from drivers/media/dvb-frontends/si2168.c:17:
   include/linux/i2c-mux.h:53:21: note: declared here
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^
--
   include/linux/compiler.h:228:8: sparse: attribute 'no_sanitize_address': unknown attribute
>> drivers/media/dvb-frontends/m88ds3103.c:1470:47: sparse: too many arguments for function i2c_add_mux_adapter
   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:53: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/m88ds3103.c:1471:13: warning: passing argument 3 of 'i2c_add_mux_adapter' makes integer from pointer without a cast [-Wint-conversion]
                dev, 0, 0, 0, m88ds3103_select,
                ^
   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:53:21: note: expected 'u32 {aka unsigned int}' but argument is of type 'struct m88ds3103_dev *'
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^
   drivers/media/dvb-frontends/m88ds3103.c:1470:21: error: too many arguments to function 'i2c_add_mux_adapter'
     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:53:21: note: declared here
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^
--
   include/linux/compiler.h:228:8: sparse: attribute 'no_sanitize_address': unknown attribute
>> drivers/media/dvb-frontends/rtl2830.c:868:43: sparse: too many arguments for function i2c_add_mux_adapter
   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:53: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:869:4: warning: passing argument 3 of 'i2c_add_mux_adapter' makes integer from pointer without a cast [-Wint-conversion]
       client, 0, 0, 0, rtl2830_select, NULL);
       ^
   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:53:21: note: expected 'u32 {aka unsigned int}' but argument is of type 'struct i2c_client *'
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^
   drivers/media/dvb-frontends/rtl2830.c:868:17: error: too many arguments to function 'i2c_add_mux_adapter'
     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:53:21: note: declared here
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^
--
   include/linux/compiler.h:228:8: sparse: attribute 'no_sanitize_address': unknown attribute
>> drivers/media/dvb-frontends/rtl2832.c:1265:53: sparse: too many arguments for function i2c_add_mux_adapter
   drivers/media/dvb-frontends/rtl2832.c: In function 'rtl2832_probe':
   drivers/media/dvb-frontends/rtl2832.c:1265:47: warning: passing argument 1 of 'i2c_add_mux_adapter' from incompatible pointer type [-Wincompatible-pointer-types]
     dev->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, dev,
                                                  ^
   In file included from drivers/media/dvb-frontends/rtl2832.h:26:0,
                    from drivers/media/dvb-frontends/rtl2832_priv.h:31,
                    from drivers/media/dvb-frontends/rtl2832.c:22:
   include/linux/i2c-mux.h:53: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/rtl2832.c:1265:63: warning: passing argument 3 of 'i2c_add_mux_adapter' makes integer from pointer without a cast [-Wint-conversion]
     dev->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, dev,
                                                                  ^
   In file included from drivers/media/dvb-frontends/rtl2832.h:26:0,
                    from drivers/media/dvb-frontends/rtl2832_priv.h:31,
                    from drivers/media/dvb-frontends/rtl2832.c:22:
   include/linux/i2c-mux.h:53:21: note: expected 'u32 {aka unsigned int}' but argument is of type 'struct rtl2832_dev *'
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^
   drivers/media/dvb-frontends/rtl2832.c:1265:27: error: too many arguments to function 'i2c_add_mux_adapter'
     dev->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, dev,
                              ^
   In file included from drivers/media/dvb-frontends/rtl2832.h:26:0,
                    from drivers/media/dvb-frontends/rtl2832_priv.h:31,
                    from drivers/media/dvb-frontends/rtl2832.c:22:
   include/linux/i2c-mux.h:53:21: note: declared here
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^
--
   include/linux/compiler.h:228:8: sparse: attribute 'no_sanitize_address': unknown attribute
>> drivers/media/usb/cx231xx/cx231xx-i2c.c:574:56: sparse: too many arguments for function i2c_add_mux_adapter
   drivers/media/usb/cx231xx/cx231xx-i2c.c: In function 'cx231xx_i2c_mux_register':
   drivers/media/usb/cx231xx/cx231xx-i2c.c:574:50: warning: passing argument 1 of 'i2c_add_mux_adapter' from incompatible pointer type [-Wincompatible-pointer-types]
     dev->i2c_mux_adap[mux_no] = i2c_add_mux_adapter(i2c_parent,
                                                     ^
   In file included from drivers/media/usb/cx231xx/cx231xx-i2c.c:27:0:
   include/linux/i2c-mux.h:53: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/usb/cx231xx/cx231xx-i2c.c:576:5: warning: passing argument 3 of 'i2c_add_mux_adapter' makes integer from pointer without a cast [-Wint-conversion]
        dev /* mux_priv */,
        ^
   In file included from drivers/media/usb/cx231xx/cx231xx-i2c.c:27:0:
   include/linux/i2c-mux.h:53:21: note: expected 'u32 {aka unsigned int}' but argument is of type 'struct cx231xx *'
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^
   drivers/media/usb/cx231xx/cx231xx-i2c.c:574:30: error: too many arguments to function 'i2c_add_mux_adapter'
     dev->i2c_mux_adap[mux_no] = i2c_add_mux_adapter(i2c_parent,
                                 ^
   In file included from drivers/media/usb/cx231xx/cx231xx-i2c.c:27:0:
   include/linux/i2c-mux.h:53:21: note: declared here
    struct i2c_adapter *i2c_add_mux_adapter(struct i2c_mux_core *muxc,
                        ^

vim +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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 01/10] i2c-mux: add common core data for every mux instance
  2016-01-04 15:37   ` Guenter Roeck
@ 2016-01-05  9:05     ` Peter Rosin
  0 siblings, 0 replies; 22+ messages in thread
From: Peter Rosin @ 2016-01-05  9:05 UTC (permalink / raw)
  To: Guenter Roeck, Wolfram Sang
  Cc: Peter Rosin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Peter Korsgaard, linux-i2c, devicetree, linux-kernel

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2016-01-05  9:05 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-04 15:10 [PATCH 00/10] i2c mux cleanup and locking update Peter Rosin
2016-01-04 15:10 ` [PATCH 01/10] i2c-mux: add common core data for every mux instance Peter Rosin
2016-01-04 15:37   ` Guenter Roeck
2016-01-05  9:05     ` Peter Rosin
2016-01-04 15:46   ` kbuild test robot
2016-01-04 15:49   ` kbuild test robot
2016-01-04 15:10 ` [PATCH 02/10] i2c-mux: move select and deselect ops to i2c_mux_core Peter Rosin
2016-01-04 15:54   ` kbuild test robot
2016-01-04 15:56   ` kbuild test robot
2016-01-04 16:01   ` kbuild test robot
2016-01-04 16:02   ` kbuild test robot
2016-01-04 15:10 ` [PATCH 03/10] i2c-mux: move the slave side adapter management " Peter Rosin
2016-01-04 16:02   ` kbuild test robot
2016-01-04 15:10 ` [PATCH 04/10] i2c-mux: remove the mux dev pointer from the mux per channel data Peter Rosin
2016-01-04 15:10 ` [PATCH 05/10] i2c-mux: pinctrl: get rid of the driver private struct device pointer Peter Rosin
2016-01-04 15:10 ` [PATCH 06/10] i2c: allow adapter drivers to override the adapter locking Peter Rosin
2016-01-04 15:10 ` [PATCH 07/10] i2c: muxes always lock the parent adapter Peter Rosin
2016-01-04 15:10 ` [PATCH 08/10] i2c-mux: relax locking of the top i2c adapter during i2c controlled muxing Peter Rosin
2016-01-04 15:10 ` [PATCH 09/10] i2c: pca9541: get rid of the i2c deadlock workaround Peter Rosin
2016-01-04 15:10 ` [PATCH 10/10] i2c: pca954x: " Peter Rosin
2016-01-04 15:19   ` Lars-Peter Clausen
2016-01-04 15:45     ` Peter Rosin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).