diff mbox

[v6,08/24] iio: imu: inv_mpu6050: convert to use an explicit i2c mux core

Message ID 1459673574-11440-9-git-send-email-peda@lysator.liu.se (mailing list archive)
State New, archived
Headers show

Commit Message

Peter Rosin April 3, 2016, 8:52 a.m. UTC
From: Peter Rosin <peda@axentia.se>

Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select/deselect ops to be in terms of the i2c mux core
instead of the child adapter.

Signed-off-by: Peter Rosin <peda@axentia.se>
---
 drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c |  2 +-
 drivers/iio/imu/inv_mpu6050/inv_mpu_core.c |  1 -
 drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c  | 32 +++++++++++++-----------------
 drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h  |  3 ++-
 4 files changed, 17 insertions(+), 21 deletions(-)

Comments

Jonathan Cameron April 3, 2016, 10:51 a.m. UTC | #1
On 03/04/16 09:52, Peter Rosin wrote:
> From: Peter Rosin <peda@axentia.se>
> 
> Allocate an explicit i2c mux core to handle parent and child adapters
> etc. Update the select/deselect ops to be in terms of the i2c mux core
> instead of the child adapter.
> 
> Signed-off-by: Peter Rosin <peda@axentia.se>
I'm mostly fine with this (though one unrelated change seems to have snuck
in).  However, I'm not set up to test it - hence other than fixing the change
you can have my ack, but ideal would be a tested by from someone with
relevant hardware...  However, it looks to be a fairly mechanical change so
if no one is currently setup to test it, then don't let it hold up the
series too long!

Acked-by: Jonathan Cameron <jic23@kernel.org>

Jonathan
> ---
>  drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c |  2 +-
>  drivers/iio/imu/inv_mpu6050/inv_mpu_core.c |  1 -
>  drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c  | 32 +++++++++++++-----------------
>  drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h  |  3 ++-
>  4 files changed, 17 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
> index 2771106fd650..f62b8bd9ad7e 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
> @@ -183,7 +183,7 @@ int inv_mpu_acpi_create_mux_client(struct i2c_client *client)
>  			} else
>  				return 0; /* no secondary addr, which is OK */
>  		}
> -		st->mux_client = i2c_new_device(st->mux_adapter, &info);
> +		st->mux_client = i2c_new_device(st->muxc->adapter[0], &info);
>  		if (!st->mux_client)
>  			return -ENODEV;
>  	}
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> index d192953e9a38..0c2bded2b5b7 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> @@ -23,7 +23,6 @@
>  #include <linux/kfifo.h>
>  #include <linux/spinlock.h>
>  #include <linux/iio/iio.h>
> -#include <linux/i2c-mux.h>
>  #include <linux/acpi.h>
>  #include "inv_mpu_iio.h"
>  
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
> index f581256d9d4c..0d429d788106 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
> @@ -15,7 +15,6 @@
>  #include <linux/delay.h>
>  #include <linux/err.h>
>  #include <linux/i2c.h>
> -#include <linux/i2c-mux.h>
>  #include <linux/iio/iio.h>
>  #include <linux/module.h>
>  #include "inv_mpu_iio.h"
> @@ -52,10 +51,9 @@ static int inv_mpu6050_write_reg_unlocked(struct i2c_client *client,
>  	return 0;
>  }
>  
> -static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv,
> -				     u32 chan_id)
> +static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
>  {
> -	struct i2c_client *client = mux_priv;
> +	struct i2c_client *client = i2c_mux_priv(muxc);
>  	struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);
>  	struct inv_mpu6050_state *st = iio_priv(indio_dev);
>  	int ret = 0;
> @@ -84,10 +82,9 @@ write_error:
>  	return ret;
>  }
>  
> -static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap,
> -				       void *mux_priv, u32 chan_id)
> +static int inv_mpu6050_deselect_bypass(struct i2c_mux_core *muxc, u32 chan_id)
>  {
> -	struct i2c_client *client = mux_priv;
> +	struct i2c_client *client = i2c_mux_priv(muxc);
>  	struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);
>  	struct inv_mpu6050_state *st = iio_priv(indio_dev);
>  
> @@ -136,16 +133,15 @@ static int inv_mpu_probe(struct i2c_client *client,
>  		return result;
>  
>  	st = iio_priv(dev_get_drvdata(&client->dev));
> -	st->mux_adapter = i2c_add_mux_adapter(client->adapter,
> -					      &client->dev,
> -					      client,
> -					      0, 0, 0,
> -					      inv_mpu6050_select_bypass,
> -					      inv_mpu6050_deselect_bypass);
> -	if (!st->mux_adapter) {
> -		result = -ENODEV;
> +	st->muxc = i2c_mux_one_adapter(client->adapter, &client->dev, 0, 0,
> +				       0, 0, 0,
> +				       inv_mpu6050_select_bypass,
> +				       inv_mpu6050_deselect_bypass);
> +	if (IS_ERR(st->muxc)) {
> +		result = PTR_ERR(st->muxc);
>  		goto out_unreg_device;
>  	}
> +	st->muxc->priv = client;
>  
>  	result = inv_mpu_acpi_create_mux_client(client);
>  	if (result)
> @@ -154,7 +150,7 @@ static int inv_mpu_probe(struct i2c_client *client,
>  	return 0;
>  
>  out_del_mux:
> -	i2c_del_mux_adapter(st->mux_adapter);
> +	i2c_mux_del_adapters(st->muxc);
>  out_unreg_device:
>  	inv_mpu_core_remove(&client->dev);
>  	return result;
> @@ -162,11 +158,11 @@ out_unreg_device:
>  
>  static int inv_mpu_remove(struct i2c_client *client)
>  {
> -	struct iio_dev *indio_dev = i2c_get_clientdata(client);
> +	struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);
Why this change?  Seems unrelated.
>  	struct inv_mpu6050_state *st = iio_priv(indio_dev);
>  
>  	inv_mpu_acpi_delete_mux_client(client);
> -	i2c_del_mux_adapter(st->mux_adapter);
> +	i2c_mux_del_adapters(st->muxc);
>  
>  	return inv_mpu_core_remove(&client->dev);
>  }
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> index e302a49703bf..bb3cef6d7059 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> @@ -11,6 +11,7 @@
>  * GNU General Public License for more details.
>  */
>  #include <linux/i2c.h>
> +#include <linux/i2c-mux.h>
>  #include <linux/kfifo.h>
>  #include <linux/spinlock.h>
>  #include <linux/iio/iio.h>
> @@ -127,7 +128,7 @@ struct inv_mpu6050_state {
>  	const struct inv_mpu6050_hw *hw;
>  	enum   inv_devices chip_type;
>  	spinlock_t time_stamp_lock;
> -	struct i2c_adapter *mux_adapter;
> +	struct i2c_mux_core *muxc;
>  	struct i2c_client *mux_client;
>  	unsigned int powerup_count;
>  	struct inv_mpu6050_platform_data plat_data;
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Peter Rosin April 3, 2016, 11:51 a.m. UTC | #2
On 2016-04-03 12:51, Jonathan Cameron wrote:
> On 03/04/16 09:52, Peter Rosin wrote:
>> From: Peter Rosin <peda@axentia.se>
>>
>> Allocate an explicit i2c mux core to handle parent and child adapters
>> etc. Update the select/deselect ops to be in terms of the i2c mux core
>> instead of the child adapter.
>>
>> Signed-off-by: Peter Rosin <peda@axentia.se>
> I'm mostly fine with this (though one unrelated change seems to have snuck
> in).  However, I'm not set up to test it - hence other than fixing the change
> you can have my ack, but ideal would be a tested by from someone with
> relevant hardware...  However, it looks to be a fairly mechanical change so
> if no one is currently setup to test it, then don't let it hold up the
> series too long!
> 
> Acked-by: Jonathan Cameron <jic23@kernel.org>

Thanks for your acks!

> Jonathan
>> ---
>>  drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c |  2 +-
>>  drivers/iio/imu/inv_mpu6050/inv_mpu_core.c |  1 -
>>  drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c  | 32 +++++++++++++-----------------
>>  drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h  |  3 ++-
>>  4 files changed, 17 insertions(+), 21 deletions(-)
>>
>> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
>> index 2771106fd650..f62b8bd9ad7e 100644
>> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
>> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
>> @@ -183,7 +183,7 @@ int inv_mpu_acpi_create_mux_client(struct i2c_client *client)
>>  			} else
>>  				return 0; /* no secondary addr, which is OK */
>>  		}
>> -		st->mux_client = i2c_new_device(st->mux_adapter, &info);
>> +		st->mux_client = i2c_new_device(st->muxc->adapter[0], &info);
>>  		if (!st->mux_client)
>>  			return -ENODEV;
>>  	}
>> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
>> index d192953e9a38..0c2bded2b5b7 100644
>> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
>> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
>> @@ -23,7 +23,6 @@
>>  #include <linux/kfifo.h>
>>  #include <linux/spinlock.h>
>>  #include <linux/iio/iio.h>
>> -#include <linux/i2c-mux.h>
>>  #include <linux/acpi.h>
>>  #include "inv_mpu_iio.h"
>>  
>> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
>> index f581256d9d4c..0d429d788106 100644
>> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
>> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
>> @@ -15,7 +15,6 @@
>>  #include <linux/delay.h>
>>  #include <linux/err.h>
>>  #include <linux/i2c.h>
>> -#include <linux/i2c-mux.h>
>>  #include <linux/iio/iio.h>
>>  #include <linux/module.h>
>>  #include "inv_mpu_iio.h"
>> @@ -52,10 +51,9 @@ static int inv_mpu6050_write_reg_unlocked(struct i2c_client *client,
>>  	return 0;
>>  }
>>  
>> -static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv,
>> -				     u32 chan_id)
>> +static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
>>  {
>> -	struct i2c_client *client = mux_priv;
>> +	struct i2c_client *client = i2c_mux_priv(muxc);
>>  	struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);

Here, the existing code uses drv_get_drvdata to get from i2c_client to iio_dev...

>>  	struct inv_mpu6050_state *st = iio_priv(indio_dev);
>>  	int ret = 0;
>> @@ -84,10 +82,9 @@ write_error:
>>  	return ret;
>>  }
>>  
>> -static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap,
>> -				       void *mux_priv, u32 chan_id)
>> +static int inv_mpu6050_deselect_bypass(struct i2c_mux_core *muxc, u32 chan_id)
>>  {
>> -	struct i2c_client *client = mux_priv;
>> +	struct i2c_client *client = i2c_mux_priv(muxc);
>>  	struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);

...and here too...

>>  	struct inv_mpu6050_state *st = iio_priv(indio_dev);
>>  
>> @@ -136,16 +133,15 @@ static int inv_mpu_probe(struct i2c_client *client,
>>  		return result;
>>  
>>  	st = iio_priv(dev_get_drvdata(&client->dev));
>> -	st->mux_adapter = i2c_add_mux_adapter(client->adapter,
>> -					      &client->dev,
>> -					      client,
>> -					      0, 0, 0,
>> -					      inv_mpu6050_select_bypass,
>> -					      inv_mpu6050_deselect_bypass);
>> -	if (!st->mux_adapter) {
>> -		result = -ENODEV;
>> +	st->muxc = i2c_mux_one_adapter(client->adapter, &client->dev, 0, 0,
>> +				       0, 0, 0,
>> +				       inv_mpu6050_select_bypass,
>> +				       inv_mpu6050_deselect_bypass);
>> +	if (IS_ERR(st->muxc)) {
>> +		result = PTR_ERR(st->muxc);
>>  		goto out_unreg_device;
>>  	}
>> +	st->muxc->priv = client;
>>  
>>  	result = inv_mpu_acpi_create_mux_client(client);
>>  	if (result)
>> @@ -154,7 +150,7 @@ static int inv_mpu_probe(struct i2c_client *client,
>>  	return 0;
>>  
>>  out_del_mux:
>> -	i2c_del_mux_adapter(st->mux_adapter);
>> +	i2c_mux_del_adapters(st->muxc);
>>  out_unreg_device:
>>  	inv_mpu_core_remove(&client->dev);
>>  	return result;
>> @@ -162,11 +158,11 @@ out_unreg_device:
>>  
>>  static int inv_mpu_remove(struct i2c_client *client)
>>  {
>> -	struct iio_dev *indio_dev = i2c_get_clientdata(client);
>> +	struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);
> Why this change?  Seems unrelated.

...which is why I made this change. Maybe a bad call, but the inconsistency
disturbed me and I was changing the function anyway. I could split it out
to its own commit I suppose, or should I just not bother at all?

Cheers,
Peter

>>  	struct inv_mpu6050_state *st = iio_priv(indio_dev);
>>  
>>  	inv_mpu_acpi_delete_mux_client(client);
>> -	i2c_del_mux_adapter(st->mux_adapter);
>> +	i2c_mux_del_adapters(st->muxc);
>>  
>>  	return inv_mpu_core_remove(&client->dev);
>>  }
>> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
>> index e302a49703bf..bb3cef6d7059 100644
>> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
>> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
>> @@ -11,6 +11,7 @@
>>  * GNU General Public License for more details.
>>  */
>>  #include <linux/i2c.h>
>> +#include <linux/i2c-mux.h>
>>  #include <linux/kfifo.h>
>>  #include <linux/spinlock.h>
>>  #include <linux/iio/iio.h>
>> @@ -127,7 +128,7 @@ struct inv_mpu6050_state {
>>  	const struct inv_mpu6050_hw *hw;
>>  	enum   inv_devices chip_type;
>>  	spinlock_t time_stamp_lock;
>> -	struct i2c_adapter *mux_adapter;
>> +	struct i2c_mux_core *muxc;
>>  	struct i2c_client *mux_client;
>>  	unsigned int powerup_count;
>>  	struct inv_mpu6050_platform_data plat_data;
>>
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jonathan Cameron April 10, 2016, 2:12 p.m. UTC | #3
On 03/04/16 12:51, Peter Rosin wrote:
> On 2016-04-03 12:51, Jonathan Cameron wrote:
>> On 03/04/16 09:52, Peter Rosin wrote:
>>> From: Peter Rosin <peda@axentia.se>
>>>
>>> Allocate an explicit i2c mux core to handle parent and child adapters
>>> etc. Update the select/deselect ops to be in terms of the i2c mux core
>>> instead of the child adapter.
>>>
>>> Signed-off-by: Peter Rosin <peda@axentia.se>
>> I'm mostly fine with this (though one unrelated change seems to have snuck
>> in).  However, I'm not set up to test it - hence other than fixing the change
>> you can have my ack, but ideal would be a tested by from someone with
>> relevant hardware...  However, it looks to be a fairly mechanical change so
>> if no one is currently setup to test it, then don't let it hold up the
>> series too long!
>>
>> Acked-by: Jonathan Cameron <jic23@kernel.org>
> 
> Thanks for your acks!
> 
>> Jonathan
>>> ---
>>>  drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c |  2 +-
>>>  drivers/iio/imu/inv_mpu6050/inv_mpu_core.c |  1 -
>>>  drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c  | 32 +++++++++++++-----------------
>>>  drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h  |  3 ++-
>>>  4 files changed, 17 insertions(+), 21 deletions(-)
>>>
>>> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
>>> index 2771106fd650..f62b8bd9ad7e 100644
>>> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
>>> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
>>> @@ -183,7 +183,7 @@ int inv_mpu_acpi_create_mux_client(struct i2c_client *client)
>>>  			} else
>>>  				return 0; /* no secondary addr, which is OK */
>>>  		}
>>> -		st->mux_client = i2c_new_device(st->mux_adapter, &info);
>>> +		st->mux_client = i2c_new_device(st->muxc->adapter[0], &info);
>>>  		if (!st->mux_client)
>>>  			return -ENODEV;
>>>  	}
>>> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
>>> index d192953e9a38..0c2bded2b5b7 100644
>>> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
>>> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
>>> @@ -23,7 +23,6 @@
>>>  #include <linux/kfifo.h>
>>>  #include <linux/spinlock.h>
>>>  #include <linux/iio/iio.h>
>>> -#include <linux/i2c-mux.h>
>>>  #include <linux/acpi.h>
>>>  #include "inv_mpu_iio.h"
>>>  
>>> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
>>> index f581256d9d4c..0d429d788106 100644
>>> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
>>> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
>>> @@ -15,7 +15,6 @@
>>>  #include <linux/delay.h>
>>>  #include <linux/err.h>
>>>  #include <linux/i2c.h>
>>> -#include <linux/i2c-mux.h>
>>>  #include <linux/iio/iio.h>
>>>  #include <linux/module.h>
>>>  #include "inv_mpu_iio.h"
>>> @@ -52,10 +51,9 @@ static int inv_mpu6050_write_reg_unlocked(struct i2c_client *client,
>>>  	return 0;
>>>  }
>>>  
>>> -static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv,
>>> -				     u32 chan_id)
>>> +static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
>>>  {
>>> -	struct i2c_client *client = mux_priv;
>>> +	struct i2c_client *client = i2c_mux_priv(muxc);
>>>  	struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);
> 
> Here, the existing code uses drv_get_drvdata to get from i2c_client to iio_dev...
> 
>>>  	struct inv_mpu6050_state *st = iio_priv(indio_dev);
>>>  	int ret = 0;
>>> @@ -84,10 +82,9 @@ write_error:
>>>  	return ret;
>>>  }
>>>  
>>> -static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap,
>>> -				       void *mux_priv, u32 chan_id)
>>> +static int inv_mpu6050_deselect_bypass(struct i2c_mux_core *muxc, u32 chan_id)
>>>  {
>>> -	struct i2c_client *client = mux_priv;
>>> +	struct i2c_client *client = i2c_mux_priv(muxc);
>>>  	struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);
> 
> ...and here too...
> 
>>>  	struct inv_mpu6050_state *st = iio_priv(indio_dev);
>>>  
>>> @@ -136,16 +133,15 @@ static int inv_mpu_probe(struct i2c_client *client,
>>>  		return result;
>>>  
>>>  	st = iio_priv(dev_get_drvdata(&client->dev));
>>> -	st->mux_adapter = i2c_add_mux_adapter(client->adapter,
>>> -					      &client->dev,
>>> -					      client,
>>> -					      0, 0, 0,
>>> -					      inv_mpu6050_select_bypass,
>>> -					      inv_mpu6050_deselect_bypass);
>>> -	if (!st->mux_adapter) {
>>> -		result = -ENODEV;
>>> +	st->muxc = i2c_mux_one_adapter(client->adapter, &client->dev, 0, 0,
>>> +				       0, 0, 0,
>>> +				       inv_mpu6050_select_bypass,
>>> +				       inv_mpu6050_deselect_bypass);
>>> +	if (IS_ERR(st->muxc)) {
>>> +		result = PTR_ERR(st->muxc);
>>>  		goto out_unreg_device;
>>>  	}
>>> +	st->muxc->priv = client;
>>>  
>>>  	result = inv_mpu_acpi_create_mux_client(client);
>>>  	if (result)
>>> @@ -154,7 +150,7 @@ static int inv_mpu_probe(struct i2c_client *client,
>>>  	return 0;
>>>  
>>>  out_del_mux:
>>> -	i2c_del_mux_adapter(st->mux_adapter);
>>> +	i2c_mux_del_adapters(st->muxc);
>>>  out_unreg_device:
>>>  	inv_mpu_core_remove(&client->dev);
>>>  	return result;
>>> @@ -162,11 +158,11 @@ out_unreg_device:
>>>  
>>>  static int inv_mpu_remove(struct i2c_client *client)
>>>  {
>>> -	struct iio_dev *indio_dev = i2c_get_clientdata(client);
>>> +	struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);
>> Why this change?  Seems unrelated.
> 
> ...which is why I made this change. Maybe a bad call, but the inconsistency
> disturbed me and I was changing the function anyway. I could split it out
> to its own commit I suppose, or should I just not bother at all?
Funny thing is I'd say the i2c_get_clientdata option is the better of the two!

I don't really care though either way.

J
> 
> Cheers,
> Peter
> 
>>>  	struct inv_mpu6050_state *st = iio_priv(indio_dev);
>>>  
>>>  	inv_mpu_acpi_delete_mux_client(client);
>>> -	i2c_del_mux_adapter(st->mux_adapter);
>>> +	i2c_mux_del_adapters(st->muxc);
>>>  
>>>  	return inv_mpu_core_remove(&client->dev);
>>>  }
>>> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
>>> index e302a49703bf..bb3cef6d7059 100644
>>> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
>>> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
>>> @@ -11,6 +11,7 @@
>>>  * GNU General Public License for more details.
>>>  */
>>>  #include <linux/i2c.h>
>>> +#include <linux/i2c-mux.h>
>>>  #include <linux/kfifo.h>
>>>  #include <linux/spinlock.h>
>>>  #include <linux/iio/iio.h>
>>> @@ -127,7 +128,7 @@ struct inv_mpu6050_state {
>>>  	const struct inv_mpu6050_hw *hw;
>>>  	enum   inv_devices chip_type;
>>>  	spinlock_t time_stamp_lock;
>>> -	struct i2c_adapter *mux_adapter;
>>> +	struct i2c_mux_core *muxc;
>>>  	struct i2c_client *mux_client;
>>>  	unsigned int powerup_count;
>>>  	struct inv_mpu6050_platform_data plat_data;
>>>
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Crestez Dan Leonard April 19, 2016, 3:58 p.m. UTC | #4
On 04/03/2016 11:52 AM, Peter Rosin wrote:
> From: Peter Rosin <peda@axentia.se>
> 
> Allocate an explicit i2c mux core to handle parent and child adapters
> etc. Update the select/deselect ops to be in terms of the i2c mux core
> instead of the child adapter.
> 
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
> @@ -136,16 +133,15 @@ static int inv_mpu_probe(struct i2c_client *client,
>  		return result;
>  
>  	st = iio_priv(dev_get_drvdata(&client->dev));
> -	st->mux_adapter = i2c_add_mux_adapter(client->adapter,
> -					      &client->dev,
> -					      client,
> -					      0, 0, 0,
> -					      inv_mpu6050_select_bypass,
> -					      inv_mpu6050_deselect_bypass);
> -	if (!st->mux_adapter) {
> -		result = -ENODEV;
> +	st->muxc = i2c_mux_one_adapter(client->adapter, &client->dev, 0, 0,
> +				       0, 0, 0,
> +				       inv_mpu6050_select_bypass,
> +				       inv_mpu6050_deselect_bypass);
> +	if (IS_ERR(st->muxc)) {
> +		result = PTR_ERR(st->muxc);
>  		goto out_unreg_device;
>  	}
> +	st->muxc->priv = client;

I just tested this patch on mpu9150 (combo mpu6050+ak8975) and I got a
crash on probe which looks sort of like this:

[    5.565374] RIP: 0010:[<ffffffff81481aed>] [<ffffffff81481aed>]
mutex_lock+0xd/0x30
[    5.565374] Call Trace:
[    5.565374]  [<ffffffff813be34c>] inv_mpu6050_select_bypass+0x1c/0xa0
...
[    5.565374]  [<ffffffff81392141>] i2c_transfer+0x51/0x90
...
[    5.565374]  [<ffffffff81392cb5>] i2c_smbus_read_i2c_block_data+0x45/0xd0
[    5.565374]  [<ffffffff813bec5a>] ak8975_probe+0x14a/0x5c0
...
[    5.565374]  [<ffffffff813933d8>] i2c_new_device+0x178/0x1e0
[    5.565374]  [<ffffffff8139362d>] of_i2c_register_device+0xdd/0x1a0
[    5.565374]  [<ffffffff8139372b>] of_i2c_register_devices+0x3b/0x60
[    5.565374]  [<ffffffff81393e88>] i2c_register_adapter+0x178/0x410
[    5.565374]  [<ffffffff81394203>] i2c_add_adapter+0x73/0x90
[    5.565374]  [<ffffffff81395f3d>] i2c_mux_add_adapter+0x2ed/0x400
[    5.565374]  [<ffffffff81396091>] i2c_mux_one_adapter+0x41/0x70
[    5.565374]  [<ffffffff813be48a>] inv_mpu_probe+0xba/0x1a0

This happens because muxc->priv is not initialized when probing devices
behind the mux as described by devicetree. This can be easily fixed by
using muxc->dev instead of muxc->priv, or perhaps by calling
i2c_mux_alloc, initializing priv and later doing i2c_mux_add_adapter.

These fixes are driver-specific and other drivers might experience
similar issues. Perhaps i2c_mux_one_adapter should take void *priv just
like old i2c_add_mux_adapter?

After I fix this locally the deadlock when reading from both devices no
longer happens.

--
Regards,
Leonard
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Peter Rosin April 19, 2016, 4:37 p.m. UTC | #5
<hans.verkuil@cisco.com>,Arnd Bergmann <arnd@arndb.de>,Tommi Rantala <tt.rantala@gmail.com>,linux-i2c@vger.kernel.org,linux-doc@vger.kernel.org,linux-iio@vger.kernel.org,linux-media@vger.kernel.org,devicetree@vger.kernel.org
Message-ID: <B09CD200-56D1-4BE0-B567-90CC23507ED5@lysator.liu.se>

On April 19, 2016 5:58:11 PM CEST, Crestez Dan Leonard <leonard.crestez@intel.com> wrote:
> On 04/03/2016 11:52 AM, Peter Rosin wrote:
> > From: Peter Rosin <peda@axentia.se>
> > 
> > Allocate an explicit i2c mux core to handle parent and child
> adapters
> > etc. Update the select/deselect ops to be in terms of the i2c mux
> core
> > instead of the child adapter.
> > 
> > --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
> > +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
> > @@ -136,16 +133,15 @@ static int inv_mpu_probe(struct i2c_client
> *client,
> >  		return result;
> >  
> >  	st = iio_priv(dev_get_drvdata(&client->dev));
> > -	st->mux_adapter = i2c_add_mux_adapter(client->adapter,
> > -					      &client->dev,
> > -					      client,
> > -					      0, 0, 0,
> > -					      inv_mpu6050_select_bypass,
> > -					      inv_mpu6050_deselect_bypass);
> > -	if (!st->mux_adapter) {
> > -		result = -ENODEV;
> > +	st->muxc = i2c_mux_one_adapter(client->adapter, &client->dev, 0,
> 0,
> > +				       0, 0, 0,
> > +				       inv_mpu6050_select_bypass,
> > +				       inv_mpu6050_deselect_bypass);
> > +	if (IS_ERR(st->muxc)) {
> > +		result = PTR_ERR(st->muxc);
> >  		goto out_unreg_device;
> >  	}
> > +	st->muxc->priv = client;
> 
> I just tested this patch on mpu9150 (combo mpu6050+ak8975) and I got a
> crash on probe which looks sort of like this:
> 
> [    5.565374] RIP: 0010:[<ffffffff81481aed>] [<ffffffff81481aed>]
> mutex_lock+0xd/0x30
> [    5.565374] Call Trace:
> [    5.565374]  [<ffffffff813be34c>]
> inv_mpu6050_select_bypass+0x1c/0xa0
> ...
> [    5.565374]  [<ffffffff81392141>] i2c_transfer+0x51/0x90
> ...
> [    5.565374]  [<ffffffff81392cb5>]
> i2c_smbus_read_i2c_block_data+0x45/0xd0
> [    5.565374]  [<ffffffff813bec5a>] ak8975_probe+0x14a/0x5c0
> ...
> [    5.565374]  [<ffffffff813933d8>] i2c_new_device+0x178/0x1e0
> [    5.565374]  [<ffffffff8139362d>] of_i2c_register_device+0xdd/0x1a0
> [    5.565374]  [<ffffffff8139372b>] of_i2c_register_devices+0x3b/0x60
> [    5.565374]  [<ffffffff81393e88>] i2c_register_adapter+0x178/0x410
> [    5.565374]  [<ffffffff81394203>] i2c_add_adapter+0x73/0x90
> [    5.565374]  [<ffffffff81395f3d>] i2c_mux_add_adapter+0x2ed/0x400
> [    5.565374]  [<ffffffff81396091>] i2c_mux_one_adapter+0x41/0x70
> [    5.565374]  [<ffffffff813be48a>] inv_mpu_probe+0xba/0x1a0
> 
> This happens because muxc->priv is not initialized when probing
> devices
> behind the mux as described by devicetree. This can be easily fixed by
> using muxc->dev instead of muxc->priv, or perhaps by calling
> i2c_mux_alloc, initializing priv and later doing i2c_mux_add_adapter.
> 
> These fixes are driver-specific and other drivers might experience
> similar issues. Perhaps i2c_mux_one_adapter should take void *priv
> just
> like old i2c_add_mux_adapter?
> 
> After I fix this locally the deadlock when reading from both devices
> no
> longer happens.
> 
> --
> Regards,
> Leonard

Duh. Obvious now that you point it out. Thanks for catching this!

I will just remove the i2c_mux_one_adapter interface for v7 and
have the affected drivers do i2c_mux_alloc as a separate step
(which was one of your suggested paths forward...)

Thanks again, and sorry for the inconvenience,
Peter

(Written on my phone, sorry for crappy formatting)

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

Patch

diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
index 2771106fd650..f62b8bd9ad7e 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
@@ -183,7 +183,7 @@  int inv_mpu_acpi_create_mux_client(struct i2c_client *client)
 			} else
 				return 0; /* no secondary addr, which is OK */
 		}
-		st->mux_client = i2c_new_device(st->mux_adapter, &info);
+		st->mux_client = i2c_new_device(st->muxc->adapter[0], &info);
 		if (!st->mux_client)
 			return -ENODEV;
 	}
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index d192953e9a38..0c2bded2b5b7 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -23,7 +23,6 @@ 
 #include <linux/kfifo.h>
 #include <linux/spinlock.h>
 #include <linux/iio/iio.h>
-#include <linux/i2c-mux.h>
 #include <linux/acpi.h>
 #include "inv_mpu_iio.h"
 
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
index f581256d9d4c..0d429d788106 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
@@ -15,7 +15,6 @@ 
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
-#include <linux/i2c-mux.h>
 #include <linux/iio/iio.h>
 #include <linux/module.h>
 #include "inv_mpu_iio.h"
@@ -52,10 +51,9 @@  static int inv_mpu6050_write_reg_unlocked(struct i2c_client *client,
 	return 0;
 }
 
-static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv,
-				     u32 chan_id)
+static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
 {
-	struct i2c_client *client = mux_priv;
+	struct i2c_client *client = i2c_mux_priv(muxc);
 	struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);
 	struct inv_mpu6050_state *st = iio_priv(indio_dev);
 	int ret = 0;
@@ -84,10 +82,9 @@  write_error:
 	return ret;
 }
 
-static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap,
-				       void *mux_priv, u32 chan_id)
+static int inv_mpu6050_deselect_bypass(struct i2c_mux_core *muxc, u32 chan_id)
 {
-	struct i2c_client *client = mux_priv;
+	struct i2c_client *client = i2c_mux_priv(muxc);
 	struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);
 	struct inv_mpu6050_state *st = iio_priv(indio_dev);
 
@@ -136,16 +133,15 @@  static int inv_mpu_probe(struct i2c_client *client,
 		return result;
 
 	st = iio_priv(dev_get_drvdata(&client->dev));
-	st->mux_adapter = i2c_add_mux_adapter(client->adapter,
-					      &client->dev,
-					      client,
-					      0, 0, 0,
-					      inv_mpu6050_select_bypass,
-					      inv_mpu6050_deselect_bypass);
-	if (!st->mux_adapter) {
-		result = -ENODEV;
+	st->muxc = i2c_mux_one_adapter(client->adapter, &client->dev, 0, 0,
+				       0, 0, 0,
+				       inv_mpu6050_select_bypass,
+				       inv_mpu6050_deselect_bypass);
+	if (IS_ERR(st->muxc)) {
+		result = PTR_ERR(st->muxc);
 		goto out_unreg_device;
 	}
+	st->muxc->priv = client;
 
 	result = inv_mpu_acpi_create_mux_client(client);
 	if (result)
@@ -154,7 +150,7 @@  static int inv_mpu_probe(struct i2c_client *client,
 	return 0;
 
 out_del_mux:
-	i2c_del_mux_adapter(st->mux_adapter);
+	i2c_mux_del_adapters(st->muxc);
 out_unreg_device:
 	inv_mpu_core_remove(&client->dev);
 	return result;
@@ -162,11 +158,11 @@  out_unreg_device:
 
 static int inv_mpu_remove(struct i2c_client *client)
 {
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);
 	struct inv_mpu6050_state *st = iio_priv(indio_dev);
 
 	inv_mpu_acpi_delete_mux_client(client);
-	i2c_del_mux_adapter(st->mux_adapter);
+	i2c_mux_del_adapters(st->muxc);
 
 	return inv_mpu_core_remove(&client->dev);
 }
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index e302a49703bf..bb3cef6d7059 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -11,6 +11,7 @@ 
 * GNU General Public License for more details.
 */
 #include <linux/i2c.h>
+#include <linux/i2c-mux.h>
 #include <linux/kfifo.h>
 #include <linux/spinlock.h>
 #include <linux/iio/iio.h>
@@ -127,7 +128,7 @@  struct inv_mpu6050_state {
 	const struct inv_mpu6050_hw *hw;
 	enum   inv_devices chip_type;
 	spinlock_t time_stamp_lock;
-	struct i2c_adapter *mux_adapter;
+	struct i2c_mux_core *muxc;
 	struct i2c_client *mux_client;
 	unsigned int powerup_count;
 	struct inv_mpu6050_platform_data plat_data;