Re: [RFC PATCH v2] media: i2c: add SCCB helpers

2018-06-14 Thread Peter Rosin
On 2018-06-14 17:41, Wolfram Sang wrote:
> 
>> So, maybe the easier thing to do is change i2c_lock_adapter to only
>> lock the segment, and then have the callers beneath drivers/i2c/
>> (plus the above mlx90614 driver) that really want to lock the root
>> adapter instead of the segment adapter call a new function named
>> i2c_lock_root (or something like that). Admittedly, that will be
>> a few more trivial changes, but all but one will be under the I2C
>> umbrella and thus require less interaction.
>>
>> Wolfram, what do you think?
> 
> It sounds tempting, yet I am concerned about regressions. From that
> point of view, it is safer to introduce i2c_lock_segment() and convert the
> users which would benefit from that. How many drivers would be affected?

Right, there is also the aspect that changing a function like this
might surprise people. Maybe i2c_lock_adapter should be killed and
all callers changed to one of i2c_lock_segment and i2c_lock_root?
It's not that much churn...

Current callers (I didn't hunt the very latest sources, nor -next)
of i2c_lock_adapter are:

drivers/i2c/i2c-core-slave.c
Locks the adapter during (un)registration of the slave. Should
keep locking the root adapter.

drivers/i2c/busses/i2c-brcmstb.c
Locks the adapter during suspend/resume. Should keep locking
the root adapter.

drivers/i2c/busses/i2c-davinci.c
Locks the adapter if/when the CPU frequency changes. Should
keep locking the root adapter.

drivers/i2c/busses/i2c-gpio.c
Locks the adapter while twiddling the lines from debugfs. Should
keep locking the root adapter.

drivers/i2c/busses/i2c-s3c2410.c
Locks the adapter if/when the CPU frequency changes.Should keep
locking the root adapter.

drivers/i2c/busses/i2c-sprd.c
Locks the adapter during suspend/resume. Should keep locking
the root adapter.

drivers/i2c/busses/i2c-tegra.c
Locks the adapter during suspend/resume. Should keep locking
the root adapter.

drivers/i2c/muxes/i2c-mux-pca9541.c
Locks the adapter during probe to make I2C transfers. Should
only need to lock the segment.

drivers/iio/temperature/mlx90614.c
Mentioned previously up-thread, suspend/resume apparently does
nasty things with the bus. Should probably keep locking the root
adapter.

drivers/char/tpm/tpm_i2c_infineon.c
Does a bunch of __i2c_transfer calls inside the locked regions
(and some sleeping). Should only need to lock the segment.

drivers/input/touchscreen/rohm_bu21023.c
Does a couple of __i2c_transfer calls inside the locked region.
Should only need to lock the segment.

drivers/media/dvb-frontends/af9013.c
Does a one or two __i2c_transfer calls inside the locked regions.
Should only need to lock the segment.

drivers/media/dvb-frontends/drxk_hard.c
This one is a bit hairy. It does all sorts of things inside the
locked region. And it is a bit hard to say if the root adapter
really needs to be locked.

drivers/media/dvb-frontends/rtl2830.c
Does regmap accesses inside the locked regions, with the regmap
ops overridden to use __i2c_transfer. Should only need to lock
the segment.

drivers/media/dvb-frontends/tda1004x.c
Does a bunch of __i2c_transfer calls inside the locked region.
Should only need to lock the segment.

drivers/media/tuners/tda18271-common.c
Seems to opens a gate in conjunction with locking the adapter.
So, I'm a bit uncertain what will happen on the other side of
that gate if there is any stray thing happening on the I2C
bus.

drivers/mfd/88pm860x-i2c.c
Does a bunch of adap->algo->master_xfer calls inside the locked
regions. Should only need to lock the segment (and should probably
be using __i2c_transfer).

So, drxk_hard.c and tda18271-common.c are a bit uncertain. However, since
these drivers do make calls to __i2c_transfer from inside their locked
regions, both drivers will deadlock if the chips sit downstream from a
mux-locked I2C mux. And if they don't, locking the segment and the
adapter are equivalent. So, the risk of regressions are nil AFAICT. Famous
last words...

Cheers,
Peter


Re: [RFC PATCH v2] media: i2c: add SCCB helpers

2018-06-13 Thread Peter Rosin
On 2018-06-12 19:31, Peter Rosin wrote:
> On 2018-06-12 17:34, Akinobu Mita wrote:
>> (This is 2nd version of SCCB helpers patch.  After 1st version was
>> submitted, I sent alternative patch titled "i2c: add I2C_M_FORCE_STOP".
>> But it wasn't accepted because it makes the I2C core code unreadable.
>> I couldn't find out a way to untangle it, so I returned to the original
>> approach.)
>>
>> This adds Serial Camera Control Bus (SCCB) helper functions (sccb_read_byte
>> and sccb_write_byte) that are intended to be used by some of Omnivision
>> sensor drivers.
>>
>> The ov772x driver is going to use these functions in order to make it work
>> with most i2c controllers.
>>
>> As the ov772x device doesn't support repeated starts, this driver currently
>> requires I2C_FUNC_PROTOCOL_MANGLING that is not supported by many i2c
>> controller drivers.
>>
>> With the sccb_read_byte() that issues two separated requests in order to
>> avoid repeated start, the driver doesn't require I2C_FUNC_PROTOCOL_MANGLING.
>>
>> Cc: Sebastian Reichel 
>> Cc: Wolfram Sang 
>> Cc: Jacopo Mondi 
>> Cc: Laurent Pinchart 
>> Cc: Hans Verkuil 
>> Cc: Sakari Ailus 
>> Cc: Mauro Carvalho Chehab 
>> Signed-off-by: Akinobu Mita 
>> ---
>> * v2
>> - Convert all helpers into static inline functions, and remove C source
>>   and Kconfig option.
>> - Acquire i2c adapter lock while issuing two requests for sccb_read_byte
>>
>>  drivers/media/i2c/sccb.h | 74 
>> 
>>  1 file changed, 74 insertions(+)
>>  create mode 100644 drivers/media/i2c/sccb.h
>>
>> diff --git a/drivers/media/i2c/sccb.h b/drivers/media/i2c/sccb.h
>> new file mode 100644
>> index 000..a531fdc
>> --- /dev/null
>> +++ b/drivers/media/i2c/sccb.h
>> @@ -0,0 +1,74 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * Serial Camera Control Bus (SCCB) helper functions
>> + */
>> +
>> +#ifndef __SCCB_H__
>> +#define __SCCB_H__
>> +
>> +#include 
>> +
>> +/**
>> + * sccb_read_byte - Read data from SCCB slave device
>> + * @client: Handle to slave device
>> + * @addr: Register to be read from
>> + *
>> + * This executes the 2-phase write transmission cycle that is followed by a
>> + * 2-phase read transmission cycle, returning negative errno else a data 
>> byte
>> + * received from the device.
>> + */
>> +static inline int sccb_read_byte(struct i2c_client *client, u8 addr)
>> +{
>> +u8 val;
>> +struct i2c_msg msg[] = {
>> +{
>> +.addr = client->addr,
>> +.len = 1,
>> +.buf = ,
>> +},
>> +{
>> +.addr = client->addr,
>> +.flags = I2C_M_RD,
>> +.len = 1,
>> +.buf = ,
>> +},
>> +};
>> +int ret;
>> +int i;
>> +
>> +i2c_lock_adapter(client->adapter);
> 
> I'd say that
> 
>   i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
> 
> is more appropriate. Maybe we should have a i2c_lock_segment helper?

Hmmm, I looked into that and happened to scan the other callers
of i2c_lock_adapter. And, AFAICT, almost all callers outside
drivers/i2c/ would benefit from only locking the segment. The only
exception I could find was in drivers/iio/temperature/mlx90614.c
which seems to want to protect the adapter from trying to use the
I2C bus while the device is in a strange state (I assume it is
somehow causing glitches on the I2C bus as it wakes up).

So, maybe the easier thing to do is change i2c_lock_adapter to only
lock the segment, and then have the callers beneath drivers/i2c/
(plus the above mlx90614 driver) that really want to lock the root
adapter instead of the segment adapter call a new function named
i2c_lock_root (or something like that). Admittedly, that will be
a few more trivial changes, but all but one will be under the I2C
umbrella and thus require less interaction.

Wolfram, what do you think?

Cheers,
Peter

>> +
>> +/* Issue two separated requests in order to avoid repeated start */
>> +for (i = 0; i < 2; i++) {
>> +ret = __i2c_transfer(client->adapter, [i], 1);
>> +if (ret != 1)
>> +break;
>> +}
>> +
>> +i2c_unlock_adapter(client->adapter);
>> +
>> +return i == 2 ? val : ret;
>> +}
>> +
>> +/**
>> + * sccb_write_byte - Write data to SCCB slave device
>> + * @client: Handle to slave device
>> + * @addr: Register to write to
>> + * @data: Value to be written
>> + *
>> + * This executes the SCCB 3-phase write transmission cycle, returning 
>> negative
>> + * errno else zero on success.
>> + */
>> +static inline int sccb_write_byte(struct i2c_client *client, u8 addr, u8 
>> data)
>> +{
>> +int ret;
>> +unsigned char msgbuf[] = { addr, data };
>> +
>> +ret = i2c_master_send(client, msgbuf, 2);
>> +if (ret < 0)
>> +return ret;
>> +
>> +return 0;
>> +}
>> +
>> +#endif /* __SCCB_H__ */
>>
> 



Re: [RFC PATCH v2] media: i2c: add SCCB helpers

2018-06-12 Thread Peter Rosin
On 2018-06-12 17:34, Akinobu Mita wrote:
> (This is 2nd version of SCCB helpers patch.  After 1st version was
> submitted, I sent alternative patch titled "i2c: add I2C_M_FORCE_STOP".
> But it wasn't accepted because it makes the I2C core code unreadable.
> I couldn't find out a way to untangle it, so I returned to the original
> approach.)
> 
> This adds Serial Camera Control Bus (SCCB) helper functions (sccb_read_byte
> and sccb_write_byte) that are intended to be used by some of Omnivision
> sensor drivers.
> 
> The ov772x driver is going to use these functions in order to make it work
> with most i2c controllers.
> 
> As the ov772x device doesn't support repeated starts, this driver currently
> requires I2C_FUNC_PROTOCOL_MANGLING that is not supported by many i2c
> controller drivers.
> 
> With the sccb_read_byte() that issues two separated requests in order to
> avoid repeated start, the driver doesn't require I2C_FUNC_PROTOCOL_MANGLING.
> 
> Cc: Sebastian Reichel 
> Cc: Wolfram Sang 
> Cc: Jacopo Mondi 
> Cc: Laurent Pinchart 
> Cc: Hans Verkuil 
> Cc: Sakari Ailus 
> Cc: Mauro Carvalho Chehab 
> Signed-off-by: Akinobu Mita 
> ---
> * v2
> - Convert all helpers into static inline functions, and remove C source
>   and Kconfig option.
> - Acquire i2c adapter lock while issuing two requests for sccb_read_byte
> 
>  drivers/media/i2c/sccb.h | 74 
> 
>  1 file changed, 74 insertions(+)
>  create mode 100644 drivers/media/i2c/sccb.h
> 
> diff --git a/drivers/media/i2c/sccb.h b/drivers/media/i2c/sccb.h
> new file mode 100644
> index 000..a531fdc
> --- /dev/null
> +++ b/drivers/media/i2c/sccb.h
> @@ -0,0 +1,74 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Serial Camera Control Bus (SCCB) helper functions
> + */
> +
> +#ifndef __SCCB_H__
> +#define __SCCB_H__
> +
> +#include 
> +
> +/**
> + * sccb_read_byte - Read data from SCCB slave device
> + * @client: Handle to slave device
> + * @addr: Register to be read from
> + *
> + * This executes the 2-phase write transmission cycle that is followed by a
> + * 2-phase read transmission cycle, returning negative errno else a data byte
> + * received from the device.
> + */
> +static inline int sccb_read_byte(struct i2c_client *client, u8 addr)
> +{
> + u8 val;
> + struct i2c_msg msg[] = {
> + {
> + .addr = client->addr,
> + .len = 1,
> + .buf = ,
> + },
> + {
> + .addr = client->addr,
> + .flags = I2C_M_RD,
> + .len = 1,
> + .buf = ,
> + },
> + };
> + int ret;
> + int i;
> +
> + i2c_lock_adapter(client->adapter);

I'd say that

i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);

is more appropriate. Maybe we should have a i2c_lock_segment helper?

Cheers,
Peter

> +
> + /* Issue two separated requests in order to avoid repeated start */
> + for (i = 0; i < 2; i++) {
> + ret = __i2c_transfer(client->adapter, [i], 1);
> + if (ret != 1)
> + break;
> + }
> +
> + i2c_unlock_adapter(client->adapter);
> +
> + return i == 2 ? val : ret;
> +}
> +
> +/**
> + * sccb_write_byte - Write data to SCCB slave device
> + * @client: Handle to slave device
> + * @addr: Register to write to
> + * @data: Value to be written
> + *
> + * This executes the SCCB 3-phase write transmission cycle, returning 
> negative
> + * errno else zero on success.
> + */
> +static inline int sccb_write_byte(struct i2c_client *client, u8 addr, u8 
> data)
> +{
> + int ret;
> + unsigned char msgbuf[] = { addr, data };
> +
> + ret = i2c_master_send(client, msgbuf, 2);
> + if (ret < 0)
> + return ret;
> +
> + return 0;
> +}
> +
> +#endif /* __SCCB_H__ */
> 



[PATCH] [media] saa7146: fix error return from master_xfer

2018-05-09 Thread Peter Rosin
Returning -1 (-EPERM) is not appropriate here, go with -EIO.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/common/saa7146/saa7146_i2c.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/common/saa7146/saa7146_i2c.c 
b/drivers/media/common/saa7146/saa7146_i2c.c
index f9e099d812c8..3feddc52c446 100644
--- a/drivers/media/common/saa7146/saa7146_i2c.c
+++ b/drivers/media/common/saa7146/saa7146_i2c.c
@@ -308,7 +308,7 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, 
const struct i2c_msg *m
/* prepare the message(s), get number of u32s to transfer */
count = saa7146_i2c_msg_prepare(msgs, num, buffer);
if ( 0 > count ) {
-   err = -1;
+   err = -EIO;
goto out;
}
 
@@ -360,7 +360,7 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, 
const struct i2c_msg *m
/* if any things had to be read, get the results */
if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) {
DEB_I2C("could not cleanup i2c-message\n");
-   err = -1;
+   err = -EIO;
goto out;
}
 
-- 
2.11.0



Re: [PATCH 6/8] drm: rcar-du: rcar-lvds: Add bridge format support

2018-04-23 Thread Peter Rosin
On 2018-04-23 09:28, jacopo mondi wrote:
> Hi Peter,
>thanks for looking into this
> 
> On Sun, Apr 22, 2018 at 10:08:21PM +0200, Peter Rosin wrote:
>> On 2018-04-19 11:31, Jacopo Mondi wrote:
>>> With the introduction of static input image format enumeration in DRM
>>> bridges, add support to retrieve the format in rcar-lvds LVDS encoder
>>> from both panel or bridge, to set the desired LVDS mode.
>>>
>>> Do not rely on 'DRM_BUS_FLAG_DATA_LSB_TO_MSB' flag to mirror the LVDS
>>> format, as it is only defined for drm connectors, but use the newly
>>> introduced _LE version of LVDS mbus image formats.
>>>
>>> Signed-off-by: Jacopo Mondi <jacopo+rene...@jmondi.org>
>>> ---
>>>  drivers/gpu/drm/rcar-du/rcar_lvds.c | 64 
>>> +
>>>  1 file changed, 44 insertions(+), 20 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c 
>>> b/drivers/gpu/drm/rcar-du/rcar_lvds.c
>>> index 3d2d3bb..2fa875f 100644
>>> --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
>>> +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
>>> @@ -280,41 +280,65 @@ static bool rcar_lvds_mode_fixup(struct drm_bridge 
>>> *bridge,
>>> return true;
>>>  }
>>>
>>> -static void rcar_lvds_get_lvds_mode(struct rcar_lvds *lvds)
>>> +static int rcar_lvds_get_lvds_mode_from_connector(struct rcar_lvds *lvds,
>>> + unsigned int *bus_fmt)
>>>  {
>>> struct drm_display_info *info = >connector.display_info;
>>> -   enum rcar_lvds_mode mode;
>>> -
>>> -   /*
>>> -* There is no API yet to retrieve LVDS mode from a bridge, only panels
>>> -* are supported.
>>> -*/
>>> -   if (!lvds->panel)
>>> -   return;
>>>
>>> if (!info->num_bus_formats || !info->bus_formats) {
>>> dev_err(lvds->dev, "no LVDS bus format reported\n");
>>> -   return;
>>> +   return -EINVAL;
>>> +   }
>>> +
>>> +   *bus_fmt = info->bus_formats[0];
>>> +
>>> +   return 0;
>>> +}
>>> +
>>> +static int rcar_lvds_get_lvds_mode_from_bridge(struct rcar_lvds *lvds,
>>> +  unsigned int *bus_fmt)
>>> +{
>>> +   if (!lvds->next_bridge->num_bus_formats ||
>>> +   !lvds->next_bridge->bus_formats) {
>>> +   dev_err(lvds->dev, "no LVDS bus format reported\n");
>>> +   return -EINVAL;
>>> }
>>>
>>> -   switch (info->bus_formats[0]) {
>>> +   *bus_fmt = lvds->next_bridge->bus_formats[0];
>>
>> What makes the first reported format the best choice?
> 
> It already was the selection 'policy' in place in this driver before
> introducing bridge formats. As you can see from the switch I have here
> removed, the first format was selected even when only the format
> reported by the connector was inspected.

Well, *if* some bridge/panel do support more than one format, and your
driver depends on it being the first reported format, then I can easily
see that some other driver also requires its expected format to be first.
Then we might end up in a war over what format should be reported as the
first so that this multi-input bridge/panel could be used by both drivers.

> And, anyway, as DRM lacks a format negotiation API, there is no way to
> tell a bridge/panel "use this format instead of this other one" (which
> makes me wonders why more formats can be reported, but the
> bus_formats[] helpers for connectors allow that, so I thought it made
> sense to do the same for bridges).

Since there is no way to negotiate, I would assume that the other end
really does support all reported formats (in some automagical way). To
me, the only sensible approach is to loop over the formats and see if
*any* of them fits, and assume that something else deals with the
details.

>>
>>> +
>>> +   return 0;
>>> +}
>>> +
>>> +static void rcar_lvds_get_lvds_mode(struct rcar_lvds *lvds)
>>> +{
>>> +   unsigned int bus_fmt;
>>> +   int ret;
>>> +
>>> +   if (lvds->panel)
>>> +   ret = rcar_lvds_get_lvds_mode_from_connector(lvds, _fmt);
>>> +   else
>>> +   ret = rcar_lvds_get_lvds_mode_from_bridge(lvds, _fmt);
>>
>> What if no bridge reports any format, shouldn't the connector be examined
>> then?
> 
> Th

Re: [PATCH 6/8] drm: rcar-du: rcar-lvds: Add bridge format support

2018-04-22 Thread Peter Rosin
On 2018-04-19 11:31, Jacopo Mondi wrote:
> With the introduction of static input image format enumeration in DRM
> bridges, add support to retrieve the format in rcar-lvds LVDS encoder
> from both panel or bridge, to set the desired LVDS mode.
> 
> Do not rely on 'DRM_BUS_FLAG_DATA_LSB_TO_MSB' flag to mirror the LVDS
> format, as it is only defined for drm connectors, but use the newly
> introduced _LE version of LVDS mbus image formats.
> 
> Signed-off-by: Jacopo Mondi 
> ---
>  drivers/gpu/drm/rcar-du/rcar_lvds.c | 64 
> +
>  1 file changed, 44 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c 
> b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> index 3d2d3bb..2fa875f 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> @@ -280,41 +280,65 @@ static bool rcar_lvds_mode_fixup(struct drm_bridge 
> *bridge,
>   return true;
>  }
>  
> -static void rcar_lvds_get_lvds_mode(struct rcar_lvds *lvds)
> +static int rcar_lvds_get_lvds_mode_from_connector(struct rcar_lvds *lvds,
> +   unsigned int *bus_fmt)
>  {
>   struct drm_display_info *info = >connector.display_info;
> - enum rcar_lvds_mode mode;
> -
> - /*
> -  * There is no API yet to retrieve LVDS mode from a bridge, only panels
> -  * are supported.
> -  */
> - if (!lvds->panel)
> - return;
>  
>   if (!info->num_bus_formats || !info->bus_formats) {
>   dev_err(lvds->dev, "no LVDS bus format reported\n");
> - return;
> + return -EINVAL;
> + }
> +
> + *bus_fmt = info->bus_formats[0];
> +
> + return 0;
> +}
> +
> +static int rcar_lvds_get_lvds_mode_from_bridge(struct rcar_lvds *lvds,
> +unsigned int *bus_fmt)
> +{
> + if (!lvds->next_bridge->num_bus_formats ||
> + !lvds->next_bridge->bus_formats) {
> + dev_err(lvds->dev, "no LVDS bus format reported\n");
> + return -EINVAL;
>   }
>  
> - switch (info->bus_formats[0]) {
> + *bus_fmt = lvds->next_bridge->bus_formats[0];

What makes the first reported format the best choice?

> +
> + return 0;
> +}
> +
> +static void rcar_lvds_get_lvds_mode(struct rcar_lvds *lvds)
> +{
> + unsigned int bus_fmt;
> + int ret;
> +
> + if (lvds->panel)
> + ret = rcar_lvds_get_lvds_mode_from_connector(lvds, _fmt);
> + else
> + ret = rcar_lvds_get_lvds_mode_from_bridge(lvds, _fmt);

What if no bridge reports any format, shouldn't the connector be examined
then?

> + if (ret)
> + return;
> +
> + switch (bus_fmt) {
> + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG_LE:
> + case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA_LE:
> + lvds->mode |= RCAR_LVDS_MODE_MIRROR;
>   case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
>   case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
> - mode = RCAR_LVDS_MODE_JEIDA;
> + lvds->mode = RCAR_LVDS_MODE_JEIDA;

This is b0rken, first the mirror bit is ORed into some unknown preexisting
value, then the code falls through (without any fall through comment, btw)
and forcibly sets the mode, thus discarding the mirror bit which was
carefully ORed in.

>   break;
> +
> + case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG_LE:
> + lvds->mode |= RCAR_LVDS_MODE_MIRROR;
>   case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
> - mode = RCAR_LVDS_MODE_VESA;
> + lvds->mode = RCAR_LVDS_MODE_VESA;

Dito.

Cheers,
Peter

>   break;
>   default:
>   dev_err(lvds->dev, "unsupported LVDS bus format 0x%04x\n",
> - info->bus_formats[0]);
> - return;
> + bus_fmt);
>   }
> -
> - if (info->bus_flags & DRM_BUS_FLAG_DATA_LSB_TO_MSB)
> - mode |= RCAR_LVDS_MODE_MIRROR;
> -
> - lvds->mode = mode;
>  }
>  
>  static void rcar_lvds_mode_set(struct drm_bridge *bridge,
> 



Re: [PATCH 2/8] dt-bindings: display: bridge: thc63lvd1024: Add lvds map property

2018-04-22 Thread Peter Rosin
On 2018-04-19 11:31, Jacopo Mondi wrote:
> The THC63LVD1024 LVDS to RGB bridge supports two different input mapping
> modes, selectable by means of an external pin.
> 
> Describe the LVDS mode map through a newly defined mandatory property in
> device tree bindings.
> 
> Signed-off-by: Jacopo Mondi 
> ---
>  .../devicetree/bindings/display/bridge/thine,thc63lvd1024.txt  | 3 
> +++
>  1 file changed, 3 insertions(+)
> 
> diff --git 
> a/Documentation/devicetree/bindings/display/bridge/thine,thc63lvd1024.txt 
> b/Documentation/devicetree/bindings/display/bridge/thine,thc63lvd1024.txt
> index 37f0c04..0937595 100644
> --- a/Documentation/devicetree/bindings/display/bridge/thine,thc63lvd1024.txt
> +++ b/Documentation/devicetree/bindings/display/bridge/thine,thc63lvd1024.txt
> @@ -12,6 +12,8 @@ Required properties:
>  - compatible: Shall be "thine,thc63lvd1024"
>  - vcc-supply: Power supply for TTL output, TTL CLOCKOUT signal, LVDS input,
>PPL and digital circuitry
> +- thine,map: LVDS mapping mode selection signal, pin name "MAP". Shall be <1>
> +  for mapping mode 1, <0> for mapping mode 2

Since the MAP pin is an input pin, I would expect there to be an optional gpio
specifier like thine,map-gpios so that the driver can set it according to
the value given in thine,map in case the HW has a line from some gpio output
to the MAP pin (instead of hardwired hi/low which seem to be your thinking).

Cheers,
Peter

>  
>  Optional properties:
>  - powerdown-gpios: Power down GPIO signal, pin name "/PDWN". Active low
> @@ -36,6 +38,7 @@ Example:
>  
>   vcc-supply = <_lvds_vcc>;
>   powerdown-gpios = < 15 GPIO_ACTIVE_LOW>;
> + thine,map = <1>;
>  
>   ports {
>   #address-cells = <1>;
> 



Re: [PATCH 3/8] drm: bridge: thc63lvd1024: Add support for LVDS mode map

2018-04-22 Thread Peter Rosin
On 2018-04-19 11:31, Jacopo Mondi wrote:
> The THC63LVD1024 LVDS to RGB bridge supports two different LVDS mapping
> modes, selectable by means of an external pin.
> 
> Add support for configurable LVDS input mapping modes, using the newly
> introduced support for bridge input image formats.
> 
> Signed-off-by: Jacopo Mondi 
> ---
>  drivers/gpu/drm/bridge/thc63lvd1024.c | 41 
> +++
>  1 file changed, 41 insertions(+)
> 
> diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c 
> b/drivers/gpu/drm/bridge/thc63lvd1024.c
> index 48527f8..a3071a1 100644
> --- a/drivers/gpu/drm/bridge/thc63lvd1024.c
> +++ b/drivers/gpu/drm/bridge/thc63lvd1024.c
> @@ -10,9 +10,15 @@
>  #include 
>  
>  #include 
> +#include 
>  #include 
>  #include 
>  
> +enum thc63_lvds_mapping_mode {
> + THC63_LVDS_MAP_MODE2,
> + THC63_LVDS_MAP_MODE1,
> +};
> +
>  enum thc63_ports {
>   THC63_LVDS_IN0,
>   THC63_LVDS_IN1,
> @@ -116,6 +122,37 @@ static int thc63_parse_dt(struct thc63_dev *thc63)
>   return 0;
>  }
>  
> +static int thc63_set_bus_fmt(struct thc63_dev *thc63)
> +{
> + u32 bus_fmt;
> + u32 map;
> + int ret;
> +
> + ret = of_property_read_u32(thc63->dev->of_node, "thine,map", );
> + if (ret) {
> + dev_err(thc63->dev,
> + "Unable to parse property \"thine,map\": %d\n", ret);
> + return ret;
> + }
> +
> + switch (map) {
> + case THC63_LVDS_MAP_MODE1:
> + bus_fmt = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA;
> + break;
> + case THC63_LVDS_MAP_MODE2:
> + bus_fmt = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG;

Why do you assume rgb888/1x7x4 here? It might as well be rgb666/1x7x3
or rgb101010/1x7x5, no?

Cheers,
Peter

> + break;
> + default:
> + dev_err(thc63->dev,
> + "Invalid value for property \"thine,map\": %u\n", map);
> + return -EINVAL;
> + }
> +
> + drm_bridge_set_bus_formats(>bridge, _fmt, 1);
> +
> + return 0;
> +}
> +
>  static int thc63_gpio_init(struct thc63_dev *thc63)
>  {
>   thc63->oe = devm_gpiod_get_optional(thc63->dev, "oe", GPIOD_OUT_LOW);
> @@ -166,6 +203,10 @@ static int thc63_probe(struct platform_device *pdev)
>   if (ret)
>   return ret;
>  
> + ret = thc63_set_bus_fmt(thc63);
> + if (ret)
> + return ret;
> +
>   thc63->bridge.driver_private = thc63;
>   thc63->bridge.of_node = pdev->dev.of_node;
>   thc63->bridge.funcs = _bridge_func;
> 



Re: [PATCH 1/8] drm: bridge: Add support for static image formats

2018-04-22 Thread Peter Rosin
On 2018-04-19 11:31, Jacopo Mondi wrote:
> Add support for storing image format information in DRM bridges with
> associated helper function.
> 
> This patch replicates for bridges what 'drm_display_info_set_bus_formats()'
> is for connectors.
> 
> Signed-off-by: Jacopo Mondi 
> ---
>  drivers/gpu/drm/drm_bridge.c | 30 ++
>  include/drm/drm_bridge.h |  8 
>  2 files changed, 38 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 1638bfe..e2ad098 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -157,6 +157,36 @@ void drm_bridge_detach(struct drm_bridge *bridge)
>  }
>  
>  /**
> + * drm_bridge_set_bus_formats() - set bridge supported image formats
> + * @bridge: the bridge to set image formats in
> + * @formats: array of MEDIA_BUS_FMT\_ supported image formats
> + * @num_formats: number of elements in the @formats array
> + *
> + * Store a list of supported image formats in a bridge.
> + * See MEDIA_BUS_FMT_* definitions in include/uapi/linux/media-bus-format.h 
> for
> + * a full list of available formats.
> + */
> +int drm_bridge_set_bus_formats(struct drm_bridge *bridge, const u32 *formats,
> +unsigned int num_formats)
> +{
> + u32 *fmts;
> +
> + if (!formats || !num_formats)
> + return -EINVAL;

I see no compelling reason to forbid restoring the number of reported
input formats to zero? I can't think of a use right now of course, but it
seems a bit odd all the same.

Cheers,
Peter

> +
> + fmts = kmemdup(formats, sizeof(*formats) * num_formats, GFP_KERNEL);
> + if (!fmts)
> + return -ENOMEM;
> +
> + kfree(bridge->bus_formats);
> + bridge->bus_formats = fmts;
> + bridge->num_bus_formats = num_formats;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(drm_bridge_set_bus_formats);
> +
> +/**
>   * DOC: bridge callbacks
>   *
>   * The _bridge_funcs ops are populated by the bridge driver. The DRM
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 3270fec..6b3648c 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -258,6 +258,9 @@ struct drm_bridge_timings {
>   * @encoder: encoder to which this bridge is connected
>   * @next: the next bridge in the encoder chain
>   * @of_node: device node pointer to the bridge
> + * @bus_formats: wire image formats. Array of @num_bus_formats 
> MEDIA_BUS_FMT\_
> + * elements
> + * @num_bus_formats: size of @bus_formats array
>   * @list: to keep track of all added bridges
>   * @timings: the timing specification for the bridge, if any (may
>   * be NULL)
> @@ -271,6 +274,9 @@ struct drm_bridge {
>  #ifdef CONFIG_OF
>   struct device_node *of_node;
>  #endif
> + const u32 *bus_formats;
> + unsigned int num_bus_formats;
> +
>   struct list_head list;
>   const struct drm_bridge_timings *timings;
>  
> @@ -296,6 +302,8 @@ void drm_bridge_mode_set(struct drm_bridge *bridge,
>   struct drm_display_mode *adjusted_mode);
>  void drm_bridge_pre_enable(struct drm_bridge *bridge);
>  void drm_bridge_enable(struct drm_bridge *bridge);
> +int drm_bridge_set_bus_formats(struct drm_bridge *bridge, const u32 *fmts,
> +unsigned int num_fmts);
>  
>  #ifdef CONFIG_DRM_PANEL_BRIDGE
>  struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
> 



Re: [linux-media] Patch notification: 3 patches updated

2017-08-12 Thread Peter Rosin
On 2017-08-09 17:01, Patchwork wrote:
> Hello,
> 
> The following patches (submitted by you) have been updated in patchwork:
> 
>  * linux-media: [2/3,media] cx231xx: drop return value of 
> cx231xx_i2c_unregister
>  - http://patchwork.linuxtv.org/patch/42858/
>  - for: Linux Media kernel patches
> was: Under Review
> now: Superseded
> 
>  * linux-media: [3/3,media] cx231xx: only unregister successfully registered 
> i2c adapters
>  - http://patchwork.linuxtv.org/patch/42857/
>  - for: Linux Media kernel patches
> was: Under Review
> now: Superseded
> 
>  * linux-media: [1/3,media] cx231xx: fail probe if i2c_add_adapter fails
>  - http://patchwork.linuxtv.org/patch/42859/
>  - for: Linux Media kernel patches
> was: Under Review
> now: Superseded
> 
> This email is a notification only - you do not need to respond.

*snip*

> If you think any status change is a mistake, please send an email to the ML.

I think the correct status should be "Accepted", right? Because I got mails
saying all three were queued...

Cheers,
peda


Re: [PATCH 3/3] [media] cx231xx: only unregister successfully registered i2c adapters

2017-08-09 Thread Peter Rosin
On 2017-08-09 16:27, Mauro Carvalho Chehab wrote:
> Em Mon, 31 Jul 2017 15:38:52 +0200
> Peter Rosin <p...@axentia.se> escreveu:
> 
>> This prevents potentially scary debug messages from the i2c core.
>>
>> Signed-off-by: Peter Rosin <p...@axentia.se>
>> ---
>>  drivers/media/usb/cx231xx/cx231xx-core.c | 3 +++
>>  drivers/media/usb/cx231xx/cx231xx-i2c.c  | 3 ++-
>>  2 files changed, 5 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c 
>> b/drivers/media/usb/cx231xx/cx231xx-core.c
>> index 46646ecd2dbc..f372ad3917a8 100644
>> --- a/drivers/media/usb/cx231xx/cx231xx-core.c
>> +++ b/drivers/media/usb/cx231xx/cx231xx-core.c
>> @@ -1311,6 +1311,7 @@ int cx231xx_dev_init(struct cx231xx *dev)
>>  dev->i2c_bus[0].i2c_period = I2C_SPEED_100K;/* 100 KHz */
>>  dev->i2c_bus[0].i2c_nostop = 0;
>>  dev->i2c_bus[0].i2c_reserve = 0;
>> +dev->i2c_bus[0].i2c_rc = -ENODEV;
>>  
>>  /* External Master 2 Bus */
>>  dev->i2c_bus[1].nr = 1;
>> @@ -1318,6 +1319,7 @@ int cx231xx_dev_init(struct cx231xx *dev)
>>  dev->i2c_bus[1].i2c_period = I2C_SPEED_100K;/* 100 KHz */
>>  dev->i2c_bus[1].i2c_nostop = 0;
>>  dev->i2c_bus[1].i2c_reserve = 0;
>> +dev->i2c_bus[1].i2c_rc = -ENODEV;
>>  
>>  /* Internal Master 3 Bus */
>>  dev->i2c_bus[2].nr = 2;
>> @@ -1325,6 +1327,7 @@ int cx231xx_dev_init(struct cx231xx *dev)
>>  dev->i2c_bus[2].i2c_period = I2C_SPEED_100K;/* 100kHz */
>>  dev->i2c_bus[2].i2c_nostop = 0;
>>  dev->i2c_bus[2].i2c_reserve = 0;
>> +dev->i2c_bus[2].i2c_rc = -ENODEV;
>>  
>>  /* register I2C buses */
>>  errCode = cx231xx_i2c_register(>i2c_bus[0]);
>> diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c 
>> b/drivers/media/usb/cx231xx/cx231xx-i2c.c
>> index 3e49517cb5e0..8ce6b815d16d 100644
>> --- a/drivers/media/usb/cx231xx/cx231xx-i2c.c
>> +++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c
>> @@ -553,7 +553,8 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus)
>>   */
>>  void cx231xx_i2c_unregister(struct cx231xx_i2c *bus)
>>  {
>> -i2c_del_adapter(>i2c_adap);
>> +if (!bus->i2c_rc)
>> +i2c_del_adapter(>i2c_adap);
> 
> That doesn't sound right. what happens if i2c_rc is 1 or 2?
> 
> IMHO, the right would would be, instead:
> 
>   if (bus->i2c_rc >= 0)
>   i2c_del_adapter(>i2c_adap);

In theory, yes. But in practice i2c_add_adapter never returns >0, and is
also documented so.

Let me know if you still want an update. In that case I'll also fix the
precedent present in the context of patch 1/3, i.e.

if (0 != bus->i2c_rc)
...

Cheers,
peda


[PATCH 0/3] [media] cx231xx: cleanup i2c adapter handling

2017-07-31 Thread Peter Rosin
Hi!

This seems like fairly straight forward cleanups/bugfixes. I don't
have the hardware and found the issues by reading code while doing
other things. So, it builds for me, but it's untested.

1/3 changes behavior on failure, but I think it's the right thing
to do. If it isn't for some reason, then the current code is crap
anyway, because as-is it compares with a value that is always zero
meaning that the entire "if (0 != bus->i2c_rc)"-clause with its
dev_warn can be removed from cx231xx_i2c_register.

Cheers,
Peter

Peter Rosin (3):
  [media] cx231xx: fail probe if i2c_add_adapter fails
  [media] cx231xx: drop return value of cx231xx_i2c_unregister
  [media] cx231xx: only unregister successfully registered i2c adapters

 drivers/media/usb/cx231xx/cx231xx-core.c | 3 +++
 drivers/media/usb/cx231xx/cx231xx-i2c.c  | 8 
 drivers/media/usb/cx231xx/cx231xx.h  | 4 ++--
 3 files changed, 9 insertions(+), 6 deletions(-)

-- 
2.11.0



[PATCH 1/3] [media] cx231xx: fail probe if i2c_add_adapter fails

2017-07-31 Thread Peter Rosin
While at it, change the type of the previously always-zero i2c_rc
member to int, matching the returned type from i2c_add_adapter.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/usb/cx231xx/cx231xx-i2c.c | 2 +-
 drivers/media/usb/cx231xx/cx231xx.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c 
b/drivers/media/usb/cx231xx/cx231xx-i2c.c
index 8d95b1154e12..3a0c45ffd40f 100644
--- a/drivers/media/usb/cx231xx/cx231xx-i2c.c
+++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c
@@ -538,7 +538,7 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus)
 
bus->i2c_adap.algo_data = bus;
i2c_set_adapdata(>i2c_adap, >v4l2_dev);
-   i2c_add_adapter(>i2c_adap);
+   bus->i2c_rc = i2c_add_adapter(>i2c_adap);
 
if (0 != bus->i2c_rc)
dev_warn(dev->dev,
diff --git a/drivers/media/usb/cx231xx/cx231xx.h 
b/drivers/media/usb/cx231xx/cx231xx.h
index 986c64ba5b56..27ee035f9f84 100644
--- a/drivers/media/usb/cx231xx/cx231xx.h
+++ b/drivers/media/usb/cx231xx/cx231xx.h
@@ -476,7 +476,7 @@ struct cx231xx_i2c {
 
/* i2c i/o */
struct i2c_adapter i2c_adap;
-   u32 i2c_rc;
+   int i2c_rc;
 
/* different settings for each bus */
u8 i2c_period;
-- 
2.11.0



[PATCH 2/3] [media] cx231xx: drop return value of cx231xx_i2c_unregister

2017-07-31 Thread Peter Rosin
Noone cares anyway.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/usb/cx231xx/cx231xx-i2c.c | 3 +--
 drivers/media/usb/cx231xx/cx231xx.h | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c 
b/drivers/media/usb/cx231xx/cx231xx-i2c.c
index 3a0c45ffd40f..3e49517cb5e0 100644
--- a/drivers/media/usb/cx231xx/cx231xx-i2c.c
+++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c
@@ -551,10 +551,9 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus)
  * cx231xx_i2c_unregister()
  * unregister i2c_bus
  */
-int cx231xx_i2c_unregister(struct cx231xx_i2c *bus)
+void cx231xx_i2c_unregister(struct cx231xx_i2c *bus)
 {
i2c_del_adapter(>i2c_adap);
-   return 0;
 }
 
 /*
diff --git a/drivers/media/usb/cx231xx/cx231xx.h 
b/drivers/media/usb/cx231xx/cx231xx.h
index 27ee035f9f84..72d5937a087e 100644
--- a/drivers/media/usb/cx231xx/cx231xx.h
+++ b/drivers/media/usb/cx231xx/cx231xx.h
@@ -762,7 +762,7 @@ int cx231xx_reset_analog_tuner(struct cx231xx *dev);
 /* Provided by cx231xx-i2c.c */
 void cx231xx_do_i2c_scan(struct cx231xx *dev, int i2c_port);
 int cx231xx_i2c_register(struct cx231xx_i2c *bus);
-int cx231xx_i2c_unregister(struct cx231xx_i2c *bus);
+void cx231xx_i2c_unregister(struct cx231xx_i2c *bus);
 int cx231xx_i2c_mux_create(struct cx231xx *dev);
 int cx231xx_i2c_mux_register(struct cx231xx *dev, int mux_no);
 void cx231xx_i2c_mux_unregister(struct cx231xx *dev);
-- 
2.11.0



[PATCH 3/3] [media] cx231xx: only unregister successfully registered i2c adapters

2017-07-31 Thread Peter Rosin
This prevents potentially scary debug messages from the i2c core.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/usb/cx231xx/cx231xx-core.c | 3 +++
 drivers/media/usb/cx231xx/cx231xx-i2c.c  | 3 ++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c 
b/drivers/media/usb/cx231xx/cx231xx-core.c
index 46646ecd2dbc..f372ad3917a8 100644
--- a/drivers/media/usb/cx231xx/cx231xx-core.c
+++ b/drivers/media/usb/cx231xx/cx231xx-core.c
@@ -1311,6 +1311,7 @@ int cx231xx_dev_init(struct cx231xx *dev)
dev->i2c_bus[0].i2c_period = I2C_SPEED_100K;/* 100 KHz */
dev->i2c_bus[0].i2c_nostop = 0;
dev->i2c_bus[0].i2c_reserve = 0;
+   dev->i2c_bus[0].i2c_rc = -ENODEV;
 
/* External Master 2 Bus */
dev->i2c_bus[1].nr = 1;
@@ -1318,6 +1319,7 @@ int cx231xx_dev_init(struct cx231xx *dev)
dev->i2c_bus[1].i2c_period = I2C_SPEED_100K;/* 100 KHz */
dev->i2c_bus[1].i2c_nostop = 0;
dev->i2c_bus[1].i2c_reserve = 0;
+   dev->i2c_bus[1].i2c_rc = -ENODEV;
 
/* Internal Master 3 Bus */
dev->i2c_bus[2].nr = 2;
@@ -1325,6 +1327,7 @@ int cx231xx_dev_init(struct cx231xx *dev)
dev->i2c_bus[2].i2c_period = I2C_SPEED_100K;/* 100kHz */
dev->i2c_bus[2].i2c_nostop = 0;
dev->i2c_bus[2].i2c_reserve = 0;
+   dev->i2c_bus[2].i2c_rc = -ENODEV;
 
/* register I2C buses */
errCode = cx231xx_i2c_register(>i2c_bus[0]);
diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c 
b/drivers/media/usb/cx231xx/cx231xx-i2c.c
index 3e49517cb5e0..8ce6b815d16d 100644
--- a/drivers/media/usb/cx231xx/cx231xx-i2c.c
+++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c
@@ -553,7 +553,8 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus)
  */
 void cx231xx_i2c_unregister(struct cx231xx_i2c *bus)
 {
-   i2c_del_adapter(>i2c_adap);
+   if (!bus->i2c_rc)
+   i2c_del_adapter(>i2c_adap);
 }
 
 /*
-- 
2.11.0



Re: [PATCH 2/2] [media] platform: add video-multiplexer subdevice driver

2017-05-03 Thread Peter Rosin
On 2017-05-03 10:35, Philipp Zabel wrote:
> On Tue, 2017-05-02 at 19:42 +0200, Peter Rosin wrote:
>> On 2017-05-02 17:21, Philipp Zabel wrote:
>>> Thank you, I've resent a version with a mutex lock around vmux->active.
>>
>> I had a bunch of ifs in the above message, so I'm not sure it's needed.
>> I would expect there to be a lock outside somewhere in the media layer.
>> A cursory look gets me to media-entity.c and media_entity_setup_link()
>> which does have a mutex. But I'm no media expert, so maybe there are other
>> ways of getting to video_mux_link_setup that I'm not aware of?
> 
> link_setup is always called under the graph mutex of the /dev/media
> device. That is why I didn't think about locking too hard. In fact, I
> initially wrote this expecting mux_control_get_exclusive to exist and
> the mux select/deselect not to be locked at all.
> 
> But set_format is called from an unlocked ioctl on a /dev/v4l-subdev
> device. Until your comments I didn't notice that it would be possible to
> let link_setup set active = -1 in the middle of the set_format call,
> causing it to return garbage.

Obviously, now that you point it out. I completely missed set_format...

Cheers,
peda



Re: [PATCH 2/2] [media] platform: add video-multiplexer subdevice driver

2017-05-02 Thread Peter Rosin
On 2017-05-02 17:21, Philipp Zabel wrote:
> On Sat, 2017-04-29 at 23:42 +0200, Peter Rosin wrote:
>> On 2017-04-29 23:29, Peter Rosin wrote:
>>> On 2017-04-28 16:13, Philipp Zabel wrote:
>>>> This driver can handle SoC internal and external video bus multiplexers,
>>>> controlled by mux controllers provided by the mux controller framework,
>>>> such as MMIO register bitfields or GPIOs. The subdevice passes through
>>>> the mbus configuration of the active input to the output side.
>>>>
>>>> Signed-off-by: Sascha Hauer <s.ha...@pengutronix.de>
>>>> Signed-off-by: Philipp Zabel <p.za...@pengutronix.de>
>>>> Signed-off-by: Steve Longerbeam <steve_longerb...@mentor.com>
>>>> ---
>>>> This has been last sent as part of the i.MX media series.
>>>>
>>>> Changes since https://patchwork.kernel.org/patch/9647869/:
>>>>  - Split out the actual mux operation to be provided by the mux controller
>>>>framework [1]. GPIO and MMIO control can be provided by individual mux
>>>>controller drivers [2][3].
>>>>[1] https://patchwork.kernel.org/patch/9695837/
>>>>[2] https://patchwork.kernel.org/patch/9695839/
>>>>[3] https://patchwork.kernel.org/patch/9704509/
>>>>  - Shortened 'video-multiplexer' to 'video-mux', replaced all instances of
>>>>vidsw with video_mux.
>>>>  - Made the mux inactive by default, only activated by user interaction.
>>>>  - Added CONFIG_OF and CONFIG_MULTIPLEXER dependencies.
>>>>  - Reuse subdev.entity.num_pads instead of keeping our own count.
>>>>  - Removed implicit link disabling. Instead, trying to enable a second
>>>>sink pad link yields -EBUSY.
>>>>  - Merged _async_init into _probe.
>>>>  - Removed superfluous pad index check from _set_format.
>>>>  - Added is_source_pad helper to tell source and sink pads apart.
>>>>  - Removed test for status property in endpoint nodes. Disable the remote
>>>>device or sever the endpoint link to disable a sink pad.
>>>> ---
>>>>  drivers/media/platform/Kconfig |   6 +
>>>>  drivers/media/platform/Makefile|   2 +
>>>>  drivers/media/platform/video-mux.c | 341 
>>>> +
>>>>  3 files changed, 349 insertions(+)
>>>>  create mode 100644 drivers/media/platform/video-mux.c
>>>>
>>>> diff --git a/drivers/media/platform/Kconfig 
>>>> b/drivers/media/platform/Kconfig
>>>> index c9106e105baba..b046a6d39fee5 100644
>>>> --- a/drivers/media/platform/Kconfig
>>>> +++ b/drivers/media/platform/Kconfig
>>>> @@ -74,6 +74,12 @@ config VIDEO_M32R_AR_M64278
>>>>  To compile this driver as a module, choose M here: the
>>>>  module will be called arv.
>>>>  
>>>> +config VIDEO_MUX
>>>> +  tristate "Video Multiplexer"
>>>> +  depends on OF && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER && 
>>>> MULTIPLEXER
>>>> +  help
>>>> +This driver provides support for N:1 video bus multiplexers.
>>>> +
>>>>  config VIDEO_OMAP3
>>>>tristate "OMAP 3 Camera support"
>>>>depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3
>>>> diff --git a/drivers/media/platform/Makefile 
>>>> b/drivers/media/platform/Makefile
>>>> index 349ddf6a69da2..fd2735ca3ff75 100644
>>>> --- a/drivers/media/platform/Makefile
>>>> +++ b/drivers/media/platform/Makefile
>>>> @@ -27,6 +27,8 @@ obj-$(CONFIG_VIDEO_SH_VEU)   += sh_veu.o
>>>>  
>>>>  obj-$(CONFIG_VIDEO_MEM2MEM_DEINTERLACE)   += m2m-deinterlace.o
>>>>  
>>>> +obj-$(CONFIG_VIDEO_MUX)   += video-mux.o
>>>> +
>>>>  obj-$(CONFIG_VIDEO_S3C_CAMIF) += s3c-camif/
>>>>  obj-$(CONFIG_VIDEO_SAMSUNG_EXYNOS4_IS)+= exynos4-is/
>>>>  obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG)  += s5p-jpeg/
>>>> diff --git a/drivers/media/platform/video-mux.c 
>>>> b/drivers/media/platform/video-mux.c
>>>> new file mode 100644
>>>> index 0..419541729f67e
>>>> --- /dev/null
>>>> +++ b/drivers/media/platform/video-mux.c
>>>> @@ -0,0 +1,341 @@
>>>> +/*
>>>> + * video stream mult

Re: [PATCH 2/2] [media] platform: add video-multiplexer subdevice driver

2017-04-29 Thread Peter Rosin
On 2017-04-29 23:29, Peter Rosin wrote:
> On 2017-04-28 16:13, Philipp Zabel wrote:
>> This driver can handle SoC internal and external video bus multiplexers,
>> controlled by mux controllers provided by the mux controller framework,
>> such as MMIO register bitfields or GPIOs. The subdevice passes through
>> the mbus configuration of the active input to the output side.
>>
>> Signed-off-by: Sascha Hauer <s.ha...@pengutronix.de>
>> Signed-off-by: Philipp Zabel <p.za...@pengutronix.de>
>> Signed-off-by: Steve Longerbeam <steve_longerb...@mentor.com>
>> ---
>> This has been last sent as part of the i.MX media series.
>>
>> Changes since https://patchwork.kernel.org/patch/9647869/:
>>  - Split out the actual mux operation to be provided by the mux controller
>>framework [1]. GPIO and MMIO control can be provided by individual mux
>>controller drivers [2][3].
>>[1] https://patchwork.kernel.org/patch/9695837/
>>[2] https://patchwork.kernel.org/patch/9695839/
>>[3] https://patchwork.kernel.org/patch/9704509/
>>  - Shortened 'video-multiplexer' to 'video-mux', replaced all instances of
>>vidsw with video_mux.
>>  - Made the mux inactive by default, only activated by user interaction.
>>  - Added CONFIG_OF and CONFIG_MULTIPLEXER dependencies.
>>  - Reuse subdev.entity.num_pads instead of keeping our own count.
>>  - Removed implicit link disabling. Instead, trying to enable a second
>>sink pad link yields -EBUSY.
>>  - Merged _async_init into _probe.
>>  - Removed superfluous pad index check from _set_format.
>>  - Added is_source_pad helper to tell source and sink pads apart.
>>  - Removed test for status property in endpoint nodes. Disable the remote
>>device or sever the endpoint link to disable a sink pad.
>> ---
>>  drivers/media/platform/Kconfig |   6 +
>>  drivers/media/platform/Makefile|   2 +
>>  drivers/media/platform/video-mux.c | 341 
>> +
>>  3 files changed, 349 insertions(+)
>>  create mode 100644 drivers/media/platform/video-mux.c
>>
>> diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
>> index c9106e105baba..b046a6d39fee5 100644
>> --- a/drivers/media/platform/Kconfig
>> +++ b/drivers/media/platform/Kconfig
>> @@ -74,6 +74,12 @@ config VIDEO_M32R_AR_M64278
>>To compile this driver as a module, choose M here: the
>>module will be called arv.
>>  
>> +config VIDEO_MUX
>> +tristate "Video Multiplexer"
>> +depends on OF && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER && 
>> MULTIPLEXER
>> +help
>> +  This driver provides support for N:1 video bus multiplexers.
>> +
>>  config VIDEO_OMAP3
>>  tristate "OMAP 3 Camera support"
>>  depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3
>> diff --git a/drivers/media/platform/Makefile 
>> b/drivers/media/platform/Makefile
>> index 349ddf6a69da2..fd2735ca3ff75 100644
>> --- a/drivers/media/platform/Makefile
>> +++ b/drivers/media/platform/Makefile
>> @@ -27,6 +27,8 @@ obj-$(CONFIG_VIDEO_SH_VEU) += sh_veu.o
>>  
>>  obj-$(CONFIG_VIDEO_MEM2MEM_DEINTERLACE) += m2m-deinterlace.o
>>  
>> +obj-$(CONFIG_VIDEO_MUX) += video-mux.o
>> +
>>  obj-$(CONFIG_VIDEO_S3C_CAMIF)   += s3c-camif/
>>  obj-$(CONFIG_VIDEO_SAMSUNG_EXYNOS4_IS)  += exynos4-is/
>>  obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG)+= s5p-jpeg/
>> diff --git a/drivers/media/platform/video-mux.c 
>> b/drivers/media/platform/video-mux.c
>> new file mode 100644
>> index 0..419541729f67e
>> --- /dev/null
>> +++ b/drivers/media/platform/video-mux.c
>> @@ -0,0 +1,341 @@
>> +/*
>> + * video stream multiplexer controlled via mux control
>> + *
>> + * Copyright (C) 2013 Pengutronix, Sascha Hauer <ker...@pengutronix.de>
>> + * Copyright (C) 2016 Pengutronix, Philipp Zabel <ker...@pengutronix.de>
> 
> 2017?
> 
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License
>> + * as published by the Free Software Foundation; either version 2
>> + * of the License, or (at your option) any later version.
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR

Re: [PATCH 2/2] [media] platform: add video-multiplexer subdevice driver

2017-04-29 Thread Peter Rosin
On 2017-04-28 16:13, Philipp Zabel wrote:
> This driver can handle SoC internal and external video bus multiplexers,
> controlled by mux controllers provided by the mux controller framework,
> such as MMIO register bitfields or GPIOs. The subdevice passes through
> the mbus configuration of the active input to the output side.
> 
> Signed-off-by: Sascha Hauer 
> Signed-off-by: Philipp Zabel 
> Signed-off-by: Steve Longerbeam 
> ---
> This has been last sent as part of the i.MX media series.
> 
> Changes since https://patchwork.kernel.org/patch/9647869/:
>  - Split out the actual mux operation to be provided by the mux controller
>framework [1]. GPIO and MMIO control can be provided by individual mux
>controller drivers [2][3].
>[1] https://patchwork.kernel.org/patch/9695837/
>[2] https://patchwork.kernel.org/patch/9695839/
>[3] https://patchwork.kernel.org/patch/9704509/
>  - Shortened 'video-multiplexer' to 'video-mux', replaced all instances of
>vidsw with video_mux.
>  - Made the mux inactive by default, only activated by user interaction.
>  - Added CONFIG_OF and CONFIG_MULTIPLEXER dependencies.
>  - Reuse subdev.entity.num_pads instead of keeping our own count.
>  - Removed implicit link disabling. Instead, trying to enable a second
>sink pad link yields -EBUSY.
>  - Merged _async_init into _probe.
>  - Removed superfluous pad index check from _set_format.
>  - Added is_source_pad helper to tell source and sink pads apart.
>  - Removed test for status property in endpoint nodes. Disable the remote
>device or sever the endpoint link to disable a sink pad.
> ---
>  drivers/media/platform/Kconfig |   6 +
>  drivers/media/platform/Makefile|   2 +
>  drivers/media/platform/video-mux.c | 341 
> +
>  3 files changed, 349 insertions(+)
>  create mode 100644 drivers/media/platform/video-mux.c
> 
> diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
> index c9106e105baba..b046a6d39fee5 100644
> --- a/drivers/media/platform/Kconfig
> +++ b/drivers/media/platform/Kconfig
> @@ -74,6 +74,12 @@ config VIDEO_M32R_AR_M64278
> To compile this driver as a module, choose M here: the
> module will be called arv.
>  
> +config VIDEO_MUX
> + tristate "Video Multiplexer"
> + depends on OF && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER && 
> MULTIPLEXER
> + help
> +   This driver provides support for N:1 video bus multiplexers.
> +
>  config VIDEO_OMAP3
>   tristate "OMAP 3 Camera support"
>   depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3
> diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
> index 349ddf6a69da2..fd2735ca3ff75 100644
> --- a/drivers/media/platform/Makefile
> +++ b/drivers/media/platform/Makefile
> @@ -27,6 +27,8 @@ obj-$(CONFIG_VIDEO_SH_VEU)  += sh_veu.o
>  
>  obj-$(CONFIG_VIDEO_MEM2MEM_DEINTERLACE)  += m2m-deinterlace.o
>  
> +obj-$(CONFIG_VIDEO_MUX)  += video-mux.o
> +
>  obj-$(CONFIG_VIDEO_S3C_CAMIF)+= s3c-camif/
>  obj-$(CONFIG_VIDEO_SAMSUNG_EXYNOS4_IS)   += exynos4-is/
>  obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg/
> diff --git a/drivers/media/platform/video-mux.c 
> b/drivers/media/platform/video-mux.c
> new file mode 100644
> index 0..419541729f67e
> --- /dev/null
> +++ b/drivers/media/platform/video-mux.c
> @@ -0,0 +1,341 @@
> +/*
> + * video stream multiplexer controlled via mux control
> + *
> + * Copyright (C) 2013 Pengutronix, Sascha Hauer 
> + * Copyright (C) 2016 Pengutronix, Philipp Zabel 

2017?

> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +struct video_mux {
> + struct v4l2_subdev subdev;
> + struct media_pad *pads;
> + struct v4l2_mbus_framefmt *format_mbus;
> + struct v4l2_of_endpoint *endpoint;
> + struct mux_control *mux;
> + int active;
> +};
> +
> +static inline struct video_mux *v4l2_subdev_to_video_mux(struct v4l2_subdev 
> *sd)
> +{
> + return container_of(sd, struct video_mux, subdev);
> +}
> +
> +static inline bool is_source_pad(struct video_mux *vmux, unsigned int pad)
> +{
> + return pad == vmux->subdev.entity.num_pads - 1;
> +}
> +
> +static int 

Re: [PATCH 0/9] Unify i2c_mux_add_adapter error reporting

2017-04-11 Thread Peter Rosin
On 2017-04-03 10:38, Peter Rosin wrote:
> Hi!
> 
> Many users of the i2c_mux_add_adapter interface log a message
> on failure, but the function already logs such a message. One
> or two of those users actually add more information than already
> provided by the central failure message.
> 
> So, first fix the central error reporting to provide as much
> information as any current user, and then remove the surplus
> error reporting at the call sites.

I have now pushed patches 1-7 to i2c-mux/for-next.
Jonathan grabbed patch 8 and it's going through the iio tree.
Still waiting on patch 9 and the media maintainers.

Cheers,
Peter

> 
> Cheers,
> peda
> 
> Peter Rosin (9):
>   i2c: mux: provide more info on failure in i2c_mux_add_adapter
>   i2c: arb: gpio-challenge: stop double error reporting
>   i2c: mux: gpio: stop double error reporting
>   i2c: mux: pca9541: stop double error reporting
>   i2c: mux: pca954x: stop double error reporting
>   i2c: mux: pinctrl: stop double error reporting
>   i2c: mux: reg: stop double error reporting
>   iio: gyro: mpu3050: stop double error reporting
>   [media] cx231xx: stop double error reporting
> 
>  drivers/i2c/i2c-mux.c  |  9 ++---
>  drivers/i2c/muxes/i2c-arb-gpio-challenge.c |  4 +---
>  drivers/i2c/muxes/i2c-mux-gpio.c   |  4 +---
>  drivers/i2c/muxes/i2c-mux-pca9541.c|  4 +---
>  drivers/i2c/muxes/i2c-mux-pca954x.c|  7 +--
>  drivers/i2c/muxes/i2c-mux-pinctrl.c|  4 +---
>  drivers/i2c/muxes/i2c-mux-reg.c|  4 +---
>  drivers/iio/gyro/mpu3050-i2c.c |  5 ++---
>  drivers/media/usb/cx231xx/cx231xx-i2c.c| 15 ---
>  9 files changed, 18 insertions(+), 38 deletions(-)
> 



Re: [PATCH 0/9] Unify i2c_mux_add_adapter error reporting

2017-04-03 Thread Peter Rosin
On 2017-04-03 12:27, Wolfram Sang wrote:
> On Mon, Apr 03, 2017 at 10:38:29AM +0200, Peter Rosin wrote:
>> Hi!
>>
>> Many users of the i2c_mux_add_adapter interface log a message
>> on failure, but the function already logs such a message. One
>> or two of those users actually add more information than already
>> provided by the central failure message.
>>
>> So, first fix the central error reporting to provide as much
>> information as any current user, and then remove the surplus
>> error reporting at the call sites.
> 
> Yes, I like.
> 
> Reviewed-by: Wolfram Sang <w...@the-dreams.de>

Thanks!

BTW, the improved error reporting in patch 1/9 is not needed for
patches 8/9 and 9/9 to make sense, the existing central error
message is already good enough. So, iio and media maintainers,
feel free to just grab those two patches. Or, they can go via
Wolfram and the i2c tree with the rest of the series. Either way
is fine with me, just let me know.

Cheers,
peda


Re: [PATCH 9/9] [media] cx231xx: stop double error reporting

2017-04-03 Thread Peter Rosin
On 2017-04-03 12:26, Wolfram Sang wrote:
> On Mon, Apr 03, 2017 at 10:38:38AM +0200, Peter Rosin wrote:
>> i2c_mux_add_adapter already logs a message on failure.
>>
>> Signed-off-by: Peter Rosin <p...@axentia.se>
>> ---
>>  drivers/media/usb/cx231xx/cx231xx-i2c.c | 15 ---
>>  1 file changed, 4 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c 
>> b/drivers/media/usb/cx231xx/cx231xx-i2c.c
>> index 35e9acfe63d3..dff514e147da 100644
>> --- a/drivers/media/usb/cx231xx/cx231xx-i2c.c
>> +++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c
>> @@ -576,17 +576,10 @@ int cx231xx_i2c_mux_create(struct cx231xx *dev)
>>  
>>  int cx231xx_i2c_mux_register(struct cx231xx *dev, int mux_no)
>>  {
>> -int rc;
>> -
>> -rc = i2c_mux_add_adapter(dev->muxc,
>> - 0,
>> - mux_no /* chan_id */,
>> - 0 /* class */);
>> -if (rc)
>> -dev_warn(dev->dev,
>> - "i2c mux %d register FAILED\n", mux_no);
>> -
>> -return rc;
>> +return i2c_mux_add_adapter(dev->muxc,
>> +   0,
>> +   mux_no /* chan_id */,
>> +   0 /* class */);
> 
> Could be argued that the whole function is obsolete now and the
> c231xx-core can call i2c_mux_add_adapter() directly. But maybe this is a
> seperate patch.

Agreed on all counts. BTW, the ..._unregister function below is equally
"obsolete". I'm going to leave the removal of both functions at the
discretion of whomever takes care of cx231xx maintenance...

Cheers,
peda

>>  }
>>  
>>  void cx231xx_i2c_mux_unregister(struct cx231xx *dev)
>> -- 
>> 2.1.4
>>



[PATCH 1/9] i2c: mux: provide more info on failure in i2c_mux_add_adapter

2017-04-03 Thread Peter Rosin
No callers then need to report any further info, thus reducing both the
amount of code and the log noise.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/i2c-mux.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index 2178266bca79..26f7237558ba 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -395,13 +395,16 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
if (force_nr) {
priv->adap.nr = force_nr;
ret = i2c_add_numbered_adapter(>adap);
+   dev_err(>dev,
+   "failed to add mux-adapter %u as bus %u (error=%d)\n",
+   chan_id, force_nr, ret);
} else {
ret = i2c_add_adapter(>adap);
+   dev_err(>dev,
+   "failed to add mux-adapter %u (error=%d)\n",
+   chan_id, ret);
}
if (ret < 0) {
-   dev_err(>dev,
-   "failed to add mux-adapter (error=%d)\n",
-   ret);
kfree(priv);
return ret;
}
-- 
2.1.4



[PATCH 3/9] i2c: mux: gpio: stop double error reporting

2017-04-03 Thread Peter Rosin
i2c_mux_add_adapter already logs a message on failure.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/muxes/i2c-mux-gpio.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index 655684d621a4..1a9973ede443 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -245,10 +245,8 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
unsigned int class = mux->data.classes ? mux->data.classes[i] : 
0;
 
ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class);
-   if (ret) {
-   dev_err(>dev, "Failed to add adapter %d\n", i);
+   if (ret)
goto add_adapter_failed;
-   }
}
 
dev_info(>dev, "%d port mux on %s adapter\n",
-- 
2.1.4



[PATCH 2/9] i2c: arb: gpio-challenge: stop double error reporting

2017-04-03 Thread Peter Rosin
i2c_mux_add_adapter already logs a message on failure.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/muxes/i2c-arb-gpio-challenge.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c 
b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
index 86fc2d4c081b..812b8cff265f 100644
--- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
+++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
@@ -202,10 +202,8 @@ static int i2c_arbitrator_probe(struct platform_device 
*pdev)
 
/* Actually add the mux adapter */
ret = i2c_mux_add_adapter(muxc, 0, 0, 0);
-   if (ret) {
-   dev_err(dev, "Failed to add adapter\n");
+   if (ret)
i2c_put_adapter(muxc->parent);
-   }
 
return ret;
 }
-- 
2.1.4



[PATCH 5/9] i2c: mux: pca954x: stop double error reporting

2017-04-03 Thread Peter Rosin
i2c_mux_add_adapter already logs a message on failure.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/muxes/i2c-mux-pca954x.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c 
b/drivers/i2c/muxes/i2c-mux-pca954x.c
index 15dfc1648716..b2a85a2d00f7 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -434,13 +434,8 @@ static int pca954x_probe(struct i2c_client *client,
   idle_disconnect_dt) << num;
 
ret = i2c_mux_add_adapter(muxc, force, num, class);
-
-   if (ret) {
-   dev_err(>dev,
-   "failed to register multiplexed adapter"
-   " %d as bus %d\n", num, force);
+   if (ret)
goto fail_del_adapters;
-   }
}
 
dev_info(>dev,
-- 
2.1.4



[PATCH 4/9] i2c: mux: pca9541: stop double error reporting

2017-04-03 Thread Peter Rosin
i2c_mux_add_adapter already logs a message on failure.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/muxes/i2c-mux-pca9541.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c 
b/drivers/i2c/muxes/i2c-mux-pca9541.c
index 77840f7845a1..9e318c9516c7 100644
--- a/drivers/i2c/muxes/i2c-mux-pca9541.c
+++ b/drivers/i2c/muxes/i2c-mux-pca9541.c
@@ -369,10 +369,8 @@ static int pca9541_probe(struct i2c_client *client,
i2c_set_clientdata(client, muxc);
 
ret = i2c_mux_add_adapter(muxc, force, 0, 0);
-   if (ret) {
-   dev_err(>dev, "failed to register master selector\n");
+   if (ret)
return ret;
-   }
 
dev_info(>dev, "registered master selector for I2C %s\n",
 client->name);
-- 
2.1.4



[PATCH 9/9] [media] cx231xx: stop double error reporting

2017-04-03 Thread Peter Rosin
i2c_mux_add_adapter already logs a message on failure.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/usb/cx231xx/cx231xx-i2c.c | 15 ---
 1 file changed, 4 insertions(+), 11 deletions(-)

diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c 
b/drivers/media/usb/cx231xx/cx231xx-i2c.c
index 35e9acfe63d3..dff514e147da 100644
--- a/drivers/media/usb/cx231xx/cx231xx-i2c.c
+++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c
@@ -576,17 +576,10 @@ int cx231xx_i2c_mux_create(struct cx231xx *dev)
 
 int cx231xx_i2c_mux_register(struct cx231xx *dev, int mux_no)
 {
-   int rc;
-
-   rc = i2c_mux_add_adapter(dev->muxc,
-0,
-mux_no /* chan_id */,
-0 /* class */);
-   if (rc)
-   dev_warn(dev->dev,
-"i2c mux %d register FAILED\n", mux_no);
-
-   return rc;
+   return i2c_mux_add_adapter(dev->muxc,
+  0,
+  mux_no /* chan_id */,
+  0 /* class */);
 }
 
 void cx231xx_i2c_mux_unregister(struct cx231xx *dev)
-- 
2.1.4



[PATCH 7/9] i2c: mux: reg: stop double error reporting

2017-04-03 Thread Peter Rosin
i2c_mux_add_adapter already logs a message on failure.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/muxes/i2c-mux-reg.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c
index c6a90b4a9c62..406d5059072c 100644
--- a/drivers/i2c/muxes/i2c-mux-reg.c
+++ b/drivers/i2c/muxes/i2c-mux-reg.c
@@ -222,10 +222,8 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
class = mux->data.classes ? mux->data.classes[i] : 0;
 
ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class);
-   if (ret) {
-   dev_err(>dev, "Failed to add adapter %d\n", i);
+   if (ret)
goto add_adapter_failed;
-   }
}
 
dev_dbg(>dev, "%d port mux on %s adapter\n",
-- 
2.1.4



[PATCH 6/9] i2c: mux: pinctrl: stop double error reporting

2017-04-03 Thread Peter Rosin
i2c_mux_add_adapter already logs a message on failure.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/muxes/i2c-mux-pinctrl.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c 
b/drivers/i2c/muxes/i2c-mux-pinctrl.c
index 35bb775e1b74..7c0c264b07bc 100644
--- a/drivers/i2c/muxes/i2c-mux-pinctrl.c
+++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c
@@ -245,10 +245,8 @@ static int i2c_mux_pinctrl_probe(struct platform_device 
*pdev)
(mux->pdata->base_bus_num + i) : 0;
 
ret = i2c_mux_add_adapter(muxc, bus, i, 0);
-   if (ret) {
-   dev_err(>dev, "Failed to add adapter %d\n", i);
+   if (ret)
goto err_del_adapter;
-   }
}
 
return 0;
-- 
2.1.4



[PATCH 8/9] iio: gyro: mpu3050: stop double error reporting

2017-04-03 Thread Peter Rosin
i2c_mux_add_adapter already logs a message on failure.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/iio/gyro/mpu3050-i2c.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/gyro/mpu3050-i2c.c b/drivers/iio/gyro/mpu3050-i2c.c
index 06007200bf49..93f08b304a63 100644
--- a/drivers/iio/gyro/mpu3050-i2c.c
+++ b/drivers/iio/gyro/mpu3050-i2c.c
@@ -70,9 +70,8 @@ static int mpu3050_i2c_probe(struct i2c_client *client,
dev_err(>dev, "failed to allocate I2C mux\n");
else {
mpu3050->i2cmux->priv = mpu3050;
-   ret = i2c_mux_add_adapter(mpu3050->i2cmux, 0, 0, 0);
-   if (ret)
-   dev_err(>dev, "failed to add I2C mux\n");
+   /* Ignore failure, not critical */
+   i2c_mux_add_adapter(mpu3050->i2cmux, 0, 0, 0);
}
 
return 0;
-- 
2.1.4



[PATCH 0/9] Unify i2c_mux_add_adapter error reporting

2017-04-03 Thread Peter Rosin
Hi!

Many users of the i2c_mux_add_adapter interface log a message
on failure, but the function already logs such a message. One
or two of those users actually add more information than already
provided by the central failure message.

So, first fix the central error reporting to provide as much
information as any current user, and then remove the surplus
error reporting at the call sites.

Cheers,
peda

Peter Rosin (9):
  i2c: mux: provide more info on failure in i2c_mux_add_adapter
  i2c: arb: gpio-challenge: stop double error reporting
  i2c: mux: gpio: stop double error reporting
  i2c: mux: pca9541: stop double error reporting
  i2c: mux: pca954x: stop double error reporting
  i2c: mux: pinctrl: stop double error reporting
  i2c: mux: reg: stop double error reporting
  iio: gyro: mpu3050: stop double error reporting
  [media] cx231xx: stop double error reporting

 drivers/i2c/i2c-mux.c  |  9 ++---
 drivers/i2c/muxes/i2c-arb-gpio-challenge.c |  4 +---
 drivers/i2c/muxes/i2c-mux-gpio.c   |  4 +---
 drivers/i2c/muxes/i2c-mux-pca9541.c|  4 +---
 drivers/i2c/muxes/i2c-mux-pca954x.c|  7 +--
 drivers/i2c/muxes/i2c-mux-pinctrl.c|  4 +---
 drivers/i2c/muxes/i2c-mux-reg.c|  4 +---
 drivers/iio/gyro/mpu3050-i2c.c |  5 ++---
 drivers/media/usb/cx231xx/cx231xx-i2c.c| 15 ---
 9 files changed, 18 insertions(+), 38 deletions(-)

-- 
2.1.4



[PATCH v9 1/9] i2c: allow adapter drivers to override the adapter locking

2016-05-04 Thread Peter Rosin
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_ROOT_ADAPTER and I2C_LOCK_SEGMENT, but they
are both implemented the same. For now. Locking the root 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
a 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_ROOT_ADAPTER flag).

Locking the root adapter and locking the segment is the same thing for
all root adapters (e.g. in the normal case of a simple topology with no
i2c muxes). The two locking variants are also the same for traditional
muxes (aka parent-locked muxes). These muxes traverse the tree, locking
each level as they go until they reach the root. This patch is preparatory
for a later patch in the series introducing mux-locked muxes, which behave
differently depending on the requested locking. Since all current users
are using i2c_lock_adapter, which is a wrapper for I2C_LOCK_ROOT_ADAPTER,
we only need to annotate the calls that will not need to lock the root
adapter for mux-locked muxes. I.e. the instances that needs to use
I2C_LOCK_SEGMENT instead of i2c_lock_adapter/I2C_LOCK_ROOT_ADAPTER. Those
instances are in the i2c_transfer and i2c_smbus_xfer functions, so that
mux-locked muxes can single out normal i2c accesses to its slave side
and adjust the locking for those accesses.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/i2c-core.c | 41 +++--
 include/linux/i2c.h| 44 ++--
 2 files changed, 69 insertions(+), 16 deletions(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 4979728f7fb2..7ef5bd085476 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -954,10 +954,13 @@ 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
+ * @flags: I2C_LOCK_ROOT_ADAPTER locks the root i2c adapter, I2C_LOCK_SEGMENT
+ * locks only this branch in the adapter tree
  */
-void i2c_lock_adapter(struct i2c_adapter *adapter)
+static void i2c_adapter_lock_bus(struct i2c_adapter *adapter,
+unsigned int flags)
 {
struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
 
@@ -966,27 +969,32 @@ void i2c_lock_adapter(struct i2c_adapter *adapter)
else
rt_mutex_lock(>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
+ * @flags: I2C_LOCK_ROOT_ADAPTER trylocks the root i2c adapter, 
I2C_LOCK_SEGMENT
+ * trylocks only this branch in the adapter tree
  */
-static int i2c_trylock_adapter(struct i2c_adapter *adapter)
+static int i2c_adapter_trylock_bus(struct i2c_adapter *adapter,
+  unsigned 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(>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
+ * @flags: I2C_LOCK_ROOT_ADAPTER unlocks the root i2c adapter, I2C_LOCK_SEGMENT
+ * unlocks only this branch in the adapter tree
  */
-void i2c_unlock_adapter(struct i2c_adapter *adapter)
+static void i2c_adapter_unlock_bus(struct i2c_adapter *adapter,
+  unsigned int flags)
 {
struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
 
@@ -995,7 +1003,6 @@ void i2c_unlock_adapter(struct i2c_adapter *adapter)
else
rt_mutex_unlock(>bus_lock);
 }
-EXPORT_SYMBOL_GPL(i2c_unlock_adapter);
 
 static void i2c_dev_set_name(struct i2c_adapter *adap,
 struct i2c_client *client)
@@ -1541,6 +1548,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_tryloc

[PATCH v9 4/9] i2c-mux: document i2c muxes and elaborate on parent-/mux-locked muxes

2016-05-04 Thread Peter Rosin
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/i2c/i2c-topology | 370 +
 MAINTAINERS|   1 +
 2 files changed, 371 insertions(+)
 create mode 100644 Documentation/i2c/i2c-topology

diff --git a/Documentation/i2c/i2c-topology b/Documentation/i2c/i2c-topology
new file mode 100644
index ..27bfd682808d
--- /dev/null
+++ b/Documentation/i2c/i2c-topology
@@ -0,0 +1,370 @@
+I2C topology
+
+
+There are a couple of reasons for building more complex i2c topologies
+than a straight-forward i2c bus with one adapter and one or more devices.
+
+1. A mux may be needed on the bus to prevent address collisions.
+
+2. The bus may be accessible from some external bus master, and arbitration
+   may be needed to determine if it is ok to access the bus.
+
+3. A device (particularly RF tuners) may want to avoid the digital noise
+   from the i2c bus, at least most of the time, and sits behind a gate
+   that has to be operated before the device can be accessed.
+
+Etc
+
+These constructs are represented as i2c adapter trees by Linux, where
+each adapter has a parent adapter (except the root adapter) and zero or
+more child adapters. The root adapter is the actual adapter that issues
+i2c transfers, and all adapters with a parent are part of an "i2c-mux"
+object (quoted, since it can also be an arbitrator or a gate).
+
+Depending of the particular mux driver, something happens when there is
+an i2c transfer on one of its child adapters. The mux driver can
+obviously operate a mux, but it can also do arbitration with an external
+bus master or open a gate. The mux driver has two operations for this,
+select and deselect. select is called before the transfer and (the
+optional) deselect is called after the transfer.
+
+
+Locking
+===
+
+There are two variants of locking available to i2c muxes, they can be
+mux-locked or parent-locked muxes. As is evident from below, it can be
+useful to know if a mux is mux-locked or if it is parent-locked. The
+following list was correct at the time of writing:
+
+In drivers/i2c/muxes/
+i2c-arb-gpio-challengeParent-locked
+i2c-mux-gpio  Normally parent-locked, mux-locked iff
+  all involved gpio pins are controlled by the
+  same i2c root adapter that they mux.
+i2c-mux-pca9541   Parent-locked
+i2c-mux-pca954x   Parent-locked
+i2c-mux-pinctrl   Normally parent-locked, mux-locked iff
+  all involved pinctrl devices are controlled
+  by the same i2c root adapter that they mux.
+i2c-mux-reg   Parent-locked
+
+In drivers/iio/
+imu/inv_mpu6050/  Parent-locked
+
+In drivers/media/
+dvb-frontends/m88ds3103   Parent-locked
+dvb-frontends/rtl2830 Parent-locked
+dvb-frontends/rtl2832 Parent-locked
+dvb-frontends/si2168  Parent-locked
+usb/cx231xx/  Parent-locked
+
+
+Mux-locked muxes
+
+
+Mux-locked muxes does not lock the entire parent adapter during the
+full select-transfer-deselect transaction, only the muxes on the parent
+adapter are locked. Mux-locked muxes are mostly interesting if the
+select and/or deselect operations must use i2c transfers to complete
+their tasks. Since the parent adapter is not fully locked during the
+full transaction, unrelated i2c transfers may interleave the different
+stages of the transaction. This has the benefit that the mux driver
+may be easier and cleaner to implement, but it has some caveats.
+
+ML1. If you build a topology with a mux-locked mux being the parent
+ of a parent-locked mux, this might break the expectation from the
+ parent-locked mux that the root adapter is locked during the
+ transaction.
+
+ML2. It is not safe to build arbitrary topologies with two (or more)
+ mux-locked muxes that are not siblings, when there are address
+ collisions between the devices on the child adapters of these
+ non-sibling muxes.
+
+ I.e. the select-transfer-deselect transaction targeting e.g. device
+ address 0x42 behind mux-one may be interleaved with a similar
+ operation targeting device address 0x42 behind mux-two. The
+ intension with such a topology would in this hypothetical example
+ be that mux-one and mux-two should not be selected simultaneously,
+ but mux-locked muxes do not guarantee that in all topologies.
+
+ML3. A mux-locked mux cannot be used by a driver for auto-closing
+ gates/muxes, i.e. something that closes automatically after a given
+ number (one, in most cases) of i2c transfers. Unrelated i2c transfers
+ may creep in and close prematurely.
+
+ML4. If any non-i2c operation in the mux driver changes the i2c mux state,
+ the driver has to lock the root adapter during that operation.
+ Otherwise garbage may appear on the bus as seen from devices
+ behind the mux, when 

[PATCH v9 5/9] iio: imu: inv_mpu6050: change the i2c gate to be mux-locked

2016-05-04 Thread Peter Rosin
The root i2c adapter lock is then no longer held by the i2c mux during
accesses behind the i2c gate, and such accesses need to take that lock
just like any other ordinary i2c accesses do.

So, declare the i2c gate mux-locked, and zap the code that makes the
unlocked i2c accesses and just use ordinary regmap_write accesses.

This also happens to fix the deadlock described in
http://patchwork.ozlabs.org/patch/584776/ authored by
Adriana Reus <adriana.r...@intel.com> and submitted by
Daniel Baluta <daniel.bal...@intel.com>

--8<--
iio: imu: inv_mpu6050: Fix deadlock between i2c adapter lock and mpu lock

This deadlock occurs if the accel/gyro and the sensor on the auxiliary
I2C (in my setup it's an ak8975) are working at the same time.

Scenario:

  T1T2
   
inv_mpu6050_read_fifo  aux sensor op (eg. ak8975_read_raw)
| |
mutex_lock(_dev->mlock)   i2c_transfer
| |
i2c transaction i2c adapter lock
| |
i2c adapter locki2c_mux_master_xfer
  |
inv_mpu6050_select_bypass
  |
mutex_lock(_dev->mlock)

When we operate on an mpu sensor the order of locking is mpu lock
followed by the i2c adapter lock. However, when we operate the auxiliary
sensor the order of locking is the other way around.

...
--8<--

The reason this patch fixes the deadlock is that T2 does not grab the
i2c adapter lock until the very end (and grabs the newfangled i2c mux
lock where it previously grabbed the i2c adapter lock).

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Daniel Baluta <daniel.bal...@intel.com>
Tested-by: Crestez Dan Leonard <leonard.cres...@intel.com>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/i2c/i2c-topology|  2 +-
 drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 52 ++-
 2 files changed, 11 insertions(+), 43 deletions(-)

diff --git a/Documentation/i2c/i2c-topology b/Documentation/i2c/i2c-topology
index 27bfd682808d..69b008518454 100644
--- a/Documentation/i2c/i2c-topology
+++ b/Documentation/i2c/i2c-topology
@@ -50,7 +50,7 @@ i2c-mux-pinctrl   Normally parent-locked, mux-locked 
iff
 i2c-mux-reg   Parent-locked
 
 In drivers/iio/
-imu/inv_mpu6050/  Parent-locked
+imu/inv_mpu6050/  Mux-locked
 
 In drivers/media/
 dvb-frontends/m88ds3103   Parent-locked
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c 
b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
index 3a078df84224..e25f7ef7f0ea 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
@@ -24,45 +24,16 @@ static const struct regmap_config inv_mpu_regmap_config = {
.val_bits = 8,
 };
 
-/*
- * The i2c read/write needs to happen in unlocked mode. As the parent
- * adapter is common. If we use locked versions, it will fail as
- * the mux adapter will lock the parent i2c adapter, while calling
- * select/deselect functions.
- */
-static int inv_mpu6050_write_reg_unlocked(struct i2c_client *client,
- u8 reg, u8 d)
-{
-   int ret;
-   u8 buf[2] = {reg, d};
-   struct i2c_msg msg[1] = {
-   {
-   .addr = client->addr,
-   .flags = 0,
-   .len = sizeof(buf),
-   .buf = buf,
-   }
-   };
-
-   ret = __i2c_transfer(client->adapter, msg, 1);
-   if (ret != 1)
-   return ret;
-
-   return 0;
-}
-
 static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
 {
-   struct i2c_client *client = i2c_mux_priv(muxc);
-   struct iio_dev *indio_dev = dev_get_drvdata(>dev);
+   struct iio_dev *indio_dev = i2c_mux_priv(muxc);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
int ret = 0;
 
/* Use the same mutex which was used everywhere to protect power-op */
mutex_lock(_dev->mlock);
if (!st->powerup_count) {
-   ret = inv_mpu6050_write_reg_unlocked(client,
-st->reg->pwr_mgmt_1, 0);
+   ret = regmap_write(st->map, st->reg->pwr_mgmt_1, 0);
if (ret)
goto write_error;
 
@@ -71,10 +42,9 @@ static int inv_mpu6050_select_bypass(struct i2c_mux_core 
*muxc, u32 chan_id)
}
if (!ret) {
st->powerup_count++;
-   ret = inv_mpu6050_write_reg_unlocked(

[PATCH v9 2/9] i2c: muxes always lock the parent adapter

2016-05-04 Thread Peter Rosin
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 <p...@axentia.se>
---
 drivers/i2c/i2c-core.c | 21 +++--
 drivers/i2c/i2c-mux.c  | 30 ++
 2 files changed, 33 insertions(+), 18 deletions(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 7ef5bd085476..afdee66002db 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -962,12 +962,7 @@ static int i2c_check_addr_busy(struct i2c_adapter 
*adapter, int addr)
 static void i2c_adapter_lock_bus(struct i2c_adapter *adapter,
 unsigned int flags)
 {
-   struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
-
-   if (parent)
-   i2c_lock_adapter(parent);
-   else
-   rt_mutex_lock(>bus_lock);
+   rt_mutex_lock(>bus_lock);
 }
 
 /**
@@ -979,12 +974,7 @@ static void i2c_adapter_lock_bus(struct i2c_adapter 
*adapter,
 static int i2c_adapter_trylock_bus(struct i2c_adapter *adapter,
   unsigned 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(>bus_lock);
+   return rt_mutex_trylock(>bus_lock);
 }
 
 /**
@@ -996,12 +986,7 @@ static int i2c_adapter_trylock_bus(struct i2c_adapter 
*adapter,
 static void i2c_adapter_unlock_bus(struct i2c_adapter *adapter,
   unsigned int flags)
 {
-   struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
-
-   if (parent)
-   i2c_unlock_adapter(parent);
-   else
-   rt_mutex_unlock(>bus_lock);
+   rt_mutex_unlock(>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 25e9336b0e6e..5fa8af715e24 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -98,6 +98,33 @@ static unsigned int i2c_mux_parent_classes(struct 
i2c_adapter *parent)
return class;
 }
 
+static void i2c_parent_lock_bus(struct i2c_adapter *adapter,
+   unsigned 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,
+ unsigned 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,
+ unsigned int flags)
+{
+   struct i2c_mux_priv *priv = adapter->algo_data;
+   struct i2c_adapter *parent = priv->muxc->parent;
+
+   parent->unlock_bus(parent, flags);
+}
+
 struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
   struct device *dev, int max_adapters,
   int sizeof_priv, u32 flags,
@@ -165,6 +192,9 @@ int i2c_mux_add_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

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


[PATCH v9 3/9] i2c-mux: relax locking of the top i2c adapter during mux-locked muxing

2016-05-04 Thread Peter Rosin
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).

Introduce this new locking concept as "mux-locked" muxes, and call the
pre-existing mux locking scheme "parent-locked".

Modify the i2c mux locking so that muxes that are "mux-locked" locks only
the muxes on the parent adapter 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 muxes on the parent adapter.

Add code to i2c-mux-gpio and i2c-mux-pinctrl that checks if all involved
gpio/pinctrl devices have a parent that is an i2c adapter in the same
adapter tree that is muxed, and request a "mux-locked mux" if that is the
case.

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

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/i2c-core.c  |   1 +
 drivers/i2c/i2c-mux.c   | 152 +---
 drivers/i2c/muxes/i2c-mux-gpio.c|  18 +
 drivers/i2c/muxes/i2c-mux-pinctrl.c |  38 +
 include/linux/i2c-mux.h |   8 ++
 include/linux/i2c.h |   1 +
 6 files changed, 205 insertions(+), 13 deletions(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index afdee66002db..9da446162529 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1540,6 +1540,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
}
 
rt_mutex_init(>bus_lock);
+   rt_mutex_init(>mux_lock);
mutex_init(>userspace_clients_lock);
INIT_LIST_HEAD(>userspace_clients);
 
diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index 5fa8af715e24..8eee98634cda 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -35,6 +35,25 @@ struct i2c_mux_priv {
u32 chan_id;
 };
 
+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_master_xfer(struct i2c_adapter *adap,
   struct i2c_msg msgs[], int num)
 {
@@ -47,7 +66,29 @@ static int i2c_mux_master_xfer(struct i2c_adapter *adap,
 
ret = muxc->select(muxc, priv->chan_id);
if (ret >= 0)
-   ret = __i2c_transfer(parent, msgs, num);
+   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,
+   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 = parent->algo->smbus_xfer(parent, addr, flags,
+   read_writ

[PATCH v9 9/9] [media] rtl2832: regmap is aware of lockdep, drop local locking hack

2016-05-04 Thread Peter Rosin
Tested-by: Antti Palosaari <cr...@iki.fi>
Reviewed-by: Antti Palosaari <cr...@iki.fi>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/dvb-frontends/rtl2832.c  | 30 --
 drivers/media/dvb-frontends/rtl2832_priv.h |  1 -
 2 files changed, 31 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832.c 
b/drivers/media/dvb-frontends/rtl2832.c
index 957523f07f61..bfb6beedd40b 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -890,32 +890,6 @@ static bool rtl2832_volatile_reg(struct device *dev, 
unsigned int reg)
return false;
 }
 
-/*
- * FIXME: Hack. Implement own regmap locking in order to silence lockdep
- * recursive lock warning. That happens when regmap I2C client calls I2C mux
- * adapter, which leads demod I2C repeater enable via demod regmap. Operation
- * takes two regmap locks recursively - but those are different regmap 
instances
- * in a two different I2C drivers, so it is not deadlock. Proper fix is to make
- * regmap aware of lockdep.
- */
-static void rtl2832_regmap_lock(void *__dev)
-{
-   struct rtl2832_dev *dev = __dev;
-   struct i2c_client *client = dev->client;
-
-   dev_dbg(>dev, "\n");
-   mutex_lock(>regmap_mutex);
-}
-
-static void rtl2832_regmap_unlock(void *__dev)
-{
-   struct rtl2832_dev *dev = __dev;
-   struct i2c_client *client = dev->client;
-
-   dev_dbg(>dev, "\n");
-   mutex_unlock(>regmap_mutex);
-}
-
 static struct dvb_frontend *rtl2832_get_dvb_frontend(struct i2c_client *client)
 {
struct rtl2832_dev *dev = i2c_get_clientdata(client);
@@ -1082,12 +1056,8 @@ static int rtl2832_probe(struct i2c_client *client,
dev->sleeping = true;
INIT_DELAYED_WORK(>i2c_gate_work, rtl2832_i2c_gate_work);
/* create regmap */
-   mutex_init(>regmap_mutex);
dev->regmap_config.reg_bits =  8,
dev->regmap_config.val_bits =  8,
-   dev->regmap_config.lock = rtl2832_regmap_lock,
-   dev->regmap_config.unlock = rtl2832_regmap_unlock,
-   dev->regmap_config.lock_arg = dev,
dev->regmap_config.volatile_reg = rtl2832_volatile_reg,
dev->regmap_config.max_register = 5 * 0x100,
dev->regmap_config.ranges = regmap_range_cfg,
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h 
b/drivers/media/dvb-frontends/rtl2832_priv.h
index d8f97d14f6fd..c1a8a69e9015 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -33,7 +33,6 @@
 struct rtl2832_dev {
struct rtl2832_platform_data *pdata;
struct i2c_client *client;
-   struct mutex regmap_mutex;
struct regmap_config regmap_config;
struct regmap *regmap;
struct i2c_mux_core *muxc;
-- 
2.1.4

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


[PATCH v9 7/9] [media] rtl2832: change the i2c gate to be mux-locked

2016-05-04 Thread Peter Rosin
The root i2c adapter lock is then no longer held by the i2c mux during
accesses behind the i2c gate, and such accesses need to take that lock
just like any other ordinary i2c accesses do.

So, declare the i2c gate mux-locked, and zap the regmap overrides
that makes the i2c accesses unlocked and use plain old regmap
accesses. This also removes the need for the regmap wrappers used by
rtl2832_sdr, so deconvolute the code further and provide the regmap
handle directly instead of the wrapper functions.

Tested-by: Antti Palosaari <cr...@iki.fi>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/i2c/i2c-topology|   2 +-
 drivers/media/dvb-frontends/rtl2832.c | 190 --
 drivers/media/dvb-frontends/rtl2832.h |   4 +-
 drivers/media/dvb-frontends/rtl2832_sdr.c |  13 +-
 drivers/media/dvb-frontends/rtl2832_sdr.h |   5 +-
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c   |   5 +-
 6 files changed, 37 insertions(+), 182 deletions(-)

diff --git a/Documentation/i2c/i2c-topology b/Documentation/i2c/i2c-topology
index 5e40802f0be2..e0aefeece551 100644
--- a/Documentation/i2c/i2c-topology
+++ b/Documentation/i2c/i2c-topology
@@ -55,7 +55,7 @@ imu/inv_mpu6050/  Mux-locked
 In drivers/media/
 dvb-frontends/m88ds3103   Parent-locked
 dvb-frontends/rtl2830 Parent-locked
-dvb-frontends/rtl2832 Parent-locked
+dvb-frontends/rtl2832 Mux-locked
 dvb-frontends/si2168  Mux-locked
 usb/cx231xx/  Parent-locked
 
diff --git a/drivers/media/dvb-frontends/rtl2832.c 
b/drivers/media/dvb-frontends/rtl2832.c
index 1b23788797b5..957523f07f61 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -153,43 +153,6 @@ static const struct rtl2832_reg_entry registers[] = {
[DVBT_REG_4MSEL]= {0x013,  0, 0},
 };
 
-/* Our regmap is bypassing I2C adapter lock, thus we do it! */
-static int rtl2832_bulk_write(struct i2c_client *client, unsigned int reg,
- const void *val, size_t val_count)
-{
-   struct rtl2832_dev *dev = i2c_get_clientdata(client);
-   int ret;
-
-   i2c_lock_adapter(client->adapter);
-   ret = regmap_bulk_write(dev->regmap, reg, val, val_count);
-   i2c_unlock_adapter(client->adapter);
-   return ret;
-}
-
-static int rtl2832_update_bits(struct i2c_client *client, unsigned int reg,
-  unsigned int mask, unsigned int val)
-{
-   struct rtl2832_dev *dev = i2c_get_clientdata(client);
-   int ret;
-
-   i2c_lock_adapter(client->adapter);
-   ret = regmap_update_bits(dev->regmap, reg, mask, val);
-   i2c_unlock_adapter(client->adapter);
-   return ret;
-}
-
-static int rtl2832_bulk_read(struct i2c_client *client, unsigned int reg,
-void *val, size_t val_count)
-{
-   struct rtl2832_dev *dev = i2c_get_clientdata(client);
-   int ret;
-
-   i2c_lock_adapter(client->adapter);
-   ret = regmap_bulk_read(dev->regmap, reg, val, val_count);
-   i2c_unlock_adapter(client->adapter);
-   return ret;
-}
-
 static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, int reg, u32 *val)
 {
struct i2c_client *client = dev->client;
@@ -204,7 +167,7 @@ static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, 
int reg, u32 *val)
len = (msb >> 3) + 1;
mask = REG_MASK(msb - lsb);
 
-   ret = rtl2832_bulk_read(client, reg_start_addr, reading, len);
+   ret = regmap_bulk_read(dev->regmap, reg_start_addr, reading, len);
if (ret)
goto err;
 
@@ -234,7 +197,7 @@ static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, 
int reg, u32 val)
len = (msb >> 3) + 1;
mask = REG_MASK(msb - lsb);
 
-   ret = rtl2832_bulk_read(client, reg_start_addr, reading, len);
+   ret = regmap_bulk_read(dev->regmap, reg_start_addr, reading, len);
if (ret)
goto err;
 
@@ -248,7 +211,7 @@ static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, 
int reg, u32 val)
for (i = 0; i < len; i++)
writing[i] = (writing_tmp >> ((len - 1 - i) * 8)) & 0xff;
 
-   ret = rtl2832_bulk_write(client, reg_start_addr, writing, len);
+   ret = regmap_bulk_write(dev->regmap, reg_start_addr, writing, len);
if (ret)
goto err;
 
@@ -525,7 +488,8 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe)
}
 
for (j = 0; j < sizeof(bw_params[0]); j++) {
-   ret = rtl2832_bulk_write(client, 0x11c + j, _params[i][j], 
1);
+   ret = regmap_bulk_write(dev->regmap,
+   0x11c + j, _params[i][j], 1);
if (ret)
goto err;
}
@@ -581,11 +545,11 @@ static int rtl2832_get_frontend(struct dvb_frontend *fe,
if (dev->sleeping)
return 0;
 
-

[PATCH v9 8/9] [media] rtl2832_sdr: get rid of empty regmap wrappers

2016-05-04 Thread Peter Rosin
Tested-by: Antti Palosaari <cr...@iki.fi>
Reviewed-by: Antti Palosaari <cr...@iki.fi>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/dvb-frontends/rtl2832_sdr.c | 302 +-
 1 file changed, 132 insertions(+), 170 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c 
b/drivers/media/dvb-frontends/rtl2832_sdr.c
index 6a6b1debe277..47a480a7d46c 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -120,6 +120,7 @@ struct rtl2832_sdr_dev {
unsigned long flags;
 
struct platform_device *pdev;
+   struct regmap *regmap;
 
struct video_device vdev;
struct v4l2_device v4l2_dev;
@@ -164,47 +165,6 @@ struct rtl2832_sdr_dev {
unsigned long jiffies_next;
 };
 
-/* write multiple registers */
-static int rtl2832_sdr_wr_regs(struct rtl2832_sdr_dev *dev, u16 reg,
-   const u8 *val, int len)
-{
-   struct platform_device *pdev = dev->pdev;
-   struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
-   struct regmap *regmap = pdata->regmap;
-
-   return regmap_bulk_write(regmap, reg, val, len);
-}
-
-#if 0
-/* read multiple registers */
-static int rtl2832_sdr_rd_regs(struct rtl2832_sdr_dev *dev, u16 reg, u8 *val,
-   int len)
-{
-   struct platform_device *pdev = dev->pdev;
-   struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
-   struct regmap *regmap = pdata->regmap;
-
-   return regmap_bulk_read(regmap, reg, val, len);
-}
-#endif
-
-/* write single register */
-static int rtl2832_sdr_wr_reg(struct rtl2832_sdr_dev *dev, u16 reg, u8 val)
-{
-   return rtl2832_sdr_wr_regs(dev, reg, , 1);
-}
-
-/* write single register with mask */
-static int rtl2832_sdr_wr_reg_mask(struct rtl2832_sdr_dev *dev, u16 reg,
-   u8 val, u8 mask)
-{
-   struct platform_device *pdev = dev->pdev;
-   struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
-   struct regmap *regmap = pdata->regmap;
-
-   return regmap_update_bits(regmap, reg, mask, val);
-}
-
 /* Private functions */
 static struct rtl2832_sdr_frame_buf *rtl2832_sdr_get_next_fill_buf(
struct rtl2832_sdr_dev *dev)
@@ -559,11 +519,11 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev 
*dev)
 
f_sr = dev->f_adc;
 
-   ret = rtl2832_sdr_wr_regs(dev, 0x13e, "\x00\x00", 2);
+   ret = regmap_bulk_write(dev->regmap, 0x13e, "\x00\x00", 2);
if (ret)
goto err;
 
-   ret = rtl2832_sdr_wr_regs(dev, 0x115, "\x00\x00\x00\x00", 4);
+   ret = regmap_bulk_write(dev->regmap, 0x115, "\x00\x00\x00\x00", 4);
if (ret)
goto err;
 
@@ -589,7 +549,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev)
buf[1] = (u32tmp >>  8) & 0xff;
buf[2] = (u32tmp >>  0) & 0xff;
 
-   ret = rtl2832_sdr_wr_regs(dev, 0x119, buf, 3);
+   ret = regmap_bulk_write(dev->regmap, 0x119, buf, 3);
if (ret)
goto err;
 
@@ -603,15 +563,15 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev 
*dev)
u8tmp2 = 0xcd; /* enable ADC I, ADC Q */
}
 
-   ret = rtl2832_sdr_wr_reg(dev, 0x1b1, u8tmp1);
+   ret = regmap_write(dev->regmap, 0x1b1, u8tmp1);
if (ret)
goto err;
 
-   ret = rtl2832_sdr_wr_reg(dev, 0x008, u8tmp2);
+   ret = regmap_write(dev->regmap, 0x008, u8tmp2);
if (ret)
goto err;
 
-   ret = rtl2832_sdr_wr_reg(dev, 0x006, 0x80);
+   ret = regmap_write(dev->regmap, 0x006, 0x80);
if (ret)
goto err;
 
@@ -622,168 +582,169 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev 
*dev)
buf[1] = (u32tmp >> 16) & 0xff;
buf[2] = (u32tmp >>  8) & 0xff;
buf[3] = (u32tmp >>  0) & 0xff;
-   ret = rtl2832_sdr_wr_regs(dev, 0x19f, buf, 4);
+   ret = regmap_bulk_write(dev->regmap, 0x19f, buf, 4);
if (ret)
goto err;
 
/* low-pass filter */
-   ret = rtl2832_sdr_wr_regs(dev, 0x11c,
-   
"\xca\xdc\xd7\xd8\xe0\xf2\x0e\x35\x06\x50\x9c\x0d\x71\x11\x14\x71\x74\x19\x41\xa5",
-   20);
+   ret = regmap_bulk_write(dev->regmap, 0x11c,
+   
"\xca\xdc\xd7\xd8\xe0\xf2\x0e\x35\x06\x50\x9c\x0d\x71\x11\x14\x71\x74\x19\x41\xa5",
+   20);
if (ret)
goto err;
 
-   ret = rtl2832_sdr_wr_regs(dev, 0x017, "\x11\x10", 2);
+   ret = regmap_bulk_write(dev->regmap, 0x017, "\x11\x10", 2);
if (ret)
goto err;
 
/* mode */
-   ret = rtl2832_sdr_wr_regs(dev, 0x019, "\x05", 1);
+   ret 

[PATCH v9 6/9] [media] si2168: change the i2c gate to be mux-locked

2016-05-04 Thread Peter Rosin
From: Antti Palosaari <cr...@iki.fi>

The root i2c adapter lock is then no longer held by the i2c mux during
accesses behind the i2c gate, and such accesses need to take that lock
just like any other ordinary i2c accesses do.

So, declare the i2c gate mux-locked, and zap the code that makes the
i2c accesses unlocked. But add a mutex so that firmware commands are
still serialized.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/i2c/i2c-topology|  2 +-
 drivers/media/dvb-frontends/si2168.c  | 83 ---
 drivers/media/dvb-frontends/si2168_priv.h |  1 +
 3 files changed, 22 insertions(+), 64 deletions(-)

diff --git a/Documentation/i2c/i2c-topology b/Documentation/i2c/i2c-topology
index 69b008518454..5e40802f0be2 100644
--- a/Documentation/i2c/i2c-topology
+++ b/Documentation/i2c/i2c-topology
@@ -56,7 +56,7 @@ In drivers/media/
 dvb-frontends/m88ds3103   Parent-locked
 dvb-frontends/rtl2830 Parent-locked
 dvb-frontends/rtl2832 Parent-locked
-dvb-frontends/si2168  Parent-locked
+dvb-frontends/si2168  Mux-locked
 usb/cx231xx/  Parent-locked
 
 
diff --git a/drivers/media/dvb-frontends/si2168.c 
b/drivers/media/dvb-frontends/si2168.c
index 5583827c386e..108a069fa1ae 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -18,53 +18,23 @@
 
 static const struct dvb_frontend_ops si2168_ops;
 
-/* Own I2C adapter locking is needed because of I2C gate logic. */
-static int si2168_i2c_master_send_unlocked(const struct i2c_client *client,
-  const char *buf, int count)
-{
-   int ret;
-   struct i2c_msg msg = {
-   .addr = client->addr,
-   .flags = 0,
-   .len = count,
-   .buf = (char *)buf,
-   };
-
-   ret = __i2c_transfer(client->adapter, , 1);
-   return (ret == 1) ? count : ret;
-}
-
-static int si2168_i2c_master_recv_unlocked(const struct i2c_client *client,
-  char *buf, int count)
-{
-   int ret;
-   struct i2c_msg msg = {
-   .addr = client->addr,
-   .flags = I2C_M_RD,
-   .len = count,
-   .buf = buf,
-   };
-
-   ret = __i2c_transfer(client->adapter, , 1);
-   return (ret == 1) ? count : ret;
-}
-
 /* execute firmware command */
-static int si2168_cmd_execute_unlocked(struct i2c_client *client,
-  struct si2168_cmd *cmd)
+static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd 
*cmd)
 {
+   struct si2168_dev *dev = i2c_get_clientdata(client);
int ret;
unsigned long timeout;
 
+   mutex_lock(>i2c_mutex);
+
if (cmd->wlen) {
/* write cmd and args for firmware */
-   ret = si2168_i2c_master_send_unlocked(client, cmd->args,
- cmd->wlen);
+   ret = i2c_master_send(client, cmd->args, cmd->wlen);
if (ret < 0) {
-   goto err;
+   goto err_mutex_unlock;
} else if (ret != cmd->wlen) {
ret = -EREMOTEIO;
-   goto err;
+   goto err_mutex_unlock;
}
}
 
@@ -73,13 +43,12 @@ static int si2168_cmd_execute_unlocked(struct i2c_client 
*client,
#define TIMEOUT 70
timeout = jiffies + msecs_to_jiffies(TIMEOUT);
while (!time_after(jiffies, timeout)) {
-   ret = si2168_i2c_master_recv_unlocked(client, cmd->args,
- cmd->rlen);
+   ret = i2c_master_recv(client, cmd->args, cmd->rlen);
if (ret < 0) {
-   goto err;
+   goto err_mutex_unlock;
} else if (ret != cmd->rlen) {
ret = -EREMOTEIO;
-   goto err;
+   goto err_mutex_unlock;
}
 
/* firmware ready? */
@@ -94,32 +63,23 @@ static int si2168_cmd_execute_unlocked(struct i2c_client 
*client,
/* error bit set? */
if ((cmd->args[0] >> 6) & 0x01) {
ret = -EREMOTEIO;
-   goto err;
+   goto err_mutex_unlock;
}
 
if (!((cmd->args[0] >> 7) & 0x01)) {
ret = -ETIMEDOUT;
-   goto err;
+   goto err_mutex_unlock;
}
}
 
+   mutex_unlock(>i2c_mutex);
return 0;
-err:
+err_mutex_un

[PATCH v9 0/9] i2c mux cleanup and locking update

2016-05-04 Thread Peter Rosin
 i2c_mux_core:adapters into i2c_mux_core:num_adapters.
- Some grammar and spelling fixes.

v6 compared to v5:
- Rebase on top of v4.6-rc1
- Adjust to gpio subsystem overhaul.
- Adjust to changes in the inv_mpu6050 driver.
- Adjust to changes in the rtl2832 driver.
- Fix some new trivial checkpatch issues.
- Rename "self-locked" muxes "mux-locked" instead, since the lock has
  been moved to the parent adapter and is common for all muxes with
  the same parent adapter. The advantage is that address collisions
  behind sibling muxes are handled. Parent-locked muxes also grab this
  new mux-lock so that parent-locked and mux-locked siblings interact
  better.
- Firmware mutex added to the si2168 driver.

v5 compared to v4 (only published as a git branch):
- Rebase on top of v4.5-rc7.
- A new patch making me maintainer of i2c muxes (also sent separately).
- A new file Documentation/i2c/i2c-topology that describes various muxing
  issues.
- Rename "i2c-controlled" muxes "self-locked" instead, as it is perfectly
  reasonable to have i2c-controlled muxes that use the pre-existing locking
  scheme. The pre-existing locking scheme for i2c muxes is from here on
  called "parent-locked".
- Rename i2c-mux.c:i2c_mux_master_xfer to __i2c_mux_master_xfer since it
  calls __i2c_transfer, which leaves room for a new i2c_mux_master_xfer
  that calls i2c_transfer. Similar rename shuffle for i2c_mux_smbus_xfer.
- Use sizeof(*priv) instead of sizeof(struct i2c_mux_priv). One instance.
- Some follow-up patches that were posted in response to v2-v4 cleaning up
  and simplifying various i2c muxes outside drivers/i2c/, among those is
  an unrelated cleanup patch to drivers/media/dvb-frontends/rtl2832.c that
  I carry here since it conflicts (trivially) with this series. That
  unrelated patch is (currently) the last patch in the series.

v4 compared to v3:
- Rebase on top of v4.5-rc6.
- Update to add new i2c-mux interfaces in 01/18 including glue to implement
  the old interfaces in terms of the new interfaces, then change the
  mux users over to the new interfaces one by one (in 02/18 through 14/18),
  and finally removing the old interfaces in 15/18. I.e. the first 15
  patches of v4 replaces the first 5 patches of v3, with the following
  points describing changes in the end result. Each patch is now touching
  only one subsystem.
- Rename i2c_add_mux_adapter and i2c_del_mux_adapters to i2c_mux_add_adapter
  and i2c_mux_del_adapters (so that the old functions can live on during the
  transition).
- Make i2c_mux_alloc take a parent and the select/deselect ops as
  arguments. Also add a flags argument to prevent churn later on.
- Add a new interface i2c_mux_one_adapter(). Make use of it in suitable
  mux users with a single child adapter.
- Adjust to a rename in struct gpio_chip.
- Update a couple of comments to match the new code.

v3 compared to v2:
- Fix devm_kfree of a NULL pointer in i2c_mux_reserve_adapters().
- Remove device tree "i2c-controlled" property and determine this by walking
  the dev tree instead.
- Fix compile problems with inv_mpu_acpi.c
- Wait with adding the client pointer to patch 2/8 for pca9541 and pca954x.

v2 compared to v1:
- Allocate mux core and (optional) priv in a combined allocation.
- Kill dev_err messages triggered by memory allocation failure.
- Fix the device specific i2c muxes that I had overlooked.
- Rebase on top of v4.4-rc8 (was based on v4.4-rc6 previously).
- Drop the last two patches in the series.

Cheers,
Peter

Antti Palosaari (1):
  [media] si2168: change the i2c gate to be mux-locked

Peter Rosin (8):
  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 mux-locked muxing
  i2c-mux: document i2c muxes and elaborate on parent-/mux-locked muxes
  iio: imu: inv_mpu6050: change the i2c gate to be mux-locked
  [media] rtl2832: change the i2c gate to be mux-locked
  [media] rtl2832_sdr: get rid of empty regmap wrappers
  [media] rtl2832: regmap is aware of lockdep, drop local locking hack

 Documentation/i2c/i2c-topology | 370 +
 MAINTAINERS|   1 +
 drivers/i2c/i2c-core.c |  61 +++--
 drivers/i2c/i2c-mux.c  | 170 -
 drivers/i2c/muxes/i2c-mux-gpio.c   |  18 ++
 drivers/i2c/muxes/i2c-mux-pinctrl.c|  38 +++
 drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c  |  52 +---
 drivers/media/dvb-frontends/rtl2832.c  | 220 ++---
 drivers/media/dvb-frontends/rtl2832.h  |   4 +-
 drivers/media/dvb-frontends/rtl2832_priv.h |   1 -
 drivers/media/dvb-frontends/rtl2832_sdr.c  | 303 +++
 drivers/media/dvb-frontends/rtl2832_sdr.h  |   5 +-
 drivers/media/dvb-frontends/si2168.c   |  83 ++-
 drivers/media/dvb-frontends/si2168_priv.h  |   1 +
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c  

Re: [PATCH v7 16/24] i2c: allow adapter drivers to override the adapter locking

2016-05-04 Thread Peter Rosin


On 2016-05-03 23:39, Wolfram Sang wrote:
>> Yes, they look like reasonable complaints.
> 
> Thanks for fixing them. I just sent out my latest comments and when you
> fix those and send V8, I'll apply that right away. I think we are safe
> to fix the rest incrementally if needed. Note that I didn't review the

Sounds like a plan.

> IIO and media patches, I trust the reviewers on those.
> 
> Thanks for your work on this! I need a break now, this is
> mind-boggling...

And thanks for reviewing it!

A question on best practices here... I already did a v8 (but only as
a branch) so I think this will be v9, bit that's a minor detail. The
real question is what I should do about patches 1-15 that are already
in next? Send them too? If not, should I send 16-24 with the same old
patch numbers or should they be numbered 1-9 now? And should such a
shortened series be rebased on 1-15 in next?

Or does it not really matter?

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


Re: [PATCH v7 16/24] i2c: allow adapter drivers to override the adapter locking

2016-05-04 Thread Peter Rosin
Hi!

On 2016-05-03 23:38, Wolfram Sang wrote:
> On Wed, Apr 20, 2016 at 05:17:56PM +0200, Peter Rosin wrote:
>> 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.
> 
> Can you explain a little why it is SEGMENT and not ADAPTER here? That
> probably makes it easier to get into this patch.
> 
> And to double check my understanding: I was surprised to not see any
> i2c_lock_adapter() or I2C_LOCK_ADAPTER in action. This is because muxes
> call I2C_LOCK_SEGMENT on their parent which in case of the parent being
> the root adapter is essentially the same as I2C_LOCK_ADAPTER. Correct?

Correct. Locking the ADAPTER and the SEGMENT is the same thing for
the root adapter and for traditional muxes (i.e. not mux-locked).
Traditional muxes simply feed the locking request upwards to the
root adapter. The new mux-locked muxes behave the same for ADAPTER
locking; all locks all the way up to the root adapter are grabbed
instantly. If you instead lock SEGMENT on a mux-locked mux, only
the new mux lock in the parent adapter is grabbed right away, but
when the mux then fires off accesses on its parent adapter, that
triggers SEGMENT locks one level up in the tree and the process
recurses.

So, SEGMENT locking is the normal thing that happens when e.g. normal
i2c_transfer calls are made. ADAPTER locking is used for transactions.
The patch enables muxes to use more relaxed locking compared to
locking the ADAPTER for its transations.

The naming can probably be improved. SEGMENT made more sense when
it did not lock all mux accesses one level up (that changed in v6,
but I didn't change the I2C_LOCK_SEGMENT name at that time), so it
is kind of outdated. I2C_LOCK_ROOT_ADAPTER and I2C_LOCK_MUXES instead
of I2C_LOCK_ADAPTER and L2C_LOCK_SEGMENT perhaps?

But I don't really like I2C_LOCK_MUXES as I find it a bit too specific,
and people not thinking about i2c muxes at all (most people I gather,
ignorance is bliss) will not think that it is something for them...

It is also the case that the two flags are mutually exclusive, and
at this point there is no valid uses of using neither flag, nor for
using both. It is a binary decision and one flag would technically be
enough. So, not setting e.g. I2C_LOCK_ADAPTER could in theory imply
I2C_LOCK_SEGMENT. I did it as two separate flags since there might
be a third (or fourth even) option in the future (I don't see what
it would be though, I have no crystal ball...)

So maybe there should be only one flag, e.g. I2C_LOCK_ROOT_ADAPTER?
I.e. perhaps leave the future for later?

Hmmm, I just now realized that you were not really suggesting any
changes other than to the commit message. Oh well, I can perhaps
rephrase some of the above in the commit message if you think that
we should not unnecessarily touch the code at this point...

>>
>> Signed-off-by: Peter Rosin <p...@axentia.se>
>> ---
>>  drivers/i2c/i2c-core.c | 46 --
>>  include/linux/i2c.h| 28 ++--
>>  2 files changed, 54 insertions(+), 20 deletions(-)
>>
>> diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
>> index 0f2f8484e8ec..21f46d011c33 100644
>> --- a/drivers/i2c/i2c-core.c
>> +++ b/drivers/i2c/i2c-core.c
>> @@ -960,10 +960,12 @@ 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
>> + * @flags: I2C_LOCK_ADAPTER locks the root i2c adapter, I2C_LOCK_SEGMENT
>> + *  locks only this branch in the adapter tree
>>   */
> 
> I think this kerneldoc should be moved to i2c_lock_adapter and/or
> i2c_lock_bus() which are now in i2c.h. This is what users will use, not
> this static, adapter-specific implementation. I

Re: [PATCH v7 16/24] i2c: allow adapter drivers to override the adapter locking

2016-04-29 Thread Peter Rosin
On 2016-04-29 09:16, Wolfram Sang wrote:
>> Yes, obviously... I'll make that change locally and wait for the rest.
> Another nit: You could use '--strict' with checkpatch and see if you
> want to fix the issues reported. I am not keen on those (except for
> 'space around operators'), it's a matter of taste I guess, but maybe you
> like some of the suggestions.
>
Yes, they look like reasonable complaints.

So, I fixed all of them locally except the complaint about lack of comment
on the new struct mutex member in struct si2168_dev (patch 21/24),
because that patch is Anttis and he's the maintainer of that driver...

Antti, if you want that fixed as part of this series, send a suitable comment
for the mutex this way and I'll incorporate it.

Cheers,
Peter

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


Re: [PATCH v7 22/24] [media] rtl2832: change the i2c gate to be mux-locked

2016-04-28 Thread Peter Rosin
On 2016-04-28 23:47, Wolfram Sang wrote:
> On Wed, Apr 20, 2016 at 05:18:02PM +0200, Peter Rosin wrote:
>> The root i2c adapter lock is then no longer held by the i2c mux during
>> accesses behind the i2c gate, and such accesses need to take that lock
>> just like any other ordinary i2c accesses do.
>>
>> So, declare the i2c gate mux-locked, and zap the regmap overrides
>> that makes the i2c accesses unlocked and use plain old regmap
>> accesses. This also removes the need for the regmap wrappers used by
>> rtl2832_sdr, so deconvolute the code further and provide the regmap
>> handle directly instead of the wrapper functions.
>>
>> Signed-off-by: Peter Rosin <p...@axentia.se>
> Antti, I'd need some tag from you since this is not the i2c realm.
>

Antti sent this:

https://lkml.org/lkml/2016/4/20/828

and I added a Tested-by in v8

https://github.com/peda-r/i2c-mux/commit/c023584d34db7aacbc59f28386378131cfa970d2

but the patch was never sent as an email, only as part of a pull request for

https://github.com/peda-r/i2c-mux/commits/mux-core-and-locking-8

So, I think all is ok, or do you need more than Tested-by?

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


Re: [PATCH v7 16/24] i2c: allow adapter drivers to override the adapter locking

2016-04-28 Thread Peter Rosin


On 2016-04-28 22:50, Wolfram Sang wrote:
> On Wed, Apr 20, 2016 at 05:17:56PM +0200, Peter Rosin wrote:
>> 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 <p...@axentia.se>
> Letting you know that I start reviewing the 2nd part of your series. Did
> the first glimpse today. Will hopefully do the in-depth part this
> weekend. One thing already:
>
>> +static void i2c_adapter_lock_bus(struct i2c_adapter *adapter, int flags)
> Shouldn't flags be unsigned?
>

Yes, obviously... I'll make that change locally and wait for the rest.

Cheers,
Peter

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


Re: [PATCH v7 00/24] i2c mux cleanup and locking update

2016-04-22 Thread Peter Rosin
Wolfram Sang wrote:
> > The problem with waiting until 4.8 with the rest of the series is that it
> > will likely go stale, e.g. patch 22 ([media] rtl2832: change the i2c gate
> > to be mux-locked) touches a ton of register accesses in that driver since
> > it removes a regmap wrapper that is rendered obsolete. Expecting that
> > patch to work for 4.8 is overly optimistic, and while patching things up
> 
> Okay, that can be argued, I understand that. So, what about this
> suggestion: I pull in patches 1-15 today, and we schedule the rest of
> the patches for like next week or so. That still gives the first set of
> patches some time in linux-next for further exposure and testing whilst
> the whole series should arrive in 4.7.

That sounds really good, thanks!

> However, I need help with that. There are serious locking changes
> involved and ideally these patches are reviewed by multiple people,
> especially patches 16-19. I first want to say that the collaboration
> experience with this series was great so far, lots of testing and
> reporting back. Thanks for that already. Yet, if we want to have this in
> 4.7, this needs to be a group effort. So, if people interested could
> review even a little and report back this would be extremly helpful.

Yes please!

> > Third, should we deprecate the old i2c_add_mux_adapter, so that new
> > users do not crop up behind our backs in the transition? Or not bother?
> 
> Usually it is fine to change in-kernel-APIs when you take care that all
> current users are converted. But I am also fine with being nice and
> keeping the old call around for a few cycles. It is your call.

Ok, I'm a bit fed up with this series and will ignore it then.

> > Fourth, I forgot to change patch 8 (iio: imu: inv_mpu6050: convert to
> > use an explicit i2c mux core) to not change i2c_get_clientdata() ->
> > dev_get_drvdata() as requested by Jonathan Cameron. How should I handle
> > that?
> 
> I'll pull in the first patches this eveneing. You can choose to send me
> an incremental patch or resend patch 8. I am fine with both, but it
> should appear on the mailing list somehow.

I just sent a v8 of 08/24 (not sending a whole v8 for that though)

> > There are also some new Tested-by tags that I have added to my
> > local branch but have not pushed anywhere. I'm ready to push all that
> > to a new branch once you are ready to take it.
> 
> For the patches 1-15, I am ready when you are :)

Ok, I pushed out v8, see below. Pick what you want :-)

Cheers,
Peter

The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:

  Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)

are available in the git repository at:

  https://github.com/peda-r/i2c-mux.git mux-core-and-locking-8

for you to fetch changes up to b9a0ea3a309a3a4051c7c0cc54ade0eb5a877896:

  [media] rtl2832: regmap is aware of lockdep, drop local locking hack 
(2016-04-22 12:18:45 +0200)

----
Antti Palosaari (1):
  [media] si2168: change the i2c gate to be mux-locked

Peter Rosin (23):
  i2c-mux: add common data for every i2c-mux instance
  i2c: i2c-mux-gpio: convert to use an explicit i2c mux core
  i2c: i2c-mux-pinctrl: convert to use an explicit i2c mux core
  i2c: i2c-arb-gpio-challenge: convert to use an explicit i2c mux core
  i2c: i2c-mux-pca9541: convert to use an explicit i2c mux core
  i2c: i2c-mux-pca954x: convert to use an explicit i2c mux core
  i2c: i2c-mux-reg: convert to use an explicit i2c mux core
  iio: imu: inv_mpu6050: convert to use an explicit i2c mux core
  [media] m88ds3103: convert to use an explicit i2c mux core
  [media] rtl2830: convert to use an explicit i2c mux core
  [media] rtl2832: convert to use an explicit i2c mux core
  [media] si2168: convert to use an explicit i2c mux core
  [media] cx231xx: convert to use an explicit i2c mux core
  of/unittest: convert to use an explicit i2c mux core
  i2c-mux: drop old unused i2c-mux api
  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 mux-locked muxing
  i2c-mux: document i2c muxes and elaborate on parent-/mux-locked muxes
  iio: imu: inv_mpu6050: change the i2c gate to be mux-locked
  [media] rtl2832: change the i2c gate to be mux-locked
  [media] rtl2832_sdr: get rid of empty regmap wrappers
  [media] rtl2832: regmap is aware of lockdep, drop local locking hack

 Documentation/i2c/i2c-topology   | 370 +++
 MAINTAINERS  |   1 +
 drivers/i2c/i2c-core.c   |  66 +++--
 drivers/i2c/i2c-mux.c| 297 -
 drivers/i2

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

2016-04-22 Thread Peter Rosin
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.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@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  | 33 +++---
 drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h  |  3 ++-
 4 files changed, 19 insertions(+), 20 deletions(-)

v8 compared to v7:
- Do not change i2c_get_clientdata() into dev_get_drvdata()

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, );
+   st->mux_client = i2c_new_device(st->muxc->adapter[0], );
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 
 #include 
 #include 
-#include 
 #include 
 #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..3a078df84224 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 
 #include 
 #include 
-#include 
 #include 
 #include 
 #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(>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(>dev);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
 
@@ -136,16 +133,18 @@ static int inv_mpu_probe(struct i2c_client *client,
return result;
 
st = iio_priv(dev_get_drvdata(>dev));
-   st->mux_adapter = i2c_add_mux_adapter(client->adapter,
- >dev,
- client,
- 0, 0, 0,
- inv_mpu6050_select_bypass,
- inv_mpu6050_deselect_bypass);
-   if (!st->mux_adapter) {
-   result = -ENODEV;
+   st->muxc = i2c_mux_alloc(client->adapter, >dev,
+1, 0, 0,
+inv_mpu6050_select_bypass,
+inv_mpu6050_deselect_bypass);
+   if (!st->muxc) {
+   result = -ENOMEM;
goto out_unreg_device;
}
+   st->muxc->priv = dev_get_drvdata(>dev);
+   result = i2c_mux_add_adapter(st->muxc, 0, 0, 0);
+   if (result)
+   goto out_unreg_device;
 
result = inv_mpu_acpi_create_mux_client(client);
if (result)
@@ -154,7 +153,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(>dev);
return result;
@@ -166,7 +165,7 @@ static int inv_mpu_remove(struct i2c_client *client)
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(>dev);
 }
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h 
b/dr

Re: [PATCH v7 00/24] i2c mux cleanup and locking update

2016-04-22 Thread Peter Rosin
Hi Wolfram,

Wolfram Sang wrote:
> This was the diff of v6:
> 
> >  32 files changed, 1277 insertions(+), 915 deletions(-)
> 
> This is v7:
> 
> >  32 files changed, 1225 insertions(+), 916 deletions(-)
> 
> So, we gained a little overall. And while the individual drivers have a
> few lines more now, I still think it is more readable.
> 
> So, thanks for doing that!

Most, if not all, of these ~50 lines gained in v7 come from removing
i2c_mux_reserve_adapters and realloc. I.e., I think we might even have
lost a few lines with the i2c_mux_one_adapter removal, but not that many.
If the doc patch is taken out of the equation, we gain new functionality,
fix a bug and lose lines of code. Feels good!
However, this is not why I'm writing this message...

> I'll give people some time for testing. I'll have a further look, too.
> Hopefully, I can pick up patches 1-14 by the end of the week.

The reason for this message is that I just realized a couple of things.

First, you have suggested to merge patches 1-14 about now, and I assumed
that implied merging with Linus for 4.6, but on rereading I realize that
you have consistently targeted 4.7. I must be sloppy, and that had escaped
me. Is it really necessary to be that cautious? Maybe I'm overly confident,
but is 1-14 really such a big deal that it has to float in next for a whole
cycle?

The problem with waiting until 4.8 with the rest of the series is that it
will likely go stale, e.g. patch 22 ([media] rtl2832: change the i2c gate
to be mux-locked) touches a ton of register accesses in that driver since
it removes a regmap wrapper that is rendered obsolete. Expecting that
patch to work for 4.8 is overly optimistic, and while patching things up
is (probably) easy, it also renders any previous testing suspect.

That said, maybe I'm just impatient and reckless?

Second, should we not add 15-24 to the next branch now as well to get
testing going asap, even if we do not intend to merge it just yet or even
in that exact form? Or is that abusing the next branch?

Third, should we deprecate the old i2c_add_mux_adapter, so that new
users do not crop up behind our backs in the transition? Or not bother?

Fourth, I forgot to change patch 8 (iio: imu: inv_mpu6050: convert to
use an explicit i2c mux core) to not change i2c_get_clientdata() ->
dev_get_drvdata() as requested by Jonathan Cameron. How should I handle
that? There are also some new Tested-by tags that I have added to my
local branch but have not pushed anywhere. I'm ready to push all that
to a new branch once you are ready to take it.

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


[PATCH v7 22/24] [media] rtl2832: change the i2c gate to be mux-locked

2016-04-20 Thread Peter Rosin
The root i2c adapter lock is then no longer held by the i2c mux during
accesses behind the i2c gate, and such accesses need to take that lock
just like any other ordinary i2c accesses do.

So, declare the i2c gate mux-locked, and zap the regmap overrides
that makes the i2c accesses unlocked and use plain old regmap
accesses. This also removes the need for the regmap wrappers used by
rtl2832_sdr, so deconvolute the code further and provide the regmap
handle directly instead of the wrapper functions.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/i2c/i2c-topology|   2 +-
 drivers/media/dvb-frontends/rtl2832.c | 190 --
 drivers/media/dvb-frontends/rtl2832.h |   4 +-
 drivers/media/dvb-frontends/rtl2832_sdr.c |  13 +-
 drivers/media/dvb-frontends/rtl2832_sdr.h |   5 +-
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c   |   5 +-
 6 files changed, 37 insertions(+), 182 deletions(-)

diff --git a/Documentation/i2c/i2c-topology b/Documentation/i2c/i2c-topology
index 5e40802f0be2..e0aefeece551 100644
--- a/Documentation/i2c/i2c-topology
+++ b/Documentation/i2c/i2c-topology
@@ -55,7 +55,7 @@ imu/inv_mpu6050/  Mux-locked
 In drivers/media/
 dvb-frontends/m88ds3103   Parent-locked
 dvb-frontends/rtl2830 Parent-locked
-dvb-frontends/rtl2832 Parent-locked
+dvb-frontends/rtl2832 Mux-locked
 dvb-frontends/si2168  Mux-locked
 usb/cx231xx/  Parent-locked
 
diff --git a/drivers/media/dvb-frontends/rtl2832.c 
b/drivers/media/dvb-frontends/rtl2832.c
index 1b23788797b5..957523f07f61 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -153,43 +153,6 @@ static const struct rtl2832_reg_entry registers[] = {
[DVBT_REG_4MSEL]= {0x013,  0, 0},
 };
 
-/* Our regmap is bypassing I2C adapter lock, thus we do it! */
-static int rtl2832_bulk_write(struct i2c_client *client, unsigned int reg,
- const void *val, size_t val_count)
-{
-   struct rtl2832_dev *dev = i2c_get_clientdata(client);
-   int ret;
-
-   i2c_lock_adapter(client->adapter);
-   ret = regmap_bulk_write(dev->regmap, reg, val, val_count);
-   i2c_unlock_adapter(client->adapter);
-   return ret;
-}
-
-static int rtl2832_update_bits(struct i2c_client *client, unsigned int reg,
-  unsigned int mask, unsigned int val)
-{
-   struct rtl2832_dev *dev = i2c_get_clientdata(client);
-   int ret;
-
-   i2c_lock_adapter(client->adapter);
-   ret = regmap_update_bits(dev->regmap, reg, mask, val);
-   i2c_unlock_adapter(client->adapter);
-   return ret;
-}
-
-static int rtl2832_bulk_read(struct i2c_client *client, unsigned int reg,
-void *val, size_t val_count)
-{
-   struct rtl2832_dev *dev = i2c_get_clientdata(client);
-   int ret;
-
-   i2c_lock_adapter(client->adapter);
-   ret = regmap_bulk_read(dev->regmap, reg, val, val_count);
-   i2c_unlock_adapter(client->adapter);
-   return ret;
-}
-
 static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, int reg, u32 *val)
 {
struct i2c_client *client = dev->client;
@@ -204,7 +167,7 @@ static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, 
int reg, u32 *val)
len = (msb >> 3) + 1;
mask = REG_MASK(msb - lsb);
 
-   ret = rtl2832_bulk_read(client, reg_start_addr, reading, len);
+   ret = regmap_bulk_read(dev->regmap, reg_start_addr, reading, len);
if (ret)
goto err;
 
@@ -234,7 +197,7 @@ static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, 
int reg, u32 val)
len = (msb >> 3) + 1;
mask = REG_MASK(msb - lsb);
 
-   ret = rtl2832_bulk_read(client, reg_start_addr, reading, len);
+   ret = regmap_bulk_read(dev->regmap, reg_start_addr, reading, len);
if (ret)
goto err;
 
@@ -248,7 +211,7 @@ static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, 
int reg, u32 val)
for (i = 0; i < len; i++)
writing[i] = (writing_tmp >> ((len - 1 - i) * 8)) & 0xff;
 
-   ret = rtl2832_bulk_write(client, reg_start_addr, writing, len);
+   ret = regmap_bulk_write(dev->regmap, reg_start_addr, writing, len);
if (ret)
goto err;
 
@@ -525,7 +488,8 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe)
}
 
for (j = 0; j < sizeof(bw_params[0]); j++) {
-   ret = rtl2832_bulk_write(client, 0x11c + j, _params[i][j], 
1);
+   ret = regmap_bulk_write(dev->regmap,
+   0x11c + j, _params[i][j], 1);
if (ret)
goto err;
}
@@ -581,11 +545,11 @@ static int rtl2832_get_frontend(struct dvb_frontend *fe,
if (dev->sleeping)
return 0;
 
-   ret = rtl2832_bulk_read(client, 0x33c, buf, 

[PATCH v7 06/24] i2c: i2c-mux-pca954x: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
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.

Add a mask to handle the case where not all child adapters should
cause a mux deselect to happen, now that there is a common deselect op
for all child adapters.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/muxes/i2c-mux-pca954x.c | 61 ++---
 1 file changed, 30 insertions(+), 31 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c 
b/drivers/i2c/muxes/i2c-mux-pca954x.c
index acfcef3d4068..528e755c468f 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -60,9 +60,10 @@ 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;
+   struct i2c_client *client;
 };
 
 struct chip_desc {
@@ -146,10 +147,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 = [data->type];
u8 regval;
int ret = 0;
@@ -162,21 +163,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);
 }
 
 /*
@@ -191,17 +195,22 @@ 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(>dev, sizeof(struct pca954x), GFP_KERNEL);
-   if (!data)
+   muxc = i2c_mux_alloc(adap, >dev,
+PCA954X_MAX_NCHANS, sizeof(*data), 0,
+pca954x_select_chan, pca954x_deselect_mux);
+   if (!muxc)
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(>dev, "reset", GPIOD_OUT_LOW);
@@ -238,16 +247,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(adap, >dev, client,
-   force, num, class, pca954x_select_chan,
-   (idle_disconnect_pd || idle_disconnect_dt)
-   ? pca954x_deselect_mux : NULL);
+   ret = i2c_mux_add_adapter(muxc, force, num, class);
 
-   if (data->virt_adaps[num] == NULL) {
-   ret = -ENODEV;
+   if (ret) {
dev_err(>dev,
"failed to register multiplexed adapter"
" %d as bus %d\n", num, force);
@@ -263,23 +269,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

[PATCH v7 16/24] i2c: allow adapter drivers to override the adapter locking

2016-04-20 Thread Peter Rosin
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 <p...@axentia.se>
---
 drivers/i2c/i2c-core.c | 46 --
 include/linux/i2c.h| 28 ++--
 2 files changed, 54 insertions(+), 20 deletions(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 0f2f8484e8ec..21f46d011c33 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -960,10 +960,12 @@ 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
+ * @flags: I2C_LOCK_ADAPTER locks the root i2c adapter, I2C_LOCK_SEGMENT
+ * locks only this branch in the adapter tree
  */
-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);
 
@@ -972,27 +974,30 @@ void i2c_lock_adapter(struct i2c_adapter *adapter)
else
rt_mutex_lock(>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
+ * @flags: I2C_LOCK_ADAPTER trylocks the root i2c adapter, I2C_LOCK_SEGMENT
+ * trylocks only this branch in the adapter tree
  */
-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(>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
+ * @flags: I2C_LOCK_ADAPTER unlocks the root i2c adapter, I2C_LOCK_SEGMENT
+ * unlocks only this branch in the adapter tree
  */
-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);
 
@@ -1001,7 +1006,6 @@ void i2c_unlock_adapter(struct i2c_adapter *adapter)
else
rt_mutex_unlock(>bus_lock);
 }
-EXPORT_SYMBOL_GPL(i2c_unlock_adapter);
 
 static void i2c_dev_set_name(struct i2c_adapter *adap,
 struct i2c_client *client)
@@ -1547,6 +1551,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(>bus_lock);
mutex_init(>userspace_clients_lock);
INIT_LIST_HEAD(>userspace_clients);
@@ -2315,16 +2325,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 {
@@ -3099,7 +3109,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 

[PATCH v7 19/24] i2c-mux: document i2c muxes and elaborate on parent-/mux-locked muxes

2016-04-20 Thread Peter Rosin
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/i2c/i2c-topology | 370 +
 MAINTAINERS|   1 +
 2 files changed, 371 insertions(+)
 create mode 100644 Documentation/i2c/i2c-topology

diff --git a/Documentation/i2c/i2c-topology b/Documentation/i2c/i2c-topology
new file mode 100644
index ..27bfd682808d
--- /dev/null
+++ b/Documentation/i2c/i2c-topology
@@ -0,0 +1,370 @@
+I2C topology
+
+
+There are a couple of reasons for building more complex i2c topologies
+than a straight-forward i2c bus with one adapter and one or more devices.
+
+1. A mux may be needed on the bus to prevent address collisions.
+
+2. The bus may be accessible from some external bus master, and arbitration
+   may be needed to determine if it is ok to access the bus.
+
+3. A device (particularly RF tuners) may want to avoid the digital noise
+   from the i2c bus, at least most of the time, and sits behind a gate
+   that has to be operated before the device can be accessed.
+
+Etc
+
+These constructs are represented as i2c adapter trees by Linux, where
+each adapter has a parent adapter (except the root adapter) and zero or
+more child adapters. The root adapter is the actual adapter that issues
+i2c transfers, and all adapters with a parent are part of an "i2c-mux"
+object (quoted, since it can also be an arbitrator or a gate).
+
+Depending of the particular mux driver, something happens when there is
+an i2c transfer on one of its child adapters. The mux driver can
+obviously operate a mux, but it can also do arbitration with an external
+bus master or open a gate. The mux driver has two operations for this,
+select and deselect. select is called before the transfer and (the
+optional) deselect is called after the transfer.
+
+
+Locking
+===
+
+There are two variants of locking available to i2c muxes, they can be
+mux-locked or parent-locked muxes. As is evident from below, it can be
+useful to know if a mux is mux-locked or if it is parent-locked. The
+following list was correct at the time of writing:
+
+In drivers/i2c/muxes/
+i2c-arb-gpio-challengeParent-locked
+i2c-mux-gpio  Normally parent-locked, mux-locked iff
+  all involved gpio pins are controlled by the
+  same i2c root adapter that they mux.
+i2c-mux-pca9541   Parent-locked
+i2c-mux-pca954x   Parent-locked
+i2c-mux-pinctrl   Normally parent-locked, mux-locked iff
+  all involved pinctrl devices are controlled
+  by the same i2c root adapter that they mux.
+i2c-mux-reg   Parent-locked
+
+In drivers/iio/
+imu/inv_mpu6050/  Parent-locked
+
+In drivers/media/
+dvb-frontends/m88ds3103   Parent-locked
+dvb-frontends/rtl2830 Parent-locked
+dvb-frontends/rtl2832 Parent-locked
+dvb-frontends/si2168  Parent-locked
+usb/cx231xx/  Parent-locked
+
+
+Mux-locked muxes
+
+
+Mux-locked muxes does not lock the entire parent adapter during the
+full select-transfer-deselect transaction, only the muxes on the parent
+adapter are locked. Mux-locked muxes are mostly interesting if the
+select and/or deselect operations must use i2c transfers to complete
+their tasks. Since the parent adapter is not fully locked during the
+full transaction, unrelated i2c transfers may interleave the different
+stages of the transaction. This has the benefit that the mux driver
+may be easier and cleaner to implement, but it has some caveats.
+
+ML1. If you build a topology with a mux-locked mux being the parent
+ of a parent-locked mux, this might break the expectation from the
+ parent-locked mux that the root adapter is locked during the
+ transaction.
+
+ML2. It is not safe to build arbitrary topologies with two (or more)
+ mux-locked muxes that are not siblings, when there are address
+ collisions between the devices on the child adapters of these
+ non-sibling muxes.
+
+ I.e. the select-transfer-deselect transaction targeting e.g. device
+ address 0x42 behind mux-one may be interleaved with a similar
+ operation targeting device address 0x42 behind mux-two. The
+ intension with such a topology would in this hypothetical example
+ be that mux-one and mux-two should not be selected simultaneously,
+ but mux-locked muxes do not guarantee that in all topologies.
+
+ML3. A mux-locked mux cannot be used by a driver for auto-closing
+ gates/muxes, i.e. something that closes automatically after a given
+ number (one, in most cases) of i2c transfers. Unrelated i2c transfers
+ may creep in and close prematurely.
+
+ML4. If any non-i2c operation in the mux driver changes the i2c mux state,
+ the driver has to lock the root adapter during that operation.
+ Otherwise garbage may appear on the bus as seen from devices
+ behind the mux, when 

[PATCH v7 11/24] [media] rtl2832: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
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.

Reviewed-by: Antti Palosaari <cr...@iki.fi>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/dvb-frontends/rtl2832.c  | 25 ++---
 drivers/media/dvb-frontends/rtl2832_priv.h |  2 +-
 2 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832.c 
b/drivers/media/dvb-frontends/rtl2832.c
index 7c96f7679669..1b23788797b5 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -847,9 +847,9 @@ err:
dev_dbg(>dev, "failed=%d\n", ret);
 }
 
-static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 
chan_id)
+static int rtl2832_select(struct i2c_mux_core *muxc, u32 chan_id)
 {
-   struct rtl2832_dev *dev = mux_priv;
+   struct rtl2832_dev *dev = i2c_mux_priv(muxc);
struct i2c_client *client = dev->client;
int ret;
 
@@ -870,10 +870,9 @@ err:
return ret;
 }
 
-static int rtl2832_deselect(struct i2c_adapter *adap, void *mux_priv,
-   u32 chan_id)
+static int rtl2832_deselect(struct i2c_mux_core *muxc, u32 chan_id)
 {
-   struct rtl2832_dev *dev = mux_priv;
+   struct rtl2832_dev *dev = i2c_mux_priv(muxc);
 
schedule_delayed_work(>i2c_gate_work, usecs_to_jiffies(100));
return 0;
@@ -1059,7 +1058,7 @@ static struct i2c_adapter *rtl2832_get_i2c_adapter(struct 
i2c_client *client)
struct rtl2832_dev *dev = i2c_get_clientdata(client);
 
dev_dbg(>dev, "\n");
-   return dev->i2c_adapter_tuner;
+   return dev->muxc->adapter[0];
 }
 
 static int rtl2832_slave_ts_ctrl(struct i2c_client *client, bool enable)
@@ -1242,12 +1241,16 @@ static int rtl2832_probe(struct i2c_client *client,
goto err_regmap_exit;
 
/* create muxed i2c adapter for demod tuner bus */
-   dev->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, >dev, dev,
-   0, 0, 0, rtl2832_select, rtl2832_deselect);
-   if (dev->i2c_adapter_tuner == NULL) {
-   ret = -ENODEV;
+   dev->muxc = i2c_mux_alloc(i2c, >dev, 1, 0, 0,
+ rtl2832_select, rtl2832_deselect);
+   if (!dev->muxc) {
+   ret = -ENOMEM;
goto err_regmap_exit;
}
+   dev->muxc->priv = dev;
+   ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0);
+   if (ret)
+   goto err_regmap_exit;
 
/* create dvb_frontend */
memcpy(>fe.ops, _ops, sizeof(struct dvb_frontend_ops));
@@ -1282,7 +1285,7 @@ static int rtl2832_remove(struct i2c_client *client)
 
cancel_delayed_work_sync(>i2c_gate_work);
 
-   i2c_del_mux_adapter(dev->i2c_adapter_tuner);
+   i2c_mux_del_adapters(dev->muxc);
 
regmap_exit(dev->regmap);
 
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h 
b/drivers/media/dvb-frontends/rtl2832_priv.h
index 6b875f462f8b..d8f97d14f6fd 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -36,7 +36,7 @@ struct rtl2832_dev {
struct mutex regmap_mutex;
struct regmap_config regmap_config;
struct regmap *regmap;
-   struct i2c_adapter *i2c_adapter_tuner;
+   struct i2c_mux_core *muxc;
struct dvb_frontend fe;
enum fe_status fe_status;
u64 post_bit_error_prev; /* for old DVBv3 read_ber() calculation */
-- 
2.1.4

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


[PATCH v7 21/24] [media] si2168: change the i2c gate to be mux-locked

2016-04-20 Thread Peter Rosin
From: Antti Palosaari <cr...@iki.fi>

The root i2c adapter lock is then no longer held by the i2c mux during
accesses behind the i2c gate, and such accesses need to take that lock
just like any other ordinary i2c accesses do.

So, declare the i2c gate mux-locked, and zap the code that makes the
i2c accesses unlocked. But add a mutex so that firmware commands are
still serialized.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/i2c/i2c-topology|  2 +-
 drivers/media/dvb-frontends/si2168.c  | 83 ---
 drivers/media/dvb-frontends/si2168_priv.h |  1 +
 3 files changed, 22 insertions(+), 64 deletions(-)

diff --git a/Documentation/i2c/i2c-topology b/Documentation/i2c/i2c-topology
index 69b008518454..5e40802f0be2 100644
--- a/Documentation/i2c/i2c-topology
+++ b/Documentation/i2c/i2c-topology
@@ -56,7 +56,7 @@ In drivers/media/
 dvb-frontends/m88ds3103   Parent-locked
 dvb-frontends/rtl2830 Parent-locked
 dvb-frontends/rtl2832 Parent-locked
-dvb-frontends/si2168  Parent-locked
+dvb-frontends/si2168  Mux-locked
 usb/cx231xx/  Parent-locked
 
 
diff --git a/drivers/media/dvb-frontends/si2168.c 
b/drivers/media/dvb-frontends/si2168.c
index 5583827c386e..108a069fa1ae 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -18,53 +18,23 @@
 
 static const struct dvb_frontend_ops si2168_ops;
 
-/* Own I2C adapter locking is needed because of I2C gate logic. */
-static int si2168_i2c_master_send_unlocked(const struct i2c_client *client,
-  const char *buf, int count)
-{
-   int ret;
-   struct i2c_msg msg = {
-   .addr = client->addr,
-   .flags = 0,
-   .len = count,
-   .buf = (char *)buf,
-   };
-
-   ret = __i2c_transfer(client->adapter, , 1);
-   return (ret == 1) ? count : ret;
-}
-
-static int si2168_i2c_master_recv_unlocked(const struct i2c_client *client,
-  char *buf, int count)
-{
-   int ret;
-   struct i2c_msg msg = {
-   .addr = client->addr,
-   .flags = I2C_M_RD,
-   .len = count,
-   .buf = buf,
-   };
-
-   ret = __i2c_transfer(client->adapter, , 1);
-   return (ret == 1) ? count : ret;
-}
-
 /* execute firmware command */
-static int si2168_cmd_execute_unlocked(struct i2c_client *client,
-  struct si2168_cmd *cmd)
+static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd 
*cmd)
 {
+   struct si2168_dev *dev = i2c_get_clientdata(client);
int ret;
unsigned long timeout;
 
+   mutex_lock(>i2c_mutex);
+
if (cmd->wlen) {
/* write cmd and args for firmware */
-   ret = si2168_i2c_master_send_unlocked(client, cmd->args,
- cmd->wlen);
+   ret = i2c_master_send(client, cmd->args, cmd->wlen);
if (ret < 0) {
-   goto err;
+   goto err_mutex_unlock;
} else if (ret != cmd->wlen) {
ret = -EREMOTEIO;
-   goto err;
+   goto err_mutex_unlock;
}
}
 
@@ -73,13 +43,12 @@ static int si2168_cmd_execute_unlocked(struct i2c_client 
*client,
#define TIMEOUT 70
timeout = jiffies + msecs_to_jiffies(TIMEOUT);
while (!time_after(jiffies, timeout)) {
-   ret = si2168_i2c_master_recv_unlocked(client, cmd->args,
- cmd->rlen);
+   ret = i2c_master_recv(client, cmd->args, cmd->rlen);
if (ret < 0) {
-   goto err;
+   goto err_mutex_unlock;
} else if (ret != cmd->rlen) {
ret = -EREMOTEIO;
-   goto err;
+   goto err_mutex_unlock;
}
 
/* firmware ready? */
@@ -94,32 +63,23 @@ static int si2168_cmd_execute_unlocked(struct i2c_client 
*client,
/* error bit set? */
if ((cmd->args[0] >> 6) & 0x01) {
ret = -EREMOTEIO;
-   goto err;
+   goto err_mutex_unlock;
}
 
if (!((cmd->args[0] >> 7) & 0x01)) {
ret = -ETIMEDOUT;
-   goto err;
+   goto err_mutex_unlock;
}
}
 
+   mutex_unlock(>i2c_mutex);
return 0;
-err:
+err_mutex_un

[PATCH v7 09/24] [media] m88ds3103: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select op to be in terms of the i2c mux core instead
of the child adapter.

Reviewed-by: Antti Palosaari <cr...@iki.fi>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/dvb-frontends/m88ds3103.c  | 19 +++
 drivers/media/dvb-frontends/m88ds3103_priv.h |  2 +-
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/media/dvb-frontends/m88ds3103.c 
b/drivers/media/dvb-frontends/m88ds3103.c
index 76883600ec6f..5557ef8fc704 100644
--- a/drivers/media/dvb-frontends/m88ds3103.c
+++ b/drivers/media/dvb-frontends/m88ds3103.c
@@ -1251,9 +1251,9 @@ static void m88ds3103_release(struct dvb_frontend *fe)
i2c_unregister_device(client);
 }
 
-static int m88ds3103_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
+static int m88ds3103_select(struct i2c_mux_core *muxc, u32 chan)
 {
-   struct m88ds3103_dev *dev = mux_priv;
+   struct m88ds3103_dev *dev = i2c_mux_priv(muxc);
struct i2c_client *client = dev->client;
int ret;
struct i2c_msg msg = {
@@ -1374,7 +1374,7 @@ static struct i2c_adapter 
*m88ds3103_get_i2c_adapter(struct i2c_client *client)
 
dev_dbg(>dev, "\n");
 
-   return dev->i2c_adapter;
+   return dev->muxc->adapter[0];
 }
 
 static int m88ds3103_probe(struct i2c_client *client,
@@ -1467,13 +1467,16 @@ static int m88ds3103_probe(struct i2c_client *client,
goto err_kfree;
 
/* create mux i2c adapter for tuner */
-   dev->i2c_adapter = i2c_add_mux_adapter(client->adapter, >dev,
-  dev, 0, 0, 0, m88ds3103_select,
-  NULL);
-   if (dev->i2c_adapter == NULL) {
+   dev->muxc = i2c_mux_alloc(client->adapter, >dev, 1, 0, 0,
+ m88ds3103_select, NULL);
+   if (!dev->muxc) {
ret = -ENOMEM;
goto err_kfree;
}
+   dev->muxc->priv = dev;
+   ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0);
+   if (ret)
+   goto err_kfree;
 
/* create dvb_frontend */
memcpy(>fe.ops, _ops, sizeof(struct dvb_frontend_ops));
@@ -1502,7 +1505,7 @@ static int m88ds3103_remove(struct i2c_client *client)
 
dev_dbg(>dev, "\n");
 
-   i2c_del_mux_adapter(dev->i2c_adapter);
+   i2c_mux_del_adapters(dev->muxc);
 
kfree(dev);
return 0;
diff --git a/drivers/media/dvb-frontends/m88ds3103_priv.h 
b/drivers/media/dvb-frontends/m88ds3103_priv.h
index eee8c22c51ec..c5b4e177c6ea 100644
--- a/drivers/media/dvb-frontends/m88ds3103_priv.h
+++ b/drivers/media/dvb-frontends/m88ds3103_priv.h
@@ -42,7 +42,7 @@ struct m88ds3103_dev {
enum fe_status fe_status;
u32 dvbv3_ber; /* for old DVBv3 API read_ber */
bool warm; /* FW running */
-   struct i2c_adapter *i2c_adapter;
+   struct i2c_mux_core *muxc;
/* auto detect chip id to do different config */
u8 chip_id;
/* main mclk is calculated for M88RS6000 dynamically */
-- 
2.1.4

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


[PATCH v7 20/24] iio: imu: inv_mpu6050: change the i2c gate to be mux-locked

2016-04-20 Thread Peter Rosin
The root i2c adapter lock is then no longer held by the i2c mux during
accesses behind the i2c gate, and such accesses need to take that lock
just like any other ordinary i2c accesses do.

So, declare the i2c gate mux-locked, and zap the code that makes the
unlocked i2c accesses and just use ordinary regmap_write accesses.

This also happens to fix the deadlock described in
http://patchwork.ozlabs.org/patch/584776/ authored by
Adriana Reus <adriana.r...@intel.com> and submitted by
Daniel Baluta <daniel.bal...@intel.com>

--8<--
iio: imu: inv_mpu6050: Fix deadlock between i2c adapter lock and mpu lock

This deadlock occurs if the accel/gyro and the sensor on the auxiliary
I2C (in my setup it's an ak8975) are working at the same time.

Scenario:

  T1T2
   
inv_mpu6050_read_fifo  aux sensor op (eg. ak8975_read_raw)
| |
mutex_lock(_dev->mlock)   i2c_transfer
| |
i2c transaction i2c adapter lock
| |
i2c adapter locki2c_mux_master_xfer
  |
inv_mpu6050_select_bypass
  |
mutex_lock(_dev->mlock)

When we operate on an mpu sensor the order of locking is mpu lock
followed by the i2c adapter lock. However, when we operate the auxiliary
sensor the order of locking is the other way around.

...
--8<--

The reason this patch fixes the deadlock is that T2 does not grab the
i2c adapter lock until the very end (and grabs the newfangled i2c mux
lock where it previously grabbed the i2c adapter lock).

Acked-by: Jonathan Cameron <ji...@kernel.org>
Acked-by: Daniel Baluta <daniel.bal...@intel.com>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/i2c/i2c-topology|  2 +-
 drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 52 ++-
 2 files changed, 11 insertions(+), 43 deletions(-)

diff --git a/Documentation/i2c/i2c-topology b/Documentation/i2c/i2c-topology
index 27bfd682808d..69b008518454 100644
--- a/Documentation/i2c/i2c-topology
+++ b/Documentation/i2c/i2c-topology
@@ -50,7 +50,7 @@ i2c-mux-pinctrl   Normally parent-locked, mux-locked 
iff
 i2c-mux-reg   Parent-locked
 
 In drivers/iio/
-imu/inv_mpu6050/  Parent-locked
+imu/inv_mpu6050/  Mux-locked
 
 In drivers/media/
 dvb-frontends/m88ds3103   Parent-locked
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c 
b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
index 664a45082d39..2c4188db8634 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
@@ -24,45 +24,16 @@ static const struct regmap_config inv_mpu_regmap_config = {
.val_bits = 8,
 };
 
-/*
- * The i2c read/write needs to happen in unlocked mode. As the parent
- * adapter is common. If we use locked versions, it will fail as
- * the mux adapter will lock the parent i2c adapter, while calling
- * select/deselect functions.
- */
-static int inv_mpu6050_write_reg_unlocked(struct i2c_client *client,
- u8 reg, u8 d)
-{
-   int ret;
-   u8 buf[2] = {reg, d};
-   struct i2c_msg msg[1] = {
-   {
-   .addr = client->addr,
-   .flags = 0,
-   .len = sizeof(buf),
-   .buf = buf,
-   }
-   };
-
-   ret = __i2c_transfer(client->adapter, msg, 1);
-   if (ret != 1)
-   return ret;
-
-   return 0;
-}
-
 static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
 {
-   struct i2c_client *client = i2c_mux_priv(muxc);
-   struct iio_dev *indio_dev = dev_get_drvdata(>dev);
+   struct iio_dev *indio_dev = i2c_mux_priv(muxc);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
int ret = 0;
 
/* Use the same mutex which was used everywhere to protect power-op */
mutex_lock(_dev->mlock);
if (!st->powerup_count) {
-   ret = inv_mpu6050_write_reg_unlocked(client,
-st->reg->pwr_mgmt_1, 0);
+   ret = regmap_write(st->map, st->reg->pwr_mgmt_1, 0);
if (ret)
goto write_error;
 
@@ -71,10 +42,9 @@ static int inv_mpu6050_select_bypass(struct i2c_mux_core 
*muxc, u32 chan_id)
}
if (!ret) {
st->powerup_count++;
-   ret = inv_mpu6050_write_reg_unlocked(client,
-st->reg->int_pin_

[PATCH v7 23/24] [media] rtl2832_sdr: get rid of empty regmap wrappers

2016-04-20 Thread Peter Rosin
Reviewed-by: Antti Palosaari <cr...@iki.fi>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/dvb-frontends/rtl2832_sdr.c | 302 +-
 1 file changed, 132 insertions(+), 170 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c 
b/drivers/media/dvb-frontends/rtl2832_sdr.c
index 6a6b1debe277..47a480a7d46c 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -120,6 +120,7 @@ struct rtl2832_sdr_dev {
unsigned long flags;
 
struct platform_device *pdev;
+   struct regmap *regmap;
 
struct video_device vdev;
struct v4l2_device v4l2_dev;
@@ -164,47 +165,6 @@ struct rtl2832_sdr_dev {
unsigned long jiffies_next;
 };
 
-/* write multiple registers */
-static int rtl2832_sdr_wr_regs(struct rtl2832_sdr_dev *dev, u16 reg,
-   const u8 *val, int len)
-{
-   struct platform_device *pdev = dev->pdev;
-   struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
-   struct regmap *regmap = pdata->regmap;
-
-   return regmap_bulk_write(regmap, reg, val, len);
-}
-
-#if 0
-/* read multiple registers */
-static int rtl2832_sdr_rd_regs(struct rtl2832_sdr_dev *dev, u16 reg, u8 *val,
-   int len)
-{
-   struct platform_device *pdev = dev->pdev;
-   struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
-   struct regmap *regmap = pdata->regmap;
-
-   return regmap_bulk_read(regmap, reg, val, len);
-}
-#endif
-
-/* write single register */
-static int rtl2832_sdr_wr_reg(struct rtl2832_sdr_dev *dev, u16 reg, u8 val)
-{
-   return rtl2832_sdr_wr_regs(dev, reg, , 1);
-}
-
-/* write single register with mask */
-static int rtl2832_sdr_wr_reg_mask(struct rtl2832_sdr_dev *dev, u16 reg,
-   u8 val, u8 mask)
-{
-   struct platform_device *pdev = dev->pdev;
-   struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
-   struct regmap *regmap = pdata->regmap;
-
-   return regmap_update_bits(regmap, reg, mask, val);
-}
-
 /* Private functions */
 static struct rtl2832_sdr_frame_buf *rtl2832_sdr_get_next_fill_buf(
struct rtl2832_sdr_dev *dev)
@@ -559,11 +519,11 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev 
*dev)
 
f_sr = dev->f_adc;
 
-   ret = rtl2832_sdr_wr_regs(dev, 0x13e, "\x00\x00", 2);
+   ret = regmap_bulk_write(dev->regmap, 0x13e, "\x00\x00", 2);
if (ret)
goto err;
 
-   ret = rtl2832_sdr_wr_regs(dev, 0x115, "\x00\x00\x00\x00", 4);
+   ret = regmap_bulk_write(dev->regmap, 0x115, "\x00\x00\x00\x00", 4);
if (ret)
goto err;
 
@@ -589,7 +549,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev)
buf[1] = (u32tmp >>  8) & 0xff;
buf[2] = (u32tmp >>  0) & 0xff;
 
-   ret = rtl2832_sdr_wr_regs(dev, 0x119, buf, 3);
+   ret = regmap_bulk_write(dev->regmap, 0x119, buf, 3);
if (ret)
goto err;
 
@@ -603,15 +563,15 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev 
*dev)
u8tmp2 = 0xcd; /* enable ADC I, ADC Q */
}
 
-   ret = rtl2832_sdr_wr_reg(dev, 0x1b1, u8tmp1);
+   ret = regmap_write(dev->regmap, 0x1b1, u8tmp1);
if (ret)
goto err;
 
-   ret = rtl2832_sdr_wr_reg(dev, 0x008, u8tmp2);
+   ret = regmap_write(dev->regmap, 0x008, u8tmp2);
if (ret)
goto err;
 
-   ret = rtl2832_sdr_wr_reg(dev, 0x006, 0x80);
+   ret = regmap_write(dev->regmap, 0x006, 0x80);
if (ret)
goto err;
 
@@ -622,168 +582,169 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev 
*dev)
buf[1] = (u32tmp >> 16) & 0xff;
buf[2] = (u32tmp >>  8) & 0xff;
buf[3] = (u32tmp >>  0) & 0xff;
-   ret = rtl2832_sdr_wr_regs(dev, 0x19f, buf, 4);
+   ret = regmap_bulk_write(dev->regmap, 0x19f, buf, 4);
if (ret)
goto err;
 
/* low-pass filter */
-   ret = rtl2832_sdr_wr_regs(dev, 0x11c,
-   
"\xca\xdc\xd7\xd8\xe0\xf2\x0e\x35\x06\x50\x9c\x0d\x71\x11\x14\x71\x74\x19\x41\xa5",
-   20);
+   ret = regmap_bulk_write(dev->regmap, 0x11c,
+   
"\xca\xdc\xd7\xd8\xe0\xf2\x0e\x35\x06\x50\x9c\x0d\x71\x11\x14\x71\x74\x19\x41\xa5",
+   20);
if (ret)
goto err;
 
-   ret = rtl2832_sdr_wr_regs(dev, 0x017, "\x11\x10", 2);
+   ret = regmap_bulk_write(dev->regmap, 0x017, "\x11\x10", 2);
if (ret)
goto err;
 
/* mode */
-   ret = rtl2832_sdr_wr_regs(dev, 0x019, "\x05", 1);
+   ret = regmap_write(dev->regmap, 0x019, 0x05);

[PATCH v7 24/24] [media] rtl2832: regmap is aware of lockdep, drop local locking hack

2016-04-20 Thread Peter Rosin
Reviewed-by: Antti Palosaari <cr...@iki.fi>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/dvb-frontends/rtl2832.c  | 30 --
 drivers/media/dvb-frontends/rtl2832_priv.h |  1 -
 2 files changed, 31 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832.c 
b/drivers/media/dvb-frontends/rtl2832.c
index 957523f07f61..bfb6beedd40b 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -890,32 +890,6 @@ static bool rtl2832_volatile_reg(struct device *dev, 
unsigned int reg)
return false;
 }
 
-/*
- * FIXME: Hack. Implement own regmap locking in order to silence lockdep
- * recursive lock warning. That happens when regmap I2C client calls I2C mux
- * adapter, which leads demod I2C repeater enable via demod regmap. Operation
- * takes two regmap locks recursively - but those are different regmap 
instances
- * in a two different I2C drivers, so it is not deadlock. Proper fix is to make
- * regmap aware of lockdep.
- */
-static void rtl2832_regmap_lock(void *__dev)
-{
-   struct rtl2832_dev *dev = __dev;
-   struct i2c_client *client = dev->client;
-
-   dev_dbg(>dev, "\n");
-   mutex_lock(>regmap_mutex);
-}
-
-static void rtl2832_regmap_unlock(void *__dev)
-{
-   struct rtl2832_dev *dev = __dev;
-   struct i2c_client *client = dev->client;
-
-   dev_dbg(>dev, "\n");
-   mutex_unlock(>regmap_mutex);
-}
-
 static struct dvb_frontend *rtl2832_get_dvb_frontend(struct i2c_client *client)
 {
struct rtl2832_dev *dev = i2c_get_clientdata(client);
@@ -1082,12 +1056,8 @@ static int rtl2832_probe(struct i2c_client *client,
dev->sleeping = true;
INIT_DELAYED_WORK(>i2c_gate_work, rtl2832_i2c_gate_work);
/* create regmap */
-   mutex_init(>regmap_mutex);
dev->regmap_config.reg_bits =  8,
dev->regmap_config.val_bits =  8,
-   dev->regmap_config.lock = rtl2832_regmap_lock,
-   dev->regmap_config.unlock = rtl2832_regmap_unlock,
-   dev->regmap_config.lock_arg = dev,
dev->regmap_config.volatile_reg = rtl2832_volatile_reg,
dev->regmap_config.max_register = 5 * 0x100,
dev->regmap_config.ranges = regmap_range_cfg,
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h 
b/drivers/media/dvb-frontends/rtl2832_priv.h
index d8f97d14f6fd..c1a8a69e9015 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -33,7 +33,6 @@
 struct rtl2832_dev {
struct rtl2832_platform_data *pdata;
struct i2c_client *client;
-   struct mutex regmap_mutex;
struct regmap_config regmap_config;
struct regmap *regmap;
struct i2c_mux_core *muxc;
-- 
2.1.4

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


[PATCH v7 15/24] i2c-mux: drop old unused i2c-mux api

2016-04-20 Thread Peter Rosin
All i2c mux users are using an explicit i2c mux core, drop support
for implicit i2c mux cores.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/i2c-mux.c   | 63 -
 include/linux/i2c-mux.h | 15 
 2 files changed, 78 deletions(-)

diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index 5ce1b0704cb5..25e9336b0e6e 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -28,12 +28,6 @@
 #include 
 
 /* multiplexer per channel data */
-struct i2c_mux_priv_old {
-   void *mux_priv;
-   int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
-   int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
-};
-
 struct i2c_mux_priv {
struct i2c_adapter adap;
struct i2c_algorithm algo;
@@ -104,53 +98,6 @@ static unsigned int i2c_mux_parent_classes(struct 
i2c_adapter *parent)
return class;
 }
 
-static int i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
-{
-   struct i2c_mux_priv_old *priv = i2c_mux_priv(muxc);
-
-   return priv->select(muxc->parent, priv->mux_priv, chan);
-}
-
-static int i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
-{
-   struct i2c_mux_priv_old *priv = i2c_mux_priv(muxc);
-
-   return priv->deselect(muxc->parent, priv->mux_priv, chan);
-}
-
-struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
-   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 i2c_mux_core *muxc;
-   struct i2c_mux_priv_old *priv;
-   int ret;
-
-   muxc = i2c_mux_alloc(parent, mux_dev, 1, sizeof(*priv), 0,
-i2c_mux_select, i2c_mux_deselect);
-   if (!muxc)
-   return NULL;
-
-   priv = i2c_mux_priv(muxc);
-   priv->select = select;
-   priv->deselect = deselect;
-   priv->mux_priv = mux_priv;
-
-   ret = i2c_mux_add_adapter(muxc, force_nr, chan_id, class);
-   if (ret) {
-   devm_kfree(mux_dev, muxc);
-   return NULL;
-   }
-
-   return muxc->adapter[0];
-}
-EXPORT_SYMBOL_GPL(i2c_add_mux_adapter);
-
 struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
   struct device *dev, int max_adapters,
   int sizeof_priv, u32 flags,
@@ -305,16 +252,6 @@ void i2c_mux_del_adapters(struct i2c_mux_core *muxc)
 }
 EXPORT_SYMBOL_GPL(i2c_mux_del_adapters);
 
-void i2c_del_mux_adapter(struct i2c_adapter *adap)
-{
-   struct i2c_mux_priv *priv = adap->algo_data;
-   struct i2c_mux_core *muxc = priv->muxc;
-
-   i2c_mux_del_adapters(muxc);
-   devm_kfree(muxc->dev, muxc);
-}
-EXPORT_SYMBOL_GPL(i2c_del_mux_adapter);
-
 MODULE_AUTHOR("Rodolfo Giometti <giome...@linux.it>");
 MODULE_DESCRIPTION("I2C driver for multiplexed I2C busses");
 MODULE_LICENSE("GPL v2");
diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h
index 71ac1b3f4f68..2fa93fe1345e 100644
--- a/include/linux/i2c-mux.h
+++ b/include/linux/i2c-mux.h
@@ -53,20 +53,6 @@ static inline void *i2c_mux_priv(struct i2c_mux_core *muxc)
 }
 
 /*
- * 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 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));
-/*
  * Called to create an i2c bus on a multiplexed bus segment.
  * The chan_id parameter is passed to the select and deselect
  * callback functions to perform hardware-specific mux control.
@@ -75,7 +61,6 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
u32 force_nr, u32 chan_id,
unsigned int class);
 
-void i2c_del_mux_adapter(struct i2c_adapter *adap);
 void i2c_mux_del_adapters(struct i2c_mux_core *muxc);
 
 #endif /* __KERNEL__ */
-- 
2.1.4

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


[PATCH v7 13/24] [media] cx231xx: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select op to be in terms of the i2c mux core instead
of the child adapter.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/usb/cx231xx/cx231xx-core.c |  6 ++--
 drivers/media/usb/cx231xx/cx231xx-i2c.c  | 47 
 drivers/media/usb/cx231xx/cx231xx.h  |  4 ++-
 3 files changed, 31 insertions(+), 26 deletions(-)

diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c 
b/drivers/media/usb/cx231xx/cx231xx-core.c
index f497888d94bf..f7aac2abd783 100644
--- a/drivers/media/usb/cx231xx/cx231xx-core.c
+++ b/drivers/media/usb/cx231xx/cx231xx-core.c
@@ -1304,6 +1304,9 @@ int cx231xx_dev_init(struct cx231xx *dev)
cx231xx_i2c_register(>i2c_bus[1]);
cx231xx_i2c_register(>i2c_bus[2]);
 
+   errCode = cx231xx_i2c_mux_create(dev);
+   if (errCode < 0)
+   return errCode;
cx231xx_i2c_mux_register(dev, 0);
cx231xx_i2c_mux_register(dev, 1);
 
@@ -1426,8 +1429,7 @@ EXPORT_SYMBOL_GPL(cx231xx_dev_init);
 void cx231xx_dev_uninit(struct cx231xx *dev)
 {
/* Un Initialize I2C bus */
-   cx231xx_i2c_mux_unregister(dev, 1);
-   cx231xx_i2c_mux_unregister(dev, 0);
+   cx231xx_i2c_mux_unregister(dev);
cx231xx_i2c_unregister(>i2c_bus[2]);
cx231xx_i2c_unregister(>i2c_bus[1]);
cx231xx_i2c_unregister(>i2c_bus[0]);
diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c 
b/drivers/media/usb/cx231xx/cx231xx-i2c.c
index a29c345b027d..473cd3433fe5 100644
--- a/drivers/media/usb/cx231xx/cx231xx-i2c.c
+++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c
@@ -557,40 +557,41 @@ int cx231xx_i2c_unregister(struct cx231xx_i2c *bus)
  * cx231xx_i2c_mux_select()
  * switch i2c master number 1 between port1 and port3
  */
-static int cx231xx_i2c_mux_select(struct i2c_adapter *adap,
-   void *mux_priv, u32 chan_id)
+static int cx231xx_i2c_mux_select(struct i2c_mux_core *muxc, u32 chan_id)
 {
-   struct cx231xx *dev = mux_priv;
+   struct cx231xx *dev = i2c_mux_priv(muxc);
 
return cx231xx_enable_i2c_port_3(dev, chan_id);
 }
 
+int cx231xx_i2c_mux_create(struct cx231xx *dev)
+{
+   dev->muxc = i2c_mux_alloc(>i2c_bus[1].i2c_adap, dev->dev, 2, 0, 0,
+ cx231xx_i2c_mux_select, NULL);
+   if (!dev->muxc)
+   return -ENOMEM;
+   dev->muxc->priv = dev;
+   return 0;
+}
+
 int cx231xx_i2c_mux_register(struct cx231xx *dev, int mux_no)
 {
-   struct i2c_adapter *i2c_parent = >i2c_bus[1].i2c_adap;
-   /* what is the correct mux_dev? */
-   struct device *mux_dev = dev->dev;
-
-   dev->i2c_mux_adap[mux_no] = i2c_add_mux_adapter(i2c_parent,
-   mux_dev,
-   dev /* mux_priv */,
-   0,
-   mux_no /* chan_id */,
-   0 /* class */,
-   _i2c_mux_select,
-   NULL);
-
-   if (!dev->i2c_mux_adap[mux_no])
+   int rc;
+
+   rc = i2c_mux_add_adapter(dev->muxc,
+0,
+mux_no /* chan_id */,
+0 /* class */);
+   if (rc)
dev_warn(dev->dev,
 "i2c mux %d register FAILED\n", mux_no);
 
-   return 0;
+   return rc;
 }
 
-void cx231xx_i2c_mux_unregister(struct cx231xx *dev, int mux_no)
+void cx231xx_i2c_mux_unregister(struct cx231xx *dev)
 {
-   i2c_del_mux_adapter(dev->i2c_mux_adap[mux_no]);
-   dev->i2c_mux_adap[mux_no] = NULL;
+   i2c_mux_del_adapters(dev->muxc);
 }
 
 struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx *dev, int i2c_port)
@@ -603,9 +604,9 @@ struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx 
*dev, int i2c_port)
case I2C_2:
return >i2c_bus[2].i2c_adap;
case I2C_1_MUX_1:
-   return dev->i2c_mux_adap[0];
+   return dev->muxc->adapter[0];
case I2C_1_MUX_3:
-   return dev->i2c_mux_adap[1];
+   return dev->muxc->adapter[1];
default:
return NULL;
}
diff --git a/drivers/media/usb/cx231xx/cx231xx.h 
b/drivers/media/usb/cx231xx/cx231xx.h
index 69f6d20870f5..90c867683076 100644
--- a/drivers/media/usb/cx231xx/cx231xx.h
+++ b/drivers/media/usb/cx231xx/cx231xx.h
@@ -624,6 +624,7 @@ struct cx231xx {
 
/* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
struct cx231xx_i2c i2c_bus[3];
+   struct i2c_mux_core *muxc;
struct i2c_adapter *i2c_mux_adap[2];
 
unsigned int xc_fw_load_done:1;
@@ -760,8 +761,9 @@ int cx231xx_reset_analog_tuner(struct cx231xx *dev);
 void cx231xx_do_i2c_scan(struct cx231xx *dev, int i

[PATCH v7 14/24] of/unittest: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select op to be in terms of the i2c mux core instead
of the child adapter.

Acked-by: Rob Herring <r...@kernel.org>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/of/unittest.c | 37 -
 1 file changed, 12 insertions(+), 25 deletions(-)

diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index e986e6ee52e0..c1ebbfb79453 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -1692,13 +1692,7 @@ static struct i2c_driver unittest_i2c_dev_driver = {
 
 #if IS_BUILTIN(CONFIG_I2C_MUX)
 
-struct unittest_i2c_mux_data {
-   int nchans;
-   struct i2c_adapter *adap[];
-};
-
-static int unittest_i2c_mux_select_chan(struct i2c_adapter *adap,
-  void *client, u32 chan)
+static int unittest_i2c_mux_select_chan(struct i2c_mux_core *muxc, u32 chan)
 {
return 0;
 }
@@ -1706,11 +1700,11 @@ static int unittest_i2c_mux_select_chan(struct 
i2c_adapter *adap,
 static int unittest_i2c_mux_probe(struct i2c_client *client,
const struct i2c_device_id *id)
 {
-   int ret, i, nchans, size;
+   int ret, i, nchans;
struct device *dev = >dev;
struct i2c_adapter *adap = to_i2c_adapter(dev->parent);
struct device_node *np = client->dev.of_node, *child;
-   struct unittest_i2c_mux_data *stm;
+   struct i2c_mux_core *muxc;
u32 reg, max_reg;
 
dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name);
@@ -1734,25 +1728,20 @@ static int unittest_i2c_mux_probe(struct i2c_client 
*client,
return -EINVAL;
}
 
-   size = offsetof(struct unittest_i2c_mux_data, adap[nchans]);
-   stm = devm_kzalloc(dev, size, GFP_KERNEL);
-   if (!stm) {
-   dev_err(dev, "Out of memory\n");
+   muxc = i2c_mux_alloc(adap, dev, nchans, 0, 0,
+unittest_i2c_mux_select_chan, NULL);
+   if (!muxc)
return -ENOMEM;
-   }
-   stm->nchans = nchans;
for (i = 0; i < nchans; i++) {
-   stm->adap[i] = i2c_add_mux_adapter(adap, dev, client,
-   0, i, 0, unittest_i2c_mux_select_chan, NULL);
-   if (!stm->adap[i]) {
+   ret = i2c_mux_add_adapter(muxc, 0, i, 0);
+   if (ret) {
dev_err(dev, "Failed to register mux #%d\n", i);
-   for (i--; i >= 0; i--)
-   i2c_del_mux_adapter(stm->adap[i]);
+   i2c_mux_del_adapters(muxc);
return -ENODEV;
}
}
 
-   i2c_set_clientdata(client, stm);
+   i2c_set_clientdata(client, muxc);
 
return 0;
 };
@@ -1761,12 +1750,10 @@ static int unittest_i2c_mux_remove(struct i2c_client 
*client)
 {
struct device *dev = >dev;
struct device_node *np = client->dev.of_node;
-   struct unittest_i2c_mux_data *stm = i2c_get_clientdata(client);
-   int i;
+   struct i2c_mux_core *muxc = i2c_get_clientdata(client);
 
dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name);
-   for (i = stm->nchans - 1; i >= 0; i--)
-   i2c_del_mux_adapter(stm->adap[i]);
+   i2c_mux_del_adapters(muxc);
return 0;
 }
 
-- 
2.1.4

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


[PATCH v7 12/24] [media] si2168: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
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.

Reviewed-by: Antti Palosaari <cr...@iki.fi>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/dvb-frontends/si2168.c  | 25 +++--
 drivers/media/dvb-frontends/si2168_priv.h |  2 +-
 2 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/media/dvb-frontends/si2168.c 
b/drivers/media/dvb-frontends/si2168.c
index 821a8f481507..5583827c386e 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -615,9 +615,9 @@ static int si2168_get_tune_settings(struct dvb_frontend *fe,
  * We must use unlocked I2C I/O because I2C adapter lock is already taken
  * by the caller (usually tuner driver).
  */
-static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
+static int si2168_select(struct i2c_mux_core *muxc, u32 chan)
 {
-   struct i2c_client *client = mux_priv;
+   struct i2c_client *client = i2c_mux_priv(muxc);
int ret;
struct si2168_cmd cmd;
 
@@ -635,9 +635,9 @@ err:
return ret;
 }
 
-static int si2168_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan)
+static int si2168_deselect(struct i2c_mux_core *muxc, u32 chan)
 {
-   struct i2c_client *client = mux_priv;
+   struct i2c_client *client = i2c_mux_priv(muxc);
int ret;
struct si2168_cmd cmd;
 
@@ -709,17 +709,22 @@ static int si2168_probe(struct i2c_client *client,
}
 
/* create mux i2c adapter for tuner */
-   dev->adapter = i2c_add_mux_adapter(client->adapter, >dev,
-   client, 0, 0, 0, si2168_select, si2168_deselect);
-   if (dev->adapter == NULL) {
-   ret = -ENODEV;
+   dev->muxc = i2c_mux_alloc(client->adapter, >dev,
+ 1, 0, 0,
+ si2168_select, si2168_deselect);
+   if (!dev->muxc) {
+   ret = -ENOMEM;
goto err_kfree;
}
+   dev->muxc->priv = client;
+   ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0);
+   if (ret)
+   goto err_kfree;
 
/* create dvb_frontend */
memcpy(>fe.ops, _ops, sizeof(struct dvb_frontend_ops));
dev->fe.demodulator_priv = client;
-   *config->i2c_adapter = dev->adapter;
+   *config->i2c_adapter = dev->muxc->adapter[0];
*config->fe = >fe;
dev->ts_mode = config->ts_mode;
dev->ts_clock_inv = config->ts_clock_inv;
@@ -743,7 +748,7 @@ static int si2168_remove(struct i2c_client *client)
 
dev_dbg(>dev, "\n");
 
-   i2c_del_mux_adapter(dev->adapter);
+   i2c_mux_del_adapters(dev->muxc);
 
dev->fe.ops.release = NULL;
dev->fe.demodulator_priv = NULL;
diff --git a/drivers/media/dvb-frontends/si2168_priv.h 
b/drivers/media/dvb-frontends/si2168_priv.h
index c07e6fe2cb10..165bf1412063 100644
--- a/drivers/media/dvb-frontends/si2168_priv.h
+++ b/drivers/media/dvb-frontends/si2168_priv.h
@@ -29,7 +29,7 @@
 
 /* state struct */
 struct si2168_dev {
-   struct i2c_adapter *adapter;
+   struct i2c_mux_core *muxc;
struct dvb_frontend fe;
enum fe_delivery_system delivery_system;
enum fe_status fe_status;
-- 
2.1.4

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


[PATCH v7 17/24] i2c: muxes always lock the parent adapter

2016-04-20 Thread Peter Rosin
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 <p...@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 21f46d011c33..5314434c2b5d 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -967,12 +967,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(>bus_lock);
+   rt_mutex_lock(>bus_lock);
 }
 
 /**
@@ -983,12 +978,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(>bus_lock);
+   return rt_mutex_trylock(>bus_lock);
 }
 
 /**
@@ -999,12 +989,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(>bus_lock);
+   rt_mutex_unlock(>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 25e9336b0e6e..dc958eebdbb4 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);
+}
+
 struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
   struct device *dev, int max_adapters,
   int sizeof_priv, u32 flags,
@@ -165,6 +189,9 @@ int i2c_mux_add_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

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


[PATCH v7 18/24] i2c-mux: relax locking of the top i2c adapter during mux-locked muxing

2016-04-20 Thread Peter Rosin
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).

Introduce this new locking concept as "mux-locked" muxes, and call the
pre-existing mux locking scheme "parent-locked".

Modify the i2c mux locking so that muxes that are "mux-locked" locks only
the muxes on the parent adapter 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 muxes on the parent adapter.

Add code to i2c-mux-gpio and i2c-mux-pinctrl that checks if all involved
gpio/pinctrl devices have a parent that is an i2c adapter in the same
adapter tree that is muxed, and request a "mux-locked mux" if that is the
case.

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

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/i2c-core.c  |   1 +
 drivers/i2c/i2c-mux.c   | 152 +---
 drivers/i2c/muxes/i2c-mux-gpio.c|  18 +
 drivers/i2c/muxes/i2c-mux-pinctrl.c |  38 +
 include/linux/i2c-mux.h |   6 ++
 include/linux/i2c.h |   1 +
 6 files changed, 203 insertions(+), 13 deletions(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 5314434c2b5d..53514ea314cd 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1543,6 +1543,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
}
 
rt_mutex_init(>bus_lock);
+   rt_mutex_init(>mux_lock);
mutex_init(>userspace_clients_lock);
INIT_LIST_HEAD(>userspace_clients);
 
diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index dc958eebdbb4..364319c3c95f 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -35,6 +35,25 @@ struct i2c_mux_priv {
u32 chan_id;
 };
 
+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_master_xfer(struct i2c_adapter *adap,
   struct i2c_msg msgs[], int num)
 {
@@ -47,7 +66,29 @@ static int i2c_mux_master_xfer(struct i2c_adapter *adap,
 
ret = muxc->select(muxc, priv->chan_id);
if (ret >= 0)
-   ret = __i2c_transfer(parent, msgs, num);
+   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,
+   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 = parent->algo->smbus_xfer(parent, addr, flags,
+   read_writ

[PATCH v7 03/24] i2c: i2c-mux-pinctrl: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
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 <p...@axentia.se>
---
 drivers/i2c/muxes/i2c-mux-pinctrl.c | 83 ++---
 1 file changed, 30 insertions(+), 53 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c 
b/drivers/i2c/muxes/i2c-mux-pinctrl.c
index b5a982ba8898..1b8dc711815e 100644
--- a/drivers/i2c/muxes/i2c-mux-pinctrl.c
+++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c
@@ -26,34 +26,29 @@
 #include 
 
 struct i2c_mux_pinctrl {
-   struct device *dev;
struct i2c_mux_pinctrl_platform_data *pdata;
struct pinctrl *pinctrl;
struct pinctrl_state **states;
struct pinctrl_state *state_idle;
-   struct i2c_adapter *parent;
-   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);
 }
 
 #ifdef CONFIG_OF
 static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
-   struct platform_device *pdev)
+   struct platform_device *pdev)
 {
struct device_node *np = pdev->dev.of_node;
int num_names, i, ret;
@@ -64,15 +59,12 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl 
*mux,
return 0;
 
mux->pdata = devm_kzalloc(>dev, sizeof(*mux->pdata), GFP_KERNEL);
-   if (!mux->pdata) {
-   dev_err(mux->dev,
-   "Cannot allocate i2c_mux_pinctrl_platform_data\n");
+   if (!mux->pdata)
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(>dev, "Cannot parse pinctrl-names: %d\n",
num_names);
return num_names;
}
@@ -80,23 +72,22 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl 
*mux,
mux->pdata->pinctrl_states = devm_kzalloc(>dev,
sizeof(*mux->pdata->pinctrl_states) * num_names,
GFP_KERNEL);
-   if (!mux->pdata->pinctrl_states) {
-   dev_err(mux->dev, "Cannot allocate pinctrl_states\n");
+   if (!mux->pdata->pinctrl_states)
return -ENOMEM;
-   }
 
for (i = 0; i < num_names; i++) {
ret = of_property_read_string_index(np, "pinctrl-names", i,
>pdata->pinctrl_states[mux->pdata->bus_count]);
if (ret < 0) {
-   dev_err(mux->dev, "Cannot parse pinctrl-names: %d\n",
+   dev_err(>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(>dev,
+   "idle state must be last\n");
return -EINVAL;
}
mux->pdata->pinctrl_state_idle = "idle";
@@ -107,13 +98,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(>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(>dev, "Cannot find parent bus\n");
return -EPROBE_DEFER;
}
 

[PATCH v7 02/24] i2c: i2c-mux-gpio: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
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 <p...@axentia.se>
---
 drivers/i2c/muxes/i2c-mux-gpio.c | 55 
 1 file changed, 22 insertions(+), 33 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index b8e11c16d98c..f6270ee934f9 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -18,8 +18,6 @@
 #include 
 
 struct gpiomux {
-   struct i2c_adapter *parent;
-   struct i2c_adapter **adap; /* child busses */
struct i2c_mux_gpio_platform_data data;
unsigned gpio_base;
 };
@@ -33,18 +31,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);
 
@@ -136,19 +134,15 @@ 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(>dev, sizeof(*mux), GFP_KERNEL);
-   if (!mux) {
-   dev_err(>dev, "Cannot allocate gpiomux structure");
+   if (!mux)
return -ENOMEM;
-   }
-
-   platform_set_drvdata(pdev, mux);
 
if (!dev_get_platdata(>dev)) {
ret = i2c_mux_gpio_probe_dt(mux, pdev);
@@ -180,24 +174,23 @@ static int i2c_mux_gpio_probe(struct platform_device 
*pdev)
if (!parent)
return -EPROBE_DEFER;
 
-   mux->parent = parent;
-   mux->gpio_base = gpio_base;
-
-   mux->adap = devm_kzalloc(>dev,
-sizeof(*mux->adap) * mux->data.n_values,
-GFP_KERNEL);
-   if (!mux->adap) {
-   dev_err(>dev, "Cannot allocate i2c_adapter structure");
+   muxc = i2c_mux_alloc(parent, >dev, mux->data.n_values, 0, 0,
+i2c_mux_gpio_select, NULL);
+   if (!muxc) {
ret = -ENOMEM;
goto alloc_failed;
}
+   muxc->priv = mux;
+
+   platform_set_drvdata(pdev, muxc);
+
+   mux->gpio_base = gpio_base;
 
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;
}
 
for (i = 0; i < mux->data.n_gpios; i++) {
@@ -223,11 +216,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(parent, >dev, mux, nr,
-  mux->data.values[i], class,
-  i2c_mux_gpio_select, 
deselect);
-   if (!mux->adap[i]) {
-   ret = -ENODEV;
+   ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class);
+   if (ret) {
dev_err(>dev, "Failed to add adapter %d\n", i);
goto add_adapter_failed;
}
@@ -239,8 +229,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_mux_del_adapters(muxc);
i = mux->data.n_gpios;
 err_request_gpio:
for (; i > 0; i--)
@@ -253,16 +242,16 @@ 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

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

2016-04-20 Thread Peter Rosin
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.

Acked-by: Jonathan Cameron <ji...@kernel.org>
Signed-off-by: Peter Rosin <p...@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  | 35 +++---
 drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h  |  3 ++-
 4 files changed, 20 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, );
+   st->mux_client = i2c_new_device(st->muxc->adapter[0], );
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 
 #include 
 #include 
-#include 
 #include 
 #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..664a45082d39 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 
 #include 
 #include 
-#include 
 #include 
 #include 
 #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(>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(>dev);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
 
@@ -136,16 +133,18 @@ static int inv_mpu_probe(struct i2c_client *client,
return result;
 
st = iio_priv(dev_get_drvdata(>dev));
-   st->mux_adapter = i2c_add_mux_adapter(client->adapter,
- >dev,
- client,
- 0, 0, 0,
- inv_mpu6050_select_bypass,
- inv_mpu6050_deselect_bypass);
-   if (!st->mux_adapter) {
-   result = -ENODEV;
+   st->muxc = i2c_mux_alloc(client->adapter, >dev,
+1, 0, 0,
+inv_mpu6050_select_bypass,
+inv_mpu6050_deselect_bypass);
+   if (!st->muxc) {
+   result = -ENOMEM;
goto out_unreg_device;
}
+   st->muxc->priv = dev_get_drvdata(>dev);
+   result = i2c_mux_add_adapter(st->muxc, 0, 0, 0);
+   if (result)
+   goto out_unreg_device;
 
result = inv_mpu_acpi_create_mux_client(client);
if (result)
@@ -154,7 +153,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(>dev);
return result;
@@ -162,11 +161,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(>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(&g

[PATCH v7 10/24] [media] rtl2830: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select op to be in terms of the i2c mux core instead
of the child adapter.

Reviewed-by: Antti Palosaari <cr...@iki.fi>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/dvb-frontends/rtl2830.c  | 20 
 drivers/media/dvb-frontends/rtl2830_priv.h |  2 +-
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2830.c 
b/drivers/media/dvb-frontends/rtl2830.c
index 3f96429af0e5..d25d1e0cd4ca 100644
--- a/drivers/media/dvb-frontends/rtl2830.c
+++ b/drivers/media/dvb-frontends/rtl2830.c
@@ -677,9 +677,9 @@ err:
  * adapter lock is already taken by tuner driver.
  * Gate is closed automatically after single I2C transfer.
  */
-static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 
chan_id)
+static int rtl2830_select(struct i2c_mux_core *muxc, u32 chan_id)
 {
-   struct i2c_client *client = mux_priv;
+   struct i2c_client *client = i2c_mux_priv(muxc);
struct rtl2830_dev *dev = i2c_get_clientdata(client);
int ret;
 
@@ -712,7 +712,7 @@ static struct i2c_adapter *rtl2830_get_i2c_adapter(struct 
i2c_client *client)
 
dev_dbg(>dev, "\n");
 
-   return dev->adapter;
+   return dev->muxc->adapter[0];
 }
 
 /*
@@ -865,12 +865,16 @@ static int rtl2830_probe(struct i2c_client *client,
goto err_regmap_exit;
 
/* create muxed i2c adapter for tuner */
-   dev->adapter = i2c_add_mux_adapter(client->adapter, >dev,
-   client, 0, 0, 0, rtl2830_select, NULL);
-   if (dev->adapter == NULL) {
-   ret = -ENODEV;
+   dev->muxc = i2c_mux_alloc(client->adapter, >dev, 1, 0, 0,
+ rtl2830_select, NULL);
+   if (!dev->muxc) {
+   ret = -ENOMEM;
goto err_regmap_exit;
}
+   dev->muxc->priv = client;
+   ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0);
+   if (ret)
+   goto err_regmap_exit;
 
/* create dvb frontend */
memcpy(>fe.ops, _ops, sizeof(dev->fe.ops));
@@ -903,7 +907,7 @@ static int rtl2830_remove(struct i2c_client *client)
/* stop statistics polling */
cancel_delayed_work_sync(>stat_work);
 
-   i2c_del_mux_adapter(dev->adapter);
+   i2c_mux_del_adapters(dev->muxc);
regmap_exit(dev->regmap);
kfree(dev);
 
diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h 
b/drivers/media/dvb-frontends/rtl2830_priv.h
index cf793f39a09b..da4909543da2 100644
--- a/drivers/media/dvb-frontends/rtl2830_priv.h
+++ b/drivers/media/dvb-frontends/rtl2830_priv.h
@@ -29,7 +29,7 @@ struct rtl2830_dev {
struct rtl2830_platform_data *pdata;
struct i2c_client *client;
struct regmap *regmap;
-   struct i2c_adapter *adapter;
+   struct i2c_mux_core *muxc;
struct dvb_frontend fe;
bool sleeping;
unsigned long filters;
-- 
2.1.4

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


[PATCH v7 05/24] i2c: i2c-mux-pca9541: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
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 <p...@axentia.se>
---
 drivers/i2c/muxes/i2c-mux-pca9541.c | 58 +
 1 file changed, 27 insertions(+), 31 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c 
b/drivers/i2c/muxes/i2c-mux-pca9541.c
index d0ba424adebc..3cb8af635db5 100644
--- a/drivers/i2c/muxes/i2c-mux-pca9541.c
+++ b/drivers/i2c/muxes/i2c-mux-pca9541.c
@@ -73,7 +73,7 @@
 #define SELECT_DELAY_LONG  1000
 
 struct pca9541 {
-   struct i2c_adapter *mux_adap;
+   struct i2c_client *client;
unsigned long select_timeout;
unsigned long arb_timeout;
 };
@@ -217,7 +217,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);
@@ -285,9 +286,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 */
@@ -309,9 +311,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;
 }
@@ -324,20 +328,13 @@ static int pca9541_probe(struct i2c_client *client,
 {
struct i2c_adapter *adap = client->adapter;
struct pca954x_platform_data *pdata = dev_get_platdata(>dev);
+   struct i2c_mux_core *muxc;
struct pca9541 *data;
int force;
-   int ret = -ENODEV;
+   int ret;
 
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA))
-   goto err;
-
-   data = kzalloc(sizeof(struct pca9541), GFP_KERNEL);
-   if (!data) {
-   ret = -ENOMEM;
-   goto err;
-   }
-
-   i2c_set_clientdata(client, data);
+   return -ENODEV;
 
/*
 * I2C accesses are unprotected here.
@@ -352,34 +349,33 @@ 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, >dev, client,
-force, 0, 0,
-pca9541_select_chan,
-pca9541_release_chan);
+   muxc = i2c_mux_alloc(adap, >dev, 1, sizeof(*data), 0,
+pca9541_select_chan, pca9541_release_chan);
+   if (!muxc)
+   return -ENOMEM;
 
-   if (data->mux_adap == NULL) {
+   data = i2c_mux_priv(muxc);
+   data->client = client;
+
+   i2c_set_clientdata(client, muxc);
+
+   ret = i2c_mux_add_adapter(muxc, force, 0, 0);
+   if (ret) {
dev_err(>dev, "failed to register master selector\n");
-   goto exit_free;
+   return ret;
}
 
dev_info(>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);
-
-   i2c_del_mux_adapter(data->mux_adap);
+   struct i2c_mux_core *muxc = i2c_get_clientdata(client);
 
-   kfree(data);
+   i2c_mux_del_adapters(muxc);
return 0;
 }
 
-- 
2.1.4

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


[PATCH v7 04/24] i2c: i2c-arb-gpio-challenge: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
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 <p...@axentia.se>
---
 drivers/i2c/muxes/i2c-arb-gpio-challenge.c | 47 +-
 1 file changed, 20 insertions(+), 27 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c 
b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
index 402e3a6c671a..a90bbc4037dd 100644
--- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
+++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
@@ -28,8 +28,6 @@
 /**
  * struct i2c_arbitrator_data - Driver data for I2C arbitrator
  *
- * @parent: Parent adapter
- * @child: Child bus
  * @our_gpio: GPIO we'll use to claim.
  * @our_gpio_release: 0 if active high; 1 if active low; AKA if the GPIO ==
  *   this then consider it released.
@@ -42,8 +40,6 @@
  */
 
 struct i2c_arbitrator_data {
-   struct i2c_adapter *parent;
-   struct i2c_adapter *child;
int our_gpio;
int our_gpio_release;
int their_gpio;
@@ -59,9 +55,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 */
@@ -93,7 +89,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(>dev, "Could not claim bus, timeout\n");
+   dev_err(muxc->dev, "Could not claim bus, timeout\n");
return -EBUSY;
 }
 
@@ -102,10 +98,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);
@@ -119,6 +114,7 @@ static int i2c_arbitrator_probe(struct platform_device 
*pdev)
struct device *dev = >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,12 +130,13 @@ 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(NULL, dev, 1, sizeof(*arb), 0,
+i2c_arbitrator_select, i2c_arbitrator_deselect);
+   if (!muxc)
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, _flags);
@@ -196,21 +193,18 @@ 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_get_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,
-i2c_arbitrator_select,
-i2c_arbitrator_deselect);
-   if (!arb->child) {
+   ret = i2c_mux_add_adapter(muxc, 0, 0, 0);
+   if (ret) {
dev_err(dev, "Failed to add adapter\n");
-   ret = -ENODEV;
-   i2c_put_adapter(arb->parent);
+   i2c_put_adapter(muxc->parent);
}
 
return ret;
@@ -218,11 +212,10 @@ static int i2c_arbitrator_probe(struct platform_device 
*pdev)
 
 static int i2c_arbitrator_remove(struct platfo

[PATCH v7 07/24] i2c: i2c-mux-reg: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
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 <p...@axentia.se>
---
 drivers/i2c/muxes/i2c-mux-reg.c | 69 +++--
 1 file changed, 25 insertions(+), 44 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c
index 5fbd5bd0878f..6773cadf7c9f 100644
--- a/drivers/i2c/muxes/i2c-mux-reg.c
+++ b/drivers/i2c/muxes/i2c-mux-reg.c
@@ -21,8 +21,6 @@
 #include 
 
 struct regmux {
-   struct i2c_adapter *parent;
-   struct i2c_adapter **adap; /* child busses */
struct i2c_mux_reg_platform_data data;
 };
 
@@ -64,18 +62,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);
@@ -85,7 +81,7 @@ static int i2c_mux_reg_deselect(struct i2c_adapter *adap, 
void *data,
 
 #ifdef CONFIG_OF
 static int i2c_mux_reg_probe_dt(struct regmux *mux,
-   struct platform_device *pdev)
+   struct platform_device *pdev)
 {
struct device_node *np = pdev->dev.of_node;
struct device_node *adapter_np, *child;
@@ -107,7 +103,6 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
if (!adapter)
return -EPROBE_DEFER;
 
-   mux->parent = adapter;
mux->data.parent = i2c_adapter_id(adapter);
put_device(>dev);
 
@@ -161,7 +156,7 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
 }
 #else
 static int i2c_mux_reg_probe_dt(struct regmux *mux,
-   struct platform_device *pdev)
+   struct platform_device *pdev)
 {
return 0;
 }
@@ -169,10 +164,10 @@ 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;
-   int (*deselect)(struct i2c_adapter *, void *, u32);
unsigned int class;
int i, ret, nr;
 
@@ -180,17 +175,9 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
if (!mux)
return -ENOMEM;
 
-   platform_set_drvdata(pdev, mux);
-
if (dev_get_platdata(>dev)) {
memcpy(>data, dev_get_platdata(>dev),
sizeof(mux->data));
-
-   parent = i2c_get_adapter(mux->data.parent);
-   if (!parent)
-   return -EPROBE_DEFER;
-
-   mux->parent = parent;
} else {
ret = i2c_mux_reg_probe_dt(mux, pdev);
if (ret < 0) {
@@ -199,6 +186,10 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
}
}
 
+   parent = i2c_get_adapter(mux->data.parent);
+   if (!parent)
+   return -EPROBE_DEFER;
+
if (!mux->data.reg) {
dev_info(>dev,
"Register not set, using platform resource\n");
@@ -215,55 +206,45 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
return -EINVAL;
}
 
-   mux->adap = devm_kzalloc(>dev,
-sizeof(*mux->adap) * mux->data.n_values,
-GFP_KERNEL);
-   if (!mux->adap) {
-   dev_err(>dev, "Cannot allocate i2c_adapter structure");
+   muxc = i2c_mux_alloc(parent, >dev, mux->data.n_values, 0, 0,
+i2c_mux_reg_select, NULL);
+   if (!muxc)
return -ENOMEM;
-   }
+   muxc->priv = mux;
+
+   platform_set_drvdata(pdev, muxc);
 
if (mux->data.idle_in_use)
-   deselect = i2c_mux_reg_deselect;
-   else
-   deselect = NULL;
+   muxc->deselect = i2c_mux_reg_deselect;
 
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->

[PATCH v7 00/24] i2c mux cleanup and locking update

2016-04-20 Thread Peter Rosin
 overhaul.
- Adjust to changes in the inv_mpu6050 driver.
- Adjust to changes in the rtl2832 driver.
- Fix some new trivial checkpatch issues.
- Rename "self-locked" muxes "mux-locked" instead, since the lock has
  been moved to the parent adapter and is common for all muxes with
  the same parent adapter. The advantage is that address collisions
  behind sibling muxes are handled. Parent-locked muxes also grab this
  new mux-lock so that parent-locked and mux-locked siblings interact
  better.
- Firmware mutex added to the si2168 driver.

v5 compared to v4 (only published as a git branch):
- Rebase on top of v4.5-rc7.
- A new patch making me maintainer of i2c muxes (also sent separately).
- A new file Documentation/i2c/i2c-topology that describes various muxing
  issues.
- Rename "i2c-controlled" muxes "self-locked" instead, as it is perfectly
  reasonable to have i2c-controlled muxes that use the pre-existing locking
  scheme. The pre-existing locking scheme for i2c muxes is from here on
  called "parent-locked".
- Rename i2c-mux.c:i2c_mux_master_xfer to __i2c_mux_master_xfer since it
  calls __i2c_transfer, which leaves room for a new i2c_mux_master_xfer
  that calls i2c_transfer. Similar rename shuffle for i2c_mux_smbus_xfer.
- Use sizeof(*priv) instead of sizeof(struct i2c_mux_priv). One instance.
- Some follow-up patches that were posted in response to v2-v4 cleaning up
  and simplifying various i2c muxes outside drivers/i2c/, among those is
  an unrelated cleanup patch to drivers/media/dvb-frontends/rtl2832.c that
  I carry here since it conflicts (trivially) with this series. That
  unrelated patch is (currently) the last patch in the series.

v4 compared to v3:
- Rebase on top of v4.5-rc6.
- Update to add new i2c-mux interfaces in 01/18 including glue to implement
  the old interfaces in terms of the new interfaces, then change the
  mux users over to the new interfaces one by one (in 02/18 through 14/18),
  and finally removing the old interfaces in 15/18. I.e. the first 15
  patches of v4 replaces the first 5 patches of v3, with the following
  points describing changes in the end result. Each patch is now touching
  only one subsystem.
- Rename i2c_add_mux_adapter and i2c_del_mux_adapters to i2c_mux_add_adapter
  and i2c_mux_del_adapters (so that the old functions can live on during the
  transition).
- Make i2c_mux_alloc take a parent and the select/deselect ops as
  arguments. Also add a flags argument to prevent churn later on.
- Add a new interface i2c_mux_one_adapter(). Make use of it in suitable
  mux users with a single child adapter.
- Adjust to a rename in struct gpio_chip.
- Update a couple of comments to match the new code.

v3 compared to v2:
- Fix devm_kfree of a NULL pointer in i2c_mux_reserve_adapters().
- Remove device tree "i2c-controlled" property and determine this by walking
  the dev tree instead.
- Fix compile problems with inv_mpu_acpi.c
- Wait with adding the client pointer to patch 2/8 for pca9541 and pca954x.

v2 compared to v1:
- Allocate mux core and (optional) priv in a combined allocation.
- Kill dev_err messages triggered by memory allocation failure.
- Fix the device specific i2c muxes that I had overlooked.
- Rebase on top of v4.4-rc8 (was based on v4.4-rc6 previously).
- Drop the last two patches in the series.

Cheers,
Peter

Antti Palosaari (1):
  [media] si2168: change the i2c gate to be mux-locked

Peter Rosin (23):
  i2c-mux: add common data for every i2c-mux instance
  i2c: i2c-mux-gpio: convert to use an explicit i2c mux core
  i2c: i2c-mux-pinctrl: convert to use an explicit i2c mux core
  i2c: i2c-arb-gpio-challenge: convert to use an explicit i2c mux core
  i2c: i2c-mux-pca9541: convert to use an explicit i2c mux core
  i2c: i2c-mux-pca954x: convert to use an explicit i2c mux core
  i2c: i2c-mux-reg: convert to use an explicit i2c mux core
  iio: imu: inv_mpu6050: convert to use an explicit i2c mux core
  [media] m88ds3103: convert to use an explicit i2c mux core
  [media] rtl2830: convert to use an explicit i2c mux core
  [media] rtl2832: convert to use an explicit i2c mux core
  [media] si2168: convert to use an explicit i2c mux core
  [media] cx231xx: convert to use an explicit i2c mux core
  of/unittest: convert to use an explicit i2c mux core
  i2c-mux: drop old unused i2c-mux api
  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 mux-locked muxing
  i2c-mux: document i2c muxes and elaborate on parent-/mux-locked muxes
  iio: imu: inv_mpu6050: change the i2c gate to be mux-locked
  [media] rtl2832: change the i2c gate to be mux-locked
  [media] rtl2832_sdr: get rid of empty regmap wrappers
  [media] rtl2832: regmap is aware of lockdep, drop local locking hack

 Documentation/i2c/i2c-topology   | 370 +++
 MAINTAINERS 

[PATCH v7 01/24] i2c-mux: add common data for every i2c-mux instance

2016-04-20 Thread Peter Rosin
All i2c-muxes have a parent adapter and one or many child
adapters. A mux also has some means of selection. Previously,
this was stored per child adapter, but it is only needed
to keep track of this per mux.

Add an i2c mux core, that keeps track of this consistently.

Also add some glue for users of the old interface, which will
create one implicit mux core per child adapter.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/i2c-mux.c   | 175 
 include/linux/i2c-mux.h |  34 ++
 2 files changed, 168 insertions(+), 41 deletions(-)

diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index d4022878b2f0..5ce1b0704cb5 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -28,33 +28,34 @@
 #include 
 
 /* multiplexer per channel data */
+struct i2c_mux_priv_old {
+   void *mux_priv;
+   int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
+   int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
+};
+
 struct i2c_mux_priv {
struct i2c_adapter adap;
struct i2c_algorithm algo;
-
-   struct i2c_adapter *parent;
-   struct device *mux_dev;
-   void *mux_priv;
+   struct i2c_mux_core *muxc;
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,
   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. */
 
-   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;
 }
@@ -65,17 +66,18 @@ 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. */
 
-   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;
 }
@@ -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,6 +104,20 @@ static unsigned int i2c_mux_parent_classes(struct 
i2c_adapter *parent)
return class;
 }
 
+static int i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
+{
+   struct i2c_mux_priv_old *priv = i2c_mux_priv(muxc);
+
+   return priv->select(muxc->parent, priv->mux_priv, chan);
+}
+
+static int i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
+{
+   struct i2c_mux_priv_old *priv = i2c_mux_priv(muxc);
+
+   return priv->deselect(muxc->parent, priv->mux_priv, chan);
+}
+
 struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
struct device *mux_dev,
void *mux_priv, u32 force_nr, u32 chan_id,
@@ -111,21 +127,77 @@ struct i2c_adapter *i2c_add_mux_adapter(struct 
i2c_adapter *parent,
int (*deselect) (struct i2c_adapter *,
 void *, u32))
 {
+   struct i2c_mux_core *muxc;
+   struct i2c_mux_priv_old *priv;
+   int ret;
+
+   muxc = i2c_mux_alloc(parent, mux_dev, 1, sizeof(*priv), 0,
+i2c_mux_select, i2c_mux_deselect);
+   if (!muxc)
+   return NULL;
+
+   priv = i2c_mux_priv(muxc);
+   priv->select = select;
+

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

2016-04-19 Thread Peter Rosin
<hans.verk...@cisco.com>,Arnd Bergmann <a...@arndb.de>,Tommi Rantala 
<tt.rant...@gmail.com>,linux-...@vger.kernel.org,linux-...@vger.kernel.org,linux-...@vger.kernel.org,linux-media@vger.kernel.org,devicet...@vger.kernel.org
Message-ID: <b09cd200-56d1-4be0-b567-90cc23507...@lysator.liu.se>

On April 19, 2016 5:58:11 PM CEST, Crestez Dan Leonard 
<leonard.cres...@intel.com> wrote:
> On 04/03/2016 11:52 AM, Peter Rosin wrote:
> > From: Peter Rosin <p...@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(>dev));
> > -   st->mux_adapter = i2c_add_mux_adapter(client->adapter,
> > - >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, >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:[] []
> mutex_lock+0xd/0x30
> [5.565374] Call Trace:
> [5.565374]  []
> inv_mpu6050_select_bypass+0x1c/0xa0
> ...
> [5.565374]  [] i2c_transfer+0x51/0x90
> ...
> [5.565374]  []
> i2c_smbus_read_i2c_block_data+0x45/0xd0
> [5.565374]  [] ak8975_probe+0x14a/0x5c0
> ...
> [5.565374]  [] i2c_new_device+0x178/0x1e0
> [5.565374]  [] of_i2c_register_device+0xdd/0x1a0
> [5.565374]  [] of_i2c_register_devices+0x3b/0x60
> [5.565374]  [] i2c_register_adapter+0x178/0x410
> [5.565374]  [] i2c_add_adapter+0x73/0x90
> [5.565374]  [] i2c_mux_add_adapter+0x2ed/0x400
> [5.565374]  [] i2c_mux_one_adapter+0x41/0x70
> [5.565374]  [] 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 01/24] i2c-mux: add common data for every i2c-mux instance

2016-04-15 Thread Peter Rosin
Wolfram Sang wrote:
> > > wonder even more if we couldn't supply num_adapters to i2c_mux_alloc()
> > > and reserve the memory statically. i2c busses are not
> > > dynamic/hot-pluggable so that should be good enough?
> > 
> > Yes, that would work, but it would take some restructuring in some of
> > the drivers that currently don't know how many child adapters they
> > are going to need when they call i2c_mux_alloc.
> 
> Which ones?

If you look at i2c-mux-reg.c, it currently allocates its private
struct regmux, then fills it with various platform things and then
when it knows how many children it needs it allocates them. After
v6 it first allocates a mux core and private struct regmux in one go
using i2c_mux_alloc, then continues in much the same way as before.

If the number of children is needed for the i2c_mux_alloc call, then
this is certainly doable, and it would probably not be all that bad,
but the simplest approach would probably be to allocate the private
struct regmux first, then dig through the platform data, then allocate
the mux core when the number of children is known. Which would still
be two allocations separated by the platform data dig.

So, your suggestion would basically move the mux core allocation
from generally being done early together with other private data to
later when the driver has figured out how many children it's going
to create.

The restructuring I thought about is needed if the intention of this
was to reduce number of allocations, but maybe you just wanted
what I described above? Because what I did in v6 and what you are
suggesting is quite similar in complexity, but your version has the
advantage of not having the need for realloc.

So, I have made this change locally (and the adapters->num_adapters
change) and I like it. I haven't even compile-tested it yet though,
but I'll get back when I have done some testing.

> > Because you thought about removing i2c_mux_reserve_adapters completely,
> > and not provide any means of adding more adapters than specified in
> > the i2c_mux_alloc call, right?
> 
> Yes. I assumed I2C to be static enough that such information is known in
> advance.
> 
> > > Ignoring the 80 char limit here makes the code more readable.
> > 
> > That is only true if you actually have more than 80 characters, so I don't
> > agree. Are you adamant about it? (I'm not)
> 
> No. Keep it if you prefer it.
> 
> > >> +EXPORT_SYMBOL_GPL(i2c_mux_one_adapter);
> > > 
> > > Are you sure the above function pays off? Its argument list is very
> > > complex and it doesn't save a lot of code. Having seperate calls is
> > > probably more understandable in drivers? Then again, I assume it makes
> > > the conversion of existing drivers easier.
> > 
> > I added it in v4, you can check earlier versions if you like. Without
> > it most gate-muxes (i.e. typically the muxes in drivers/media) grew
> > since the i2c_add_mux_adapter call got replaced by two calls, i.e.
> > i2c_mux_alloc followed by i2c_max_add_adapter, and coupled with
> > error checks made it look more complex than before. So, this wasn't
> > much of a cleanup from the point of those drivers.
> 
> Hmm, v3 didn't have the driver patches posted with it. Can you push it
> to your branch? I am also not too strong with this one, but having a
> look how it looks without would be nice.

Although I'm not sure what you meant by "driver patches", I have pushed
mux-core-and-locking-2 and mux-core-and-locking-3 to
https://github.com/peda-r/i2c-mux/ (note that these are the branches as
they where when I posted v2 and v3 to the list, i.e. w/o fixups)

Those early versions updated all drivers with each change, making each
patch big, so if that was what you meant by missing "driver patches" then
there simply were no driver patches.

If you meant the follow-up patches to relax locking in the media drivers
etc, I only compile-tested them using throwaway branches back then (if I
even had branches). So, I don't have anything ready to push, sorry.

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


Re: [PATCH v6 01/24] i2c-mux: add common data for every i2c-mux instance

2016-04-13 Thread Peter Rosin
Hi!

On 2016-04-11 22:46, Wolfram Sang wrote:
> Hi Peter,
> 
> first high-level review:
> 
>> +int i2c_mux_reserve_adapters(struct i2c_mux_core *muxc, int adapters)
> 
> I'd suggest to rename 'adapters' into 'num_adapters' throughout this
> patch. I think it makes the code a lot easier to understand.

Hmm, you mean just the variable names, right? And not function names
such as i2c_mux_reserve_(num_)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;
>> +
>> +if (muxc->adapter) {
>> +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);
> 
> Despite that I wonder why not using some of the realloc functions, I

When I wrote it, I found no devm_ version of realloc. I'm not finding
anything now either...

> wonder even more if we couldn't supply num_adapters to i2c_mux_alloc()
> and reserve the memory statically. i2c busses are not
> dynamic/hot-pluggable so that should be good enough?

Yes, that would work, but it would take some restructuring in some of
the drivers that currently don't know how many child adapters they
are going to need when they call i2c_mux_alloc.

Because you thought about removing i2c_mux_reserve_adapters completely,
and not provide any means of adding more adapters than specified in
the i2c_mux_alloc call, right?

>> -WARN(sysfs_create_link(>adap.dev.kobj, _dev->kobj, 
>> "mux_device"),
>> -   "can't create symlink to mux device\n");
>> +WARN(sysfs_create_link(>adap.dev.kobj, >dev->kobj,
>> +   "mux_device"),
> 
> Ignoring the 80 char limit here makes the code more readable.

That is only true if you actually have more than 80 characters, so I don't
agree. Are you adamant about it? (I'm not)

>> + "can't create symlink to mux device\n");
>>  
>>  snprintf(symlink_name, sizeof(symlink_name), "channel-%u", chan_id);
>> -WARN(sysfs_create_link(_dev->kobj, >adap.dev.kobj, 
>> symlink_name),
>> -   "can't create symlink for channel %u\n", 
>> chan_id);
>> +WARN(sysfs_create_link(>dev->kobj, >adap.dev.kobj,
>> +   symlink_name),
> 
> ditto.
> 
>> + "can't create symlink for channel %u\n", chan_id);
>>  dev_info(>dev, "Added multiplexed i2c bus %d\n",
>>   i2c_adapter_id(>adap));
>>  
>> -return >adap;
>> +muxc->adapter[muxc->adapters++] = >adap;
>> +return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(i2c_mux_add_adapter);
>> +
>> +struct i2c_mux_core *i2c_mux_one_adapter(struct i2c_adapter *parent,
>> + struct device *dev, int sizeof_priv,
>> + u32 flags, u32 force_nr,
>> + u32 chan_id, unsigned int class,
>> + int (*select)(struct i2c_mux_core *,
>> +   u32),
> 
> ditto
> 
>> + int (*deselect)(struct i2c_mux_core *,
>> + u32))
> 
> ditto
> 
>> +{
>> +struct i2c_mux_core *muxc;
>> +int ret;
>> +
>> +muxc = i2c_mux_alloc(parent, dev, sizeof_priv, flags, select, deselect);
>> +if (!muxc)
>> +return ERR_PTR(-ENOMEM);
>> +
>> +ret = i2c_mux_add_adapter(muxc, force_nr, chan_id, class);
>> +if (ret) {
>> +devm_kfree(dev, muxc);
>> +return ERR_PTR(ret);
>> +}
>> +
>> +return muxc;
>> +}
>> +EXPORT_SYMBOL_GPL(i2c_mux_one_adapter);
> 
> Are you sure the above function pays off? Its argument list is very
> complex and it doesn't save a lot of code. Having seperate calls is
> probably more understandable in drivers? Then again, I assume it makes
> the conversion of existing drivers easier.

I added it in v4, you can check earlier versions if you like. Without
it most gate-muxes (i.e. typically the muxes in drivers/media) grew
since the i2c_add_mux_adapter call got replaced by two calls, i.e.
i2c_mux_alloc followed by i2c_max_add_adapter, and coupled with
error checks made it look more complex than before. So, this wasn't
much of a cleanup from the point of those drivers.

> So much for now. Thanks!

Yeah, thanks!

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


Re: [PATCH v6 00/24] i2c mux cleanup and locking update

2016-04-11 Thread Peter Rosin

Hi!

On 2016-04-11 14:39, Wolfram Sang wrote:

Hi Peter,


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 16/24 and after with the real meat in 18/24. There
is some documentation added in 19/24 while 20/24 and after are cleanups to
existing drivers utilizing the new stuff.


My idea is to review and pull in the infrastructure work for 4.7 and the
locking changes to 4.8. This gives us one cycle to fix regressions (if
any) in the infrastructure work first. Is that okay with you?


I was just thinking about how it appears impossible to get it all of it
merged in one go and what to do about it...

The untra-defensive approach is only merge stuff that has actually been
tested on real hw, and to hold off the rest until someone has tested. That
can obviously take forever. At the same time, many of the patches are kind
of mechanical, and feels rather safe.

 1 i2c-mux: add common data for every i2c-mux instance
 2 i2c: i2c-mux-gpio: convert to use an explicit i2c mux core
 3 i2c: i2c-mux-pinctrl: convert to use an explicit i2c mux core
 4 i2c: i2c-arb-gpio-challenge: convert to use an explicit i2c mux core
 5 i2c: i2c-mux-pca9541: convert to use an explicit i2c mux core
 6 i2c: i2c-mux-pca954x: convert to use an explicit i2c mux core
 7 i2c: i2c-mux-reg: convert to use an explicit i2c mux core
 8 iio: imu: inv_mpu6050: convert to use an explicit i2c mux core
 9 [media] m88ds3103: convert to use an explicit i2c mux core
10 [media] rtl2830: convert to use an explicit i2c mux core
11 [media] rtl2832: convert to use an explicit i2c mux core
12 [media] si2168: convert to use an explicit i2c mux core
13 [media] cx231xx: convert to use an explicit i2c mux core
14 of/unittest: convert to use an explicit i2c mux core
15 i2c-mux: drop old unused i2c-mux api
16 i2c: allow adapter drivers to override the adapter locking
17 i2c: muxes always lock the parent adapter
18 i2c-mux: relax locking of the top i2c adapter during mux-locked muxing
19 i2c-mux: document i2c muxes and elaborate on parent-/mux-locked muxes
20 iio: imu: inv_mpu6050: change the i2c gate to be mux-locked
21 [media] si2168: change the i2c gate to be mux-locked
22 [media] rtl2832: change the i2c gate to be mux-locked
23 [media] rtl2832_sdr: get rid of empty regmap wrappers
24 [media] rtl2832: regmap is aware of lockdep, drop local locking hack

I have tested 1, 2, 14, 16, 17 and 18 on real hw.
Antti has tested 9, 10, 11, 12, 16, 17, 21, 22, 23 and 24, but they
have been rebased since and 22 in particular is not a pure rebase since
the driver moved underneath me. And the locking was not 100% the same
either, not that I expect things to have gone south, but...
15 is a functional no-op once 2-14 are merged.
19 is docs only.
Jonathan acked 8 and 20, but 20 needs a tested-by from Daniel Baluta
and/or Adriana Reus.

That leaves 3, 4, 5, 6, 7, 13, but all those fall in the mechanical
category, with the possible exception of 13 which is more complex
than the other patches in the 2-14 range. But 13 builds, and besides,
what can possibly go wrong with a patch with that number? :-)

IIUC, your suggestion is to push 1-15 for 4.7, i.e. hope for the best
with 3, 4, 5, 6, 7 and 13. And then hopefully get testing for 20, and
retesting for 21, 22, 23 and 24 and merge 16-24 for 4.8.

That seems like a good plan to me.

Maybe we should give Antti some more time to re-add his tested-by tags
on 9-12 before they are merged into non-rewritable branches?

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


Re: [PATCH] si2168: use i2c controlled mux interface

2016-04-05 Thread Peter Rosin
On 2016-04-05 16:50, Antti Palosaari wrote:
> On 03/23/2016 06:58 PM, Peter Rosin wrote:
>> On 2016-01-06 06:42, Antti Palosaari wrote:
>>> Recent i2c mux locking update offers support for i2c controlled i2c
>>> muxes. Use it and get the rid of homemade hackish i2c adapter
>>> locking code.
>>
>> [actual patch elided]
>>
>> I had a 2nd look and it seems that the saa7164 driver has support for
>> a HVR2055 card with dual si2168 chips. These two chips appear to sit
>> on the same i2c-bus with different i2c-addresses (0x64 and 0x66) and
>> with gates (implemented as muxes) to two identical tuners with the
>> same i2c-address (0x60). Do I read it right?
> 
> saa7164 has 3 different I2C adapters.
> 
> saa7164 I2C bus #0:
> * eeprom
> * Si2157 #1
> 
> saa7164 I2C bus #1:
> * Si2157 #2
> 
> saa7164 I2C bus #2:
> * Si2168 #1
> * Si2168 #2
> 
> So both of the Si2157 tuners could have same addresses.
> 
> (It is Hauppauge WinTV-HVR2205, not HVR-2055).

Ok, so I did read it right.

>> With the current i2c-mux-locking (parent-locked muxes), this works
>> fine as an access to one of the tuners locks the root i2c adapter
>> and thus the other tuner is also locked out. But with the upcoming
>> i2c-mux-locking for i2c-controlled muxes (self-locked muxes), the
>> root i2c adapter would no longer be locked for the full transaction
>> when one of the tuners is accessed. This means that accesses to the
>> two tuners may interleave and cause all kinds of trouble, should
>> both gates be open at the same time. So, is it really correct and
>> safe to change the si2168 driver to use a self-locked mux?
>>
>> Unless there is some other mechanism that prevents the two tuners
>> from being accessed in parallel, I think not. But maybe there is such
>> a mechanism?
> 
> Good point. Actually there is pretty often this kind of configuration used 
> for those dual tuner devices and it will cause problems... Currently all of 
> those implements hackish i2c_gate_ctrl() callback to switch mux.
> 
>        
> |I2C-adapter | |  I2C-mux   | | I2C-client |
> || || ||
> || | addr 0x1c  | | addr 0x60  |
> || || ||
> ||-+-I2C---|-/ -|---I2C---||
> || |   || ||
>|   
>|   |  I2C-mux   | | I2C-client |
>|   || ||
>|   | addr 0x1d  | | addr 0x60  |
>|   || ||
>+-I2C---|-/ -|---I2C---||
>|| ||

Right, so self-locked muxes (as in v5 [1]) can't do the job,
but mux-locked muxes (as in v6 [2]) should be fine. The v6 mux-
locked muxes grab a new mux_lock in the parent adapter where
the v5 self-locked muxes grabbed a lock in the mux itself. Which
means that sibling muxes will lock each other out with v6 when
they go for the same lock, which is what we want.

Cheers,
Peter

(v5 and v6 refer to the mux locking update patch series)

[1] http://marc.info/?l=linux-i2c=145805103325611=2
[2] http://marc.info/?l=linux-i2c=145967417924732=2
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 19/24] i2c-mux: document i2c muxes and elaborate on parent-/mux-locked muxes

2016-04-05 Thread Peter Rosin
On 2016-04-03 13:09, Jonathan Cameron wrote:
> On 03/04/16 09:52, Peter Rosin wrote:
>> From: Peter Rosin <p...@axentia.se>
>>
>> Signed-off-by: Peter Rosin <p...@axentia.se>
> Very nice, one typo that I could see.

Thanks!

*snip*

>> + and the actual transfer (e.g. if the child mux is auto-closing
>> + and the parent mux issus i2c-transfers as part of its select).
>> + This is especailly the case if the parent mux is mux-locked, but
> especially

Fixed now in my local repo.

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


Re: [PATCH v6 14/24] of/unittest: convert to use an explicit i2c mux core

2016-04-05 Thread Peter Rosin
On 2016-04-04 07:16, Rob Herring wrote:
> On Sun, Apr 03, 2016 at 10:52:44AM +0200, Peter Rosin wrote:
>> From: Peter Rosin <p...@axentia.se>
>>
>> Allocate an explicit i2c mux core to handle parent and child adapters
>> etc. Update the select op to be in terms of the i2c mux core instead
>> of the child adapter.
>>
>> Signed-off-by: Peter Rosin <p...@axentia.se>
>> ---
>>  drivers/of/unittest.c | 40 +++-
>>  1 file changed, 15 insertions(+), 25 deletions(-)
> 
> I assume you ran the unittest...

It's one of the few drivers I do have hardware for, so yes, I did
indeed test it!

> Acked-by: Rob Herring <r...@kernel.org>

Thanks!

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


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

2016-04-03 Thread Peter Rosin
On 2016-04-03 12:51, Jonathan Cameron wrote:
> On 03/04/16 09:52, Peter Rosin wrote:
>> From: Peter Rosin <p...@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 <p...@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 <ji...@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, );
>> +st->mux_client = i2c_new_device(st->muxc->adapter[0], );
>>  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 
>>  #include 
>>  #include 
>> -#include 
>>  #include 
>>  #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 
>>  #include 
>>  #include 
>> -#include 
>>  #include 
>>  #include 
>>  #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(>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(>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(>dev));
>> -st->mux_adapter = i2c_add_mux_adapter(client->adapter,
>> -  >dev,
>> -  client,
>> -  0, 0, 0,
>> -  inv_mpu6050_select_bypass,
>> -

[PATCH v6 05/24] i2c: i2c-mux-pca9541: convert to use an explicit i2c mux core

2016-04-03 Thread Peter Rosin
From: Peter Rosin <p...@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 <p...@axentia.se>
---
 drivers/i2c/muxes/i2c-mux-pca9541.c | 55 -
 1 file changed, 23 insertions(+), 32 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c 
b/drivers/i2c/muxes/i2c-mux-pca9541.c
index d0ba424adebc..93bea073ed13 100644
--- a/drivers/i2c/muxes/i2c-mux-pca9541.c
+++ b/drivers/i2c/muxes/i2c-mux-pca9541.c
@@ -73,7 +73,7 @@
 #define SELECT_DELAY_LONG  1000
 
 struct pca9541 {
-   struct i2c_adapter *mux_adap;
+   struct i2c_client *client;
unsigned long select_timeout;
unsigned long arb_timeout;
 };
@@ -217,7 +217,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);
@@ -285,9 +286,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 */
@@ -309,9 +311,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;
 }
@@ -324,20 +328,12 @@ static int pca9541_probe(struct i2c_client *client,
 {
struct i2c_adapter *adap = client->adapter;
struct pca954x_platform_data *pdata = dev_get_platdata(>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;
-
-   data = kzalloc(sizeof(struct pca9541), GFP_KERNEL);
-   if (!data) {
-   ret = -ENOMEM;
-   goto err;
-   }
-
-   i2c_set_clientdata(client, data);
+   return -ENODEV;
 
/*
 * I2C accesses are unprotected here.
@@ -352,34 +348,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, >dev, client,
-force, 0, 0,
-pca9541_select_chan,
-pca9541_release_chan);
-
-   if (data->mux_adap == NULL) {
+   muxc = i2c_mux_one_adapter(adap, >dev, sizeof(*data), 0,
+  force, 0, 0,
+  pca9541_select_chan, pca9541_release_chan);
+   if (IS_ERR(muxc)) {
dev_err(>dev, "failed to register master selector\n");
-   goto exit_free;
+   return PTR_ERR(muxc);
}
+   data = i2c_mux_priv(muxc);
+   data->client = client;
+
+   i2c_set_clientdata(client, muxc);
 
dev_info(>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);
-
-   i2c_del_mux_adapter(data->mux_adap);
+   struct i2c_mux_core *muxc = i2c_get_clientdata(client);
 
-   kfree(data);
+   i2c_mux_del_adapters(muxc);
return 0;
 }
 
-- 
2.1.4

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


[PATCH v6 01/24] i2c-mux: add common data for every i2c-mux instance

2016-04-03 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

All i2c-muxes have a parent adapter and one or many child
adapters. A mux also has some means of selection. Previously,
this was stored per child adapter, but it is only needed
to keep track of this per mux.

Add an i2c mux core, that keeps track of this consistently.

Also add some glue for users of the old interface, which will
create one implicit mux core per child adapter.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/i2c-mux.c   | 238 ++--
 include/linux/i2c-mux.h |  47 ++
 2 files changed, 237 insertions(+), 48 deletions(-)

diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index d4022878b2f0..d95eb66e11bf 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -28,33 +28,34 @@
 #include 
 
 /* multiplexer per channel data */
+struct i2c_mux_priv_old {
+   void *mux_priv;
+   int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
+   int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
+};
+
 struct i2c_mux_priv {
struct i2c_adapter adap;
struct i2c_algorithm algo;
-
-   struct i2c_adapter *parent;
-   struct device *mux_dev;
-   void *mux_priv;
+   struct i2c_mux_core *muxc;
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,
   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. */
 
-   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;
 }
@@ -65,17 +66,18 @@ 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. */
 
-   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;
 }
@@ -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,30 +104,80 @@ 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 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))
+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;
+
+   if (muxc->adapter) {
+   memcpy(adapter, muxc->adapter,
+  muxc->max_adapters * sizeof(*adapter));
+   devm_kfree(muxc->dev, muxc->adapter);
+   }
+
+   muxc->adap

[PATCH v6 11/24] [media] rtl2832: convert to use an explicit i2c mux core

2016-04-03 Thread Peter Rosin
From: Peter Rosin <p...@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.

Reviewed-by: Antti Palosaari <cr...@iki.fi>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/dvb-frontends/rtl2832.c  | 22 +++---
 drivers/media/dvb-frontends/rtl2832_priv.h |  2 +-
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832.c 
b/drivers/media/dvb-frontends/rtl2832.c
index 7c96f7679669..545c3bbbc668 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -847,9 +847,9 @@ err:
dev_dbg(>dev, "failed=%d\n", ret);
 }
 
-static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 
chan_id)
+static int rtl2832_select(struct i2c_mux_core *muxc, u32 chan_id)
 {
-   struct rtl2832_dev *dev = mux_priv;
+   struct rtl2832_dev *dev = i2c_mux_priv(muxc);
struct i2c_client *client = dev->client;
int ret;
 
@@ -870,10 +870,9 @@ err:
return ret;
 }
 
-static int rtl2832_deselect(struct i2c_adapter *adap, void *mux_priv,
-   u32 chan_id)
+static int rtl2832_deselect(struct i2c_mux_core *muxc, u32 chan_id)
 {
-   struct rtl2832_dev *dev = mux_priv;
+   struct rtl2832_dev *dev = i2c_mux_priv(muxc);
 
schedule_delayed_work(>i2c_gate_work, usecs_to_jiffies(100));
return 0;
@@ -1059,7 +1058,7 @@ static struct i2c_adapter *rtl2832_get_i2c_adapter(struct 
i2c_client *client)
struct rtl2832_dev *dev = i2c_get_clientdata(client);
 
dev_dbg(>dev, "\n");
-   return dev->i2c_adapter_tuner;
+   return dev->muxc->adapter[0];
 }
 
 static int rtl2832_slave_ts_ctrl(struct i2c_client *client, bool enable)
@@ -1242,12 +1241,13 @@ static int rtl2832_probe(struct i2c_client *client,
goto err_regmap_exit;
 
/* create muxed i2c adapter for demod tuner bus */
-   dev->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, >dev, dev,
-   0, 0, 0, rtl2832_select, rtl2832_deselect);
-   if (dev->i2c_adapter_tuner == NULL) {
-   ret = -ENODEV;
+   dev->muxc = i2c_mux_one_adapter(i2c, >dev, 0, 0, 0, 0, 0,
+   rtl2832_select, rtl2832_deselect);
+   if (IS_ERR(dev->muxc)) {
+   ret = PTR_ERR(dev->muxc);
goto err_regmap_exit;
}
+   dev->muxc->priv = dev;
 
/* create dvb_frontend */
memcpy(>fe.ops, _ops, sizeof(struct dvb_frontend_ops));
@@ -1282,7 +1282,7 @@ static int rtl2832_remove(struct i2c_client *client)
 
cancel_delayed_work_sync(>i2c_gate_work);
 
-   i2c_del_mux_adapter(dev->i2c_adapter_tuner);
+   i2c_mux_del_adapters(dev->muxc);
 
regmap_exit(dev->regmap);
 
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h 
b/drivers/media/dvb-frontends/rtl2832_priv.h
index 6b875f462f8b..d8f97d14f6fd 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -36,7 +36,7 @@ struct rtl2832_dev {
struct mutex regmap_mutex;
struct regmap_config regmap_config;
struct regmap *regmap;
-   struct i2c_adapter *i2c_adapter_tuner;
+   struct i2c_mux_core *muxc;
struct dvb_frontend fe;
enum fe_status fe_status;
u64 post_bit_error_prev; /* for old DVBv3 read_ber() calculation */
-- 
2.1.4

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


[PATCH v6 09/24] [media] m88ds3103: convert to use an explicit i2c mux core

2016-04-03 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

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

Reviewed-by: Antti Palosaari <cr...@iki.fi>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/dvb-frontends/m88ds3103.c  | 18 +-
 drivers/media/dvb-frontends/m88ds3103_priv.h |  2 +-
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/media/dvb-frontends/m88ds3103.c 
b/drivers/media/dvb-frontends/m88ds3103.c
index 76883600ec6f..bf5ffcda7797 100644
--- a/drivers/media/dvb-frontends/m88ds3103.c
+++ b/drivers/media/dvb-frontends/m88ds3103.c
@@ -1251,9 +1251,9 @@ static void m88ds3103_release(struct dvb_frontend *fe)
i2c_unregister_device(client);
 }
 
-static int m88ds3103_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
+static int m88ds3103_select(struct i2c_mux_core *muxc, u32 chan)
 {
-   struct m88ds3103_dev *dev = mux_priv;
+   struct m88ds3103_dev *dev = i2c_mux_priv(muxc);
struct i2c_client *client = dev->client;
int ret;
struct i2c_msg msg = {
@@ -1374,7 +1374,7 @@ static struct i2c_adapter 
*m88ds3103_get_i2c_adapter(struct i2c_client *client)
 
dev_dbg(>dev, "\n");
 
-   return dev->i2c_adapter;
+   return dev->muxc->adapter[0];
 }
 
 static int m88ds3103_probe(struct i2c_client *client,
@@ -1467,13 +1467,13 @@ static int m88ds3103_probe(struct i2c_client *client,
goto err_kfree;
 
/* create mux i2c adapter for tuner */
-   dev->i2c_adapter = i2c_add_mux_adapter(client->adapter, >dev,
-  dev, 0, 0, 0, m88ds3103_select,
-  NULL);
-   if (dev->i2c_adapter == NULL) {
-   ret = -ENOMEM;
+   dev->muxc = i2c_mux_one_adapter(client->adapter, >dev, 0, 0,
+   0, 0, 0, m88ds3103_select, NULL);
+   if (IS_ERR(dev->muxc)) {
+   ret = PTR_ERR(dev->muxc);
goto err_kfree;
}
+   dev->muxc->priv = dev;
 
/* create dvb_frontend */
memcpy(>fe.ops, _ops, sizeof(struct dvb_frontend_ops));
@@ -1502,7 +1502,7 @@ static int m88ds3103_remove(struct i2c_client *client)
 
dev_dbg(>dev, "\n");
 
-   i2c_del_mux_adapter(dev->i2c_adapter);
+   i2c_mux_del_adapters(dev->muxc);
 
kfree(dev);
return 0;
diff --git a/drivers/media/dvb-frontends/m88ds3103_priv.h 
b/drivers/media/dvb-frontends/m88ds3103_priv.h
index eee8c22c51ec..c5b4e177c6ea 100644
--- a/drivers/media/dvb-frontends/m88ds3103_priv.h
+++ b/drivers/media/dvb-frontends/m88ds3103_priv.h
@@ -42,7 +42,7 @@ struct m88ds3103_dev {
enum fe_status fe_status;
u32 dvbv3_ber; /* for old DVBv3 API read_ber */
bool warm; /* FW running */
-   struct i2c_adapter *i2c_adapter;
+   struct i2c_mux_core *muxc;
/* auto detect chip id to do different config */
u8 chip_id;
/* main mclk is calculated for M88RS6000 dynamically */
-- 
2.1.4

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


[PATCH v6 10/24] [media] rtl2830: convert to use an explicit i2c mux core

2016-04-03 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

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

Reviewed-by: Antti Palosaari <cr...@iki.fi>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/dvb-frontends/rtl2830.c  | 17 +
 drivers/media/dvb-frontends/rtl2830_priv.h |  2 +-
 2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2830.c 
b/drivers/media/dvb-frontends/rtl2830.c
index 3f96429af0e5..ab02c3a07194 100644
--- a/drivers/media/dvb-frontends/rtl2830.c
+++ b/drivers/media/dvb-frontends/rtl2830.c
@@ -677,9 +677,9 @@ err:
  * adapter lock is already taken by tuner driver.
  * Gate is closed automatically after single I2C transfer.
  */
-static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 
chan_id)
+static int rtl2830_select(struct i2c_mux_core *muxc, u32 chan_id)
 {
-   struct i2c_client *client = mux_priv;
+   struct i2c_client *client = i2c_mux_priv(muxc);
struct rtl2830_dev *dev = i2c_get_clientdata(client);
int ret;
 
@@ -712,7 +712,7 @@ static struct i2c_adapter *rtl2830_get_i2c_adapter(struct 
i2c_client *client)
 
dev_dbg(>dev, "\n");
 
-   return dev->adapter;
+   return dev->muxc->adapter[0];
 }
 
 /*
@@ -865,12 +865,13 @@ static int rtl2830_probe(struct i2c_client *client,
goto err_regmap_exit;
 
/* create muxed i2c adapter for tuner */
-   dev->adapter = i2c_add_mux_adapter(client->adapter, >dev,
-   client, 0, 0, 0, rtl2830_select, NULL);
-   if (dev->adapter == NULL) {
-   ret = -ENODEV;
+   dev->muxc = i2c_mux_one_adapter(client->adapter, >dev, 0, 0,
+   0, 0, 0, rtl2830_select, NULL);
+   if (IS_ERR(dev->muxc)) {
+   ret = PTR_ERR(dev->muxc);
goto err_regmap_exit;
}
+   dev->muxc->priv = client;
 
/* create dvb frontend */
memcpy(>fe.ops, _ops, sizeof(dev->fe.ops));
@@ -903,7 +904,7 @@ static int rtl2830_remove(struct i2c_client *client)
/* stop statistics polling */
cancel_delayed_work_sync(>stat_work);
 
-   i2c_del_mux_adapter(dev->adapter);
+   i2c_mux_del_adapters(dev->muxc);
regmap_exit(dev->regmap);
kfree(dev);
 
diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h 
b/drivers/media/dvb-frontends/rtl2830_priv.h
index cf793f39a09b..da4909543da2 100644
--- a/drivers/media/dvb-frontends/rtl2830_priv.h
+++ b/drivers/media/dvb-frontends/rtl2830_priv.h
@@ -29,7 +29,7 @@ struct rtl2830_dev {
struct rtl2830_platform_data *pdata;
struct i2c_client *client;
struct regmap *regmap;
-   struct i2c_adapter *adapter;
+   struct i2c_mux_core *muxc;
struct dvb_frontend fe;
bool sleeping;
unsigned long filters;
-- 
2.1.4

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


[PATCH v6 04/24] i2c: i2c-arb-gpio-challenge: convert to use an explicit i2c mux core

2016-04-03 Thread Peter Rosin
From: Peter Rosin <p...@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 <p...@axentia.se>
---
 drivers/i2c/muxes/i2c-arb-gpio-challenge.c | 47 +-
 1 file changed, 20 insertions(+), 27 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c 
b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
index 402e3a6c671a..a42827b3c672 100644
--- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
+++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
@@ -28,8 +28,6 @@
 /**
  * struct i2c_arbitrator_data - Driver data for I2C arbitrator
  *
- * @parent: Parent adapter
- * @child: Child bus
  * @our_gpio: GPIO we'll use to claim.
  * @our_gpio_release: 0 if active high; 1 if active low; AKA if the GPIO ==
  *   this then consider it released.
@@ -42,8 +40,6 @@
  */
 
 struct i2c_arbitrator_data {
-   struct i2c_adapter *parent;
-   struct i2c_adapter *child;
int our_gpio;
int our_gpio_release;
int their_gpio;
@@ -59,9 +55,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 */
@@ -93,7 +89,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(>dev, "Could not claim bus, timeout\n");
+   dev_err(muxc->dev, "Could not claim bus, timeout\n");
return -EBUSY;
 }
 
@@ -102,10 +98,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);
@@ -119,6 +114,7 @@ static int i2c_arbitrator_probe(struct platform_device 
*pdev)
struct device *dev = >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,12 +130,13 @@ 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(NULL, dev, sizeof(*arb), 0,
+i2c_arbitrator_select, i2c_arbitrator_deselect);
+   if (!muxc)
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, _flags);
@@ -196,21 +193,18 @@ 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_get_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,
-i2c_arbitrator_select,
-i2c_arbitrator_deselect);
-   if (!arb->child) {
+   ret = i2c_mux_add_adapter(muxc, 0, 0, 0);
+   if (ret) {
dev_err(dev, "Failed to add adapter\n");
-   ret = -ENODEV;
-   i2c_put_adapter(arb->parent);
+   i2c_put_adapter(muxc->parent);
}
 
return ret;
@@ -218,11 +212,10 @@ static int i2c_arbitrator_probe(struct platform_device 
*pdev)

[PATCH v6 00/24] i2c mux cleanup and locking update

2016-04-03 Thread Peter Rosin
From: Peter Rosin <p...@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. 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 it 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 code to i2c-mux-gpio and
i2c-mux-pinctrl that determines if all involved devices used to update the
mux are controlled by the same root i2c adapter that is muxed. When this
is the case, the select-transfer-deselect operations should be locked
individually to avoid the deadlock. The i2c bus *is* still 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 i2c master bus). A lock
is added to i2c adapters that muxes on that adapter grab, so that transfers
through the muxes 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 or 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.
- Is the detection of i2c-controlled gpios and pinctrls sane (i.e. the
  usage of the new i2c_root_adapter() function in 18/24)?

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 16/24 and after with the real meat in 18/24. There
is some documentation added in 19/24 while 20/24 and after are cleanups to
existing drivers utilizing the new stuff.

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

Specifically, thank you Antti for testing v5, but I did not add any
Tested-by for v6 since I moved the lock from the mux itself to the mux
parent adapter. I did this to cope with the situation I described in
http://marc.info/?l=linux-i2c=145875234525803=2
thus making it possible to get rid of the unlocked accesses in the
si2168 driver (patch 21/24). I also didn't add any Reviewed-by for
the parts of the rtl2832 driver changes that suffered the most from
driver updates since v4.5-rc7, so please review that again as well.

This series can also be pulled from github, if that is preferred:

-
The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:

  Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)

are available in the git repository at:

  https://github.com/peda-r/i2c-mux.git mux-core-and-locking-6

for you to fetch changes up to 81830e43de2bc849848b939166103217ac444df5:

  [media] rtl2832: regmap is aware of lockdep, drop local locking hack 
(2016-04-03 09:35:52 +0200)
-

v6 compared to v5:
- Rebase on top of v4.6-rc1
- Adjust to gpio subsystem overhaul.
- Adjust to changes in the inv_mpu6050 driver.
- Adjust to changes in the rtl2832 driver.
- Fix some new trivial checkpatch issues.
- Rename "self-locked" muxes "mux-locked" instead, since the lock has
  been moved to the parent adapter and is common for all muxes with
  the same parent adapter. The advantage is that address collisions
  behind sibling muxes are handled. Parent-locked muxes also grab this
  new mux-lock so that parent-locked and mux-locked siblings interact
  better.
- Firmware mutex added to the si2168 driver.

v5 compared to v4 (only published as a git branch):
- Rebase on top of v4.5-rc7.
- A new patch making me maintainer of i2c muxes (also sent separately).
- A new file Docu

[PATCH v6 20/24] iio: imu: inv_mpu6050: change the i2c gate to be mux-locked

2016-04-03 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

The root i2c adapter lock is then no longer held by the i2c mux during
accesses behind the i2c gate, and such accesses need to take that lock
just like any other ordinary i2c accesses do.

So, declare the i2c gate mux-locked, and zap the code that makes the
unlocked i2c accesses and just use ordinary regmap_write accesses.

This also happens to fix the deadlock described in
http://patchwork.ozlabs.org/patch/584776/ authored by
Adriana Reus <adriana.r...@intel.com> and submitted by
Daniel Baluta <daniel.bal...@intel.com>

--8<--
iio: imu: inv_mpu6050: Fix deadlock between i2c adapter lock and mpu lock

This deadlock occurs if the accel/gyro and the sensor on the auxiliary
I2C (in my setup it's an ak8975) are working at the same time.

Scenario:

  T1T2
   
inv_mpu6050_read_fifo  aux sensor op (eg. ak8975_read_raw)
| |
mutex_lock(_dev->mlock)   i2c_transfer
| |
i2c transaction i2c adapter lock
| |
i2c adapter locki2c_mux_master_xfer
  |
inv_mpu6050_select_bypass
  |
mutex_lock(_dev->mlock)

When we operate on an mpu sensor the order of locking is mpu lock
followed by the i2c adapter lock. However, when we operate the auxiliary
sensor the order of locking is the other way around.

...
--8<--

The reason this patch fixes the deadlock is that T2 does not grab the
i2c adapter lock until the very end (and grabs the newfangled i2c mux
lock where it previously grabbed the i2c adapter lock).

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/i2c/i2c-topology|  2 +-
 drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 56 +++
 2 files changed, 13 insertions(+), 45 deletions(-)

diff --git a/Documentation/i2c/i2c-topology b/Documentation/i2c/i2c-topology
index 7a10edd0874f..346623a80bd1 100644
--- a/Documentation/i2c/i2c-topology
+++ b/Documentation/i2c/i2c-topology
@@ -50,7 +50,7 @@ i2c-mux-pinctrl   Normally parent-locked, mux-locked 
iff
 i2c-mux-reg   Parent-locked
 
 In drivers/iio/
-imu/inv_mpu6050/  Parent-locked
+imu/inv_mpu6050/  Mux-locked
 
 In drivers/media/
 dvb-frontends/m88ds3103   Parent-locked
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c 
b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
index 0d429d788106..71ad31a275c9 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
@@ -24,45 +24,16 @@ static const struct regmap_config inv_mpu_regmap_config = {
.val_bits = 8,
 };
 
-/*
- * The i2c read/write needs to happen in unlocked mode. As the parent
- * adapter is common. If we use locked versions, it will fail as
- * the mux adapter will lock the parent i2c adapter, while calling
- * select/deselect functions.
- */
-static int inv_mpu6050_write_reg_unlocked(struct i2c_client *client,
- u8 reg, u8 d)
-{
-   int ret;
-   u8 buf[2] = {reg, d};
-   struct i2c_msg msg[1] = {
-   {
-   .addr = client->addr,
-   .flags = 0,
-   .len = sizeof(buf),
-   .buf = buf,
-   }
-   };
-
-   ret = __i2c_transfer(client->adapter, msg, 1);
-   if (ret != 1)
-   return ret;
-
-   return 0;
-}
-
 static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
 {
-   struct i2c_client *client = i2c_mux_priv(muxc);
-   struct iio_dev *indio_dev = dev_get_drvdata(>dev);
+   struct iio_dev *indio_dev = i2c_mux_priv(muxc);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
int ret = 0;
 
/* Use the same mutex which was used everywhere to protect power-op */
mutex_lock(_dev->mlock);
if (!st->powerup_count) {
-   ret = inv_mpu6050_write_reg_unlocked(client,
-st->reg->pwr_mgmt_1, 0);
+   ret = regmap_write(st->map, st->reg->pwr_mgmt_1, 0);
if (ret)
goto write_error;
 
@@ -71,10 +42,9 @@ static int inv_mpu6050_select_bypass(struct i2c_mux_core 
*muxc, u32 chan_id)
}
if (!ret) {
st->powerup_count++;
-   ret = inv_mpu6050_write_reg_unlocked(client,
-st->reg->int_pin_cfg,
-

[PATCH v6 23/24] [media] rtl2832_sdr: get rid of empty regmap wrappers

2016-04-03 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

Reviewed-by: Antti Palosaari <cr...@iki.fi>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/dvb-frontends/rtl2832_sdr.c | 302 +-
 1 file changed, 132 insertions(+), 170 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c 
b/drivers/media/dvb-frontends/rtl2832_sdr.c
index 6a6b1debe277..47a480a7d46c 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -120,6 +120,7 @@ struct rtl2832_sdr_dev {
unsigned long flags;
 
struct platform_device *pdev;
+   struct regmap *regmap;
 
struct video_device vdev;
struct v4l2_device v4l2_dev;
@@ -164,47 +165,6 @@ struct rtl2832_sdr_dev {
unsigned long jiffies_next;
 };
 
-/* write multiple registers */
-static int rtl2832_sdr_wr_regs(struct rtl2832_sdr_dev *dev, u16 reg,
-   const u8 *val, int len)
-{
-   struct platform_device *pdev = dev->pdev;
-   struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
-   struct regmap *regmap = pdata->regmap;
-
-   return regmap_bulk_write(regmap, reg, val, len);
-}
-
-#if 0
-/* read multiple registers */
-static int rtl2832_sdr_rd_regs(struct rtl2832_sdr_dev *dev, u16 reg, u8 *val,
-   int len)
-{
-   struct platform_device *pdev = dev->pdev;
-   struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
-   struct regmap *regmap = pdata->regmap;
-
-   return regmap_bulk_read(regmap, reg, val, len);
-}
-#endif
-
-/* write single register */
-static int rtl2832_sdr_wr_reg(struct rtl2832_sdr_dev *dev, u16 reg, u8 val)
-{
-   return rtl2832_sdr_wr_regs(dev, reg, , 1);
-}
-
-/* write single register with mask */
-static int rtl2832_sdr_wr_reg_mask(struct rtl2832_sdr_dev *dev, u16 reg,
-   u8 val, u8 mask)
-{
-   struct platform_device *pdev = dev->pdev;
-   struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
-   struct regmap *regmap = pdata->regmap;
-
-   return regmap_update_bits(regmap, reg, mask, val);
-}
-
 /* Private functions */
 static struct rtl2832_sdr_frame_buf *rtl2832_sdr_get_next_fill_buf(
struct rtl2832_sdr_dev *dev)
@@ -559,11 +519,11 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev 
*dev)
 
f_sr = dev->f_adc;
 
-   ret = rtl2832_sdr_wr_regs(dev, 0x13e, "\x00\x00", 2);
+   ret = regmap_bulk_write(dev->regmap, 0x13e, "\x00\x00", 2);
if (ret)
goto err;
 
-   ret = rtl2832_sdr_wr_regs(dev, 0x115, "\x00\x00\x00\x00", 4);
+   ret = regmap_bulk_write(dev->regmap, 0x115, "\x00\x00\x00\x00", 4);
if (ret)
goto err;
 
@@ -589,7 +549,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev)
buf[1] = (u32tmp >>  8) & 0xff;
buf[2] = (u32tmp >>  0) & 0xff;
 
-   ret = rtl2832_sdr_wr_regs(dev, 0x119, buf, 3);
+   ret = regmap_bulk_write(dev->regmap, 0x119, buf, 3);
if (ret)
goto err;
 
@@ -603,15 +563,15 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev 
*dev)
u8tmp2 = 0xcd; /* enable ADC I, ADC Q */
}
 
-   ret = rtl2832_sdr_wr_reg(dev, 0x1b1, u8tmp1);
+   ret = regmap_write(dev->regmap, 0x1b1, u8tmp1);
if (ret)
goto err;
 
-   ret = rtl2832_sdr_wr_reg(dev, 0x008, u8tmp2);
+   ret = regmap_write(dev->regmap, 0x008, u8tmp2);
if (ret)
goto err;
 
-   ret = rtl2832_sdr_wr_reg(dev, 0x006, 0x80);
+   ret = regmap_write(dev->regmap, 0x006, 0x80);
if (ret)
goto err;
 
@@ -622,168 +582,169 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev 
*dev)
buf[1] = (u32tmp >> 16) & 0xff;
buf[2] = (u32tmp >>  8) & 0xff;
buf[3] = (u32tmp >>  0) & 0xff;
-   ret = rtl2832_sdr_wr_regs(dev, 0x19f, buf, 4);
+   ret = regmap_bulk_write(dev->regmap, 0x19f, buf, 4);
if (ret)
goto err;
 
/* low-pass filter */
-   ret = rtl2832_sdr_wr_regs(dev, 0x11c,
-   
"\xca\xdc\xd7\xd8\xe0\xf2\x0e\x35\x06\x50\x9c\x0d\x71\x11\x14\x71\x74\x19\x41\xa5",
-   20);
+   ret = regmap_bulk_write(dev->regmap, 0x11c,
+   
"\xca\xdc\xd7\xd8\xe0\xf2\x0e\x35\x06\x50\x9c\x0d\x71\x11\x14\x71\x74\x19\x41\xa5",
+   20);
if (ret)
goto err;
 
-   ret = rtl2832_sdr_wr_regs(dev, 0x017, "\x11\x10", 2);
+   ret = regmap_bulk_write(dev->regmap, 0x017, "\x11\x10", 2);
if (ret)
goto err;
 
/* mode */
-   ret = rtl2832_sdr_wr_regs(dev, 0x019, "\x05", 1);
+   ret 

[PATCH v6 24/24] [media] rtl2832: regmap is aware of lockdep, drop local locking hack

2016-04-03 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

Reviewed-by: Antti Palosaari <cr...@iki.fi>
Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/dvb-frontends/rtl2832.c  | 30 --
 drivers/media/dvb-frontends/rtl2832_priv.h |  1 -
 2 files changed, 31 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832.c 
b/drivers/media/dvb-frontends/rtl2832.c
index ac5ac5f7a335..23459fed2516 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -890,32 +890,6 @@ static bool rtl2832_volatile_reg(struct device *dev, 
unsigned int reg)
return false;
 }
 
-/*
- * FIXME: Hack. Implement own regmap locking in order to silence lockdep
- * recursive lock warning. That happens when regmap I2C client calls I2C mux
- * adapter, which leads demod I2C repeater enable via demod regmap. Operation
- * takes two regmap locks recursively - but those are different regmap 
instances
- * in a two different I2C drivers, so it is not deadlock. Proper fix is to make
- * regmap aware of lockdep.
- */
-static void rtl2832_regmap_lock(void *__dev)
-{
-   struct rtl2832_dev *dev = __dev;
-   struct i2c_client *client = dev->client;
-
-   dev_dbg(>dev, "\n");
-   mutex_lock(>regmap_mutex);
-}
-
-static void rtl2832_regmap_unlock(void *__dev)
-{
-   struct rtl2832_dev *dev = __dev;
-   struct i2c_client *client = dev->client;
-
-   dev_dbg(>dev, "\n");
-   mutex_unlock(>regmap_mutex);
-}
-
 static struct dvb_frontend *rtl2832_get_dvb_frontend(struct i2c_client *client)
 {
struct rtl2832_dev *dev = i2c_get_clientdata(client);
@@ -1082,12 +1056,8 @@ static int rtl2832_probe(struct i2c_client *client,
dev->sleeping = true;
INIT_DELAYED_WORK(>i2c_gate_work, rtl2832_i2c_gate_work);
/* create regmap */
-   mutex_init(>regmap_mutex);
dev->regmap_config.reg_bits =  8,
dev->regmap_config.val_bits =  8,
-   dev->regmap_config.lock = rtl2832_regmap_lock,
-   dev->regmap_config.unlock = rtl2832_regmap_unlock,
-   dev->regmap_config.lock_arg = dev,
dev->regmap_config.volatile_reg = rtl2832_volatile_reg,
dev->regmap_config.max_register = 5 * 0x100,
dev->regmap_config.ranges = regmap_range_cfg,
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h 
b/drivers/media/dvb-frontends/rtl2832_priv.h
index d8f97d14f6fd..c1a8a69e9015 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -33,7 +33,6 @@
 struct rtl2832_dev {
struct rtl2832_platform_data *pdata;
struct i2c_client *client;
-   struct mutex regmap_mutex;
struct regmap_config regmap_config;
struct regmap *regmap;
struct i2c_mux_core *muxc;
-- 
2.1.4

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


[PATCH v6 15/24] i2c-mux: drop old unused i2c-mux api

2016-04-03 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

All i2c mux users are using an explicit i2c mux core, drop support
for implicit i2c mux cores.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/i2c-mux.c   | 59 -
 include/linux/i2c-mux.h | 15 -
 2 files changed, 74 deletions(-)

diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index d95eb66e11bf..08d99e776a69 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -28,12 +28,6 @@
 #include 
 
 /* multiplexer per channel data */
-struct i2c_mux_priv_old {
-   void *mux_priv;
-   int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
-   int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
-};
-
 struct i2c_mux_priv {
struct i2c_adapter adap;
struct i2c_algorithm algo;
@@ -290,48 +284,6 @@ struct i2c_mux_core *i2c_mux_one_adapter(struct 
i2c_adapter *parent,
 }
 EXPORT_SYMBOL_GPL(i2c_mux_one_adapter);
 
-static int i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
-{
-   struct i2c_mux_priv_old *priv = i2c_mux_priv(muxc);
-
-   return priv->select(muxc->parent, priv->mux_priv, chan);
-}
-
-static int i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
-{
-   struct i2c_mux_priv_old *priv = i2c_mux_priv(muxc);
-
-   return priv->deselect(muxc->parent, priv->mux_priv, chan);
-}
-
-struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
-   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 i2c_mux_core *muxc;
-   struct i2c_mux_priv_old *priv;
-
-   muxc = i2c_mux_one_adapter(parent, mux_dev, sizeof(*priv), 0,
-  force_nr, chan_id, class,
-  i2c_mux_select,
-  deselect ? i2c_mux_deselect : NULL);
-   if (IS_ERR(muxc))
-   return NULL;
-
-   priv = i2c_mux_priv(muxc);
-   priv->select = select;
-   priv->deselect = deselect;
-   priv->mux_priv = mux_priv;
-
-   return muxc->adapter[0];
-}
-EXPORT_SYMBOL_GPL(i2c_add_mux_adapter);
-
 void i2c_mux_del_adapters(struct i2c_mux_core *muxc)
 {
char symlink_name[20];
@@ -353,17 +305,6 @@ void i2c_mux_del_adapters(struct i2c_mux_core *muxc)
 }
 EXPORT_SYMBOL_GPL(i2c_mux_del_adapters);
 
-void i2c_del_mux_adapter(struct i2c_adapter *adap)
-{
-   struct i2c_mux_priv *priv = adap->algo_data;
-   struct i2c_mux_core *muxc = priv->muxc;
-
-   i2c_mux_del_adapters(muxc);
-   devm_kfree(muxc->dev, muxc->adapter);
-   devm_kfree(muxc->dev, muxc);
-}
-EXPORT_SYMBOL_GPL(i2c_del_mux_adapter);
-
 MODULE_AUTHOR("Rodolfo Giometti <giome...@linux.it>");
 MODULE_DESCRIPTION("I2C driver for multiplexed I2C busses");
 MODULE_LICENSE("GPL v2");
diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h
index 0d97d7a3f03c..25c88ccf9c38 100644
--- a/include/linux/i2c-mux.h
+++ b/include/linux/i2c-mux.h
@@ -55,20 +55,6 @@ 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_adapter *parent,
-   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));
-/*
- * Called to create a i2c bus on a multiplexed bus segment.
  * The chan_id parameter is passed to the select and deselect
  * callback functions to perform hardware-specific mux control.
  */
@@ -88,7 +74,6 @@ struct i2c_mux_core *i2c_mux_one_adapter(struct i2c_adapter 
*parent,
 int (*deselect)(struct i2c_mux_core *,
 u32));
 
-void i2c_del_mux_adapter(struct i2c_adapter *adap);
 void i2c_mux_del_adapters(struct i2c_mux_core *muxc);
 
 #endif /* __KERNEL__ */
-- 
2.1.4

--
To unsubscribe from this list: send the line "

[PATCH v6 14/24] of/unittest: convert to use an explicit i2c mux core

2016-04-03 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

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

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/of/unittest.c | 40 +++-
 1 file changed, 15 insertions(+), 25 deletions(-)

diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index e986e6ee52e0..84a65b711e8c 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -1692,13 +1692,7 @@ static struct i2c_driver unittest_i2c_dev_driver = {
 
 #if IS_BUILTIN(CONFIG_I2C_MUX)
 
-struct unittest_i2c_mux_data {
-   int nchans;
-   struct i2c_adapter *adap[];
-};
-
-static int unittest_i2c_mux_select_chan(struct i2c_adapter *adap,
-  void *client, u32 chan)
+static int unittest_i2c_mux_select_chan(struct i2c_mux_core *muxc, u32 chan)
 {
return 0;
 }
@@ -1706,11 +1700,11 @@ static int unittest_i2c_mux_select_chan(struct 
i2c_adapter *adap,
 static int unittest_i2c_mux_probe(struct i2c_client *client,
const struct i2c_device_id *id)
 {
-   int ret, i, nchans, size;
+   int ret, i, nchans;
struct device *dev = >dev;
struct i2c_adapter *adap = to_i2c_adapter(dev->parent);
struct device_node *np = client->dev.of_node, *child;
-   struct unittest_i2c_mux_data *stm;
+   struct i2c_mux_core *muxc;
u32 reg, max_reg;
 
dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name);
@@ -1734,25 +1728,23 @@ static int unittest_i2c_mux_probe(struct i2c_client 
*client,
return -EINVAL;
}
 
-   size = offsetof(struct unittest_i2c_mux_data, adap[nchans]);
-   stm = devm_kzalloc(dev, size, GFP_KERNEL);
-   if (!stm) {
-   dev_err(dev, "Out of memory\n");
+   muxc = i2c_mux_alloc(adap, dev, 0, 0,
+unittest_i2c_mux_select_chan, NULL);
+   if (!muxc)
return -ENOMEM;
-   }
-   stm->nchans = nchans;
+   ret = i2c_mux_reserve_adapters(muxc, nchans);
+   if (ret)
+   return ret;
for (i = 0; i < nchans; i++) {
-   stm->adap[i] = i2c_add_mux_adapter(adap, dev, client,
-   0, i, 0, unittest_i2c_mux_select_chan, NULL);
-   if (!stm->adap[i]) {
+   ret = i2c_mux_add_adapter(muxc, 0, i, 0);
+   if (ret) {
dev_err(dev, "Failed to register mux #%d\n", i);
-   for (i--; i >= 0; i--)
-   i2c_del_mux_adapter(stm->adap[i]);
+   i2c_mux_del_adapters(muxc);
return -ENODEV;
}
}
 
-   i2c_set_clientdata(client, stm);
+   i2c_set_clientdata(client, muxc);
 
return 0;
 };
@@ -1761,12 +1753,10 @@ static int unittest_i2c_mux_remove(struct i2c_client 
*client)
 {
struct device *dev = >dev;
struct device_node *np = client->dev.of_node;
-   struct unittest_i2c_mux_data *stm = i2c_get_clientdata(client);
-   int i;
+   struct i2c_mux_core *muxc = i2c_get_clientdata(client);
 
dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name);
-   for (i = stm->nchans - 1; i >= 0; i--)
-   i2c_del_mux_adapter(stm->adap[i]);
+   i2c_mux_del_adapters(muxc);
return 0;
 }
 
-- 
2.1.4

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


[PATCH v6 18/24] i2c-mux: relax locking of the top i2c adapter during mux-locked muxing

2016-04-03 Thread Peter Rosin
From: Peter Rosin <p...@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).

Introduce this new locking concept as "mux-locked" muxes, and call the
pre-existing mux locking scheme "parent-locked".

Modify the i2c mux locking so that muxes that are "mux-locked" locks only
the muxes on the parent adapter 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 muxes on the parent adapter.

Add code to i2c-mux-gpio and i2c-mux-pinctrl that checks if all involved
gpio/pinctrl devices have a parent that is an i2c adapter in the same
adapter tree that is muxed, and request a "mux-locked mux" if that is the
case.

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

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/i2c/i2c-core.c  |   1 +
 drivers/i2c/i2c-mux.c   | 152 +---
 drivers/i2c/muxes/i2c-mux-gpio.c|  18 +
 drivers/i2c/muxes/i2c-mux-pinctrl.c |  38 +
 include/linux/i2c-mux.h |   6 ++
 include/linux/i2c.h |   1 +
 6 files changed, 203 insertions(+), 13 deletions(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 5314434c2b5d..53514ea314cd 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1543,6 +1543,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
}
 
rt_mutex_init(>bus_lock);
+   rt_mutex_init(>mux_lock);
mutex_init(>userspace_clients_lock);
INIT_LIST_HEAD(>userspace_clients);
 
diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index e1b2bb112efd..698b25816b65 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -35,6 +35,25 @@ struct i2c_mux_priv {
u32 chan_id;
 };
 
+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_master_xfer(struct i2c_adapter *adap,
   struct i2c_msg msgs[], int num)
 {
@@ -47,7 +66,29 @@ static int i2c_mux_master_xfer(struct i2c_adapter *adap,
 
ret = muxc->select(muxc, priv->chan_id);
if (ret >= 0)
-   ret = __i2c_transfer(parent, msgs, num);
+   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,
+   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 = parent->algo->smbus_xfer(parent, addr, flags,
+

[PATCH v6 13/24] [media] cx231xx: convert to use an explicit i2c mux core

2016-04-03 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

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

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 drivers/media/usb/cx231xx/cx231xx-core.c |  6 ++--
 drivers/media/usb/cx231xx/cx231xx-i2c.c  | 47 
 drivers/media/usb/cx231xx/cx231xx.h  |  4 ++-
 3 files changed, 31 insertions(+), 26 deletions(-)

diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c 
b/drivers/media/usb/cx231xx/cx231xx-core.c
index f497888d94bf..f7aac2abd783 100644
--- a/drivers/media/usb/cx231xx/cx231xx-core.c
+++ b/drivers/media/usb/cx231xx/cx231xx-core.c
@@ -1304,6 +1304,9 @@ int cx231xx_dev_init(struct cx231xx *dev)
cx231xx_i2c_register(>i2c_bus[1]);
cx231xx_i2c_register(>i2c_bus[2]);
 
+   errCode = cx231xx_i2c_mux_create(dev);
+   if (errCode < 0)
+   return errCode;
cx231xx_i2c_mux_register(dev, 0);
cx231xx_i2c_mux_register(dev, 1);
 
@@ -1426,8 +1429,7 @@ EXPORT_SYMBOL_GPL(cx231xx_dev_init);
 void cx231xx_dev_uninit(struct cx231xx *dev)
 {
/* Un Initialize I2C bus */
-   cx231xx_i2c_mux_unregister(dev, 1);
-   cx231xx_i2c_mux_unregister(dev, 0);
+   cx231xx_i2c_mux_unregister(dev);
cx231xx_i2c_unregister(>i2c_bus[2]);
cx231xx_i2c_unregister(>i2c_bus[1]);
cx231xx_i2c_unregister(>i2c_bus[0]);
diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c 
b/drivers/media/usb/cx231xx/cx231xx-i2c.c
index a29c345b027d..eb22e05d4add 100644
--- a/drivers/media/usb/cx231xx/cx231xx-i2c.c
+++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c
@@ -557,40 +557,41 @@ int cx231xx_i2c_unregister(struct cx231xx_i2c *bus)
  * cx231xx_i2c_mux_select()
  * switch i2c master number 1 between port1 and port3
  */
-static int cx231xx_i2c_mux_select(struct i2c_adapter *adap,
-   void *mux_priv, u32 chan_id)
+static int cx231xx_i2c_mux_select(struct i2c_mux_core *muxc, u32 chan_id)
 {
-   struct cx231xx *dev = mux_priv;
+   struct cx231xx *dev = i2c_mux_priv(muxc);
 
return cx231xx_enable_i2c_port_3(dev, chan_id);
 }
 
+int cx231xx_i2c_mux_create(struct cx231xx *dev)
+{
+   dev->muxc = i2c_mux_alloc(>i2c_bus[1].i2c_adap, dev->dev, 0, 0,
+ cx231xx_i2c_mux_select, NULL);
+   if (!dev->muxc)
+   return -ENOMEM;
+   dev->muxc->priv = dev;
+   return 0;
+}
+
 int cx231xx_i2c_mux_register(struct cx231xx *dev, int mux_no)
 {
-   struct i2c_adapter *i2c_parent = >i2c_bus[1].i2c_adap;
-   /* what is the correct mux_dev? */
-   struct device *mux_dev = dev->dev;
-
-   dev->i2c_mux_adap[mux_no] = i2c_add_mux_adapter(i2c_parent,
-   mux_dev,
-   dev /* mux_priv */,
-   0,
-   mux_no /* chan_id */,
-   0 /* class */,
-   _i2c_mux_select,
-   NULL);
-
-   if (!dev->i2c_mux_adap[mux_no])
+   int rc;
+
+   rc = i2c_mux_add_adapter(dev->muxc,
+0,
+mux_no /* chan_id */,
+0 /* class */);
+   if (rc)
dev_warn(dev->dev,
 "i2c mux %d register FAILED\n", mux_no);
 
-   return 0;
+   return rc;
 }
 
-void cx231xx_i2c_mux_unregister(struct cx231xx *dev, int mux_no)
+void cx231xx_i2c_mux_unregister(struct cx231xx *dev)
 {
-   i2c_del_mux_adapter(dev->i2c_mux_adap[mux_no]);
-   dev->i2c_mux_adap[mux_no] = NULL;
+   i2c_mux_del_adapters(dev->muxc);
 }
 
 struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx *dev, int i2c_port)
@@ -603,9 +604,9 @@ struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx 
*dev, int i2c_port)
case I2C_2:
return >i2c_bus[2].i2c_adap;
case I2C_1_MUX_1:
-   return dev->i2c_mux_adap[0];
+   return dev->muxc->adapter[0];
case I2C_1_MUX_3:
-   return dev->i2c_mux_adap[1];
+   return dev->muxc->adapter[1];
default:
return NULL;
}
diff --git a/drivers/media/usb/cx231xx/cx231xx.h 
b/drivers/media/usb/cx231xx/cx231xx.h
index 69f6d20870f5..90c867683076 100644
--- a/drivers/media/usb/cx231xx/cx231xx.h
+++ b/drivers/media/usb/cx231xx/cx231xx.h
@@ -624,6 +624,7 @@ struct cx231xx {
 
/* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
struct cx231xx_i2c i2c_bus[3];
+   struct i2c_mux_core *muxc;
struct i2c_adapter *i2c_mux_adap[2];
 
unsigned int xc_fw_load_done:1;
@@ -760,8 +761,9 @@ int cx231xx_reset_analog_tuner(struct cx231xx *dev);
 voi

[PATCH v6 17/24] i2c: muxes always lock the parent adapter

2016-04-03 Thread Peter Rosin
From: Peter Rosin <p...@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 <p...@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 21f46d011c33..5314434c2b5d 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -967,12 +967,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(>bus_lock);
+   rt_mutex_lock(>bus_lock);
 }
 
 /**
@@ -983,12 +978,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(>bus_lock);
+   return rt_mutex_trylock(>bus_lock);
 }
 
 /**
@@ -999,12 +989,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(>bus_lock);
+   rt_mutex_unlock(>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 08d99e776a69..e1b2bb112efd 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;
@@ -192,6 +216,9 @@ int i2c_mux_add_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

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


[PATCH v6 19/24] i2c-mux: document i2c muxes and elaborate on parent-/mux-locked muxes

2016-04-03 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/i2c/i2c-topology | 370 +
 MAINTAINERS|   1 +
 2 files changed, 371 insertions(+)
 create mode 100644 Documentation/i2c/i2c-topology

diff --git a/Documentation/i2c/i2c-topology b/Documentation/i2c/i2c-topology
new file mode 100644
index ..7a10edd0874f
--- /dev/null
+++ b/Documentation/i2c/i2c-topology
@@ -0,0 +1,370 @@
+I2C topology
+
+
+There are a couple of reasons for building more complex i2c topologies
+than a straight-forward i2c bus with one adapter and one or more devices.
+
+1. A mux may be needed on the bus to prevent address collisions.
+
+2. The bus may be accessible from some external bus master, and arbitration
+   may be needed to determine if it is ok to access the bus.
+
+3. A device (particularly RF tuners) may want to avoid the digital noise
+   from the i2c bus, at least most of the time, and sits behind a gate
+   that has to be operated before the device can be accessed.
+
+Etc
+
+These constructs are represented as i2c adapter trees by Linux, where
+each adapter has a parent adapter (except the root adapter) and zero or
+more child adapters. The root adapter is the actual adapter that issues
+i2c transfers, and all adapters with a parent are part of an "i2c-mux"
+object (quoted, since it can also be an arbitrator or a gate).
+
+Depending of the particular mux driver, something happens when there is
+an i2c transfer on one of its child adapters. The mux driver can
+obviously operate a mux, but it can also do arbitration with an external
+bus master or open a gate. The mux driver has two operations for this,
+select and deselect. select is called before the transfer and (the
+optional) deselect is called after the transfer.
+
+
+Locking
+===
+
+There are two variants of locking available to i2c muxes, they can be
+mux-locked or parent-locked muxes. As is evident from below, it can be
+useful to know if a mux is mux-locked or if it is parent-locked. The
+following list was correct at the time of writing:
+
+In drivers/i2c/muxes/
+i2c-arb-gpio-challengeParent-locked
+i2c-mux-gpio  Normally parent-locked, mux-locked iff
+  all involved gpio pins are controlled by the
+  same i2c root adapter that they mux.
+i2c-mux-pca9541   Parent-locked
+i2c-mux-pca954x   Parent-locked
+i2c-mux-pinctrl   Normally parent-locked, mux-locked iff
+  all involved pinctrl devices are controlled
+  by the same i2c root adapter that they mux.
+i2c-mux-reg   Parent-locked
+
+In drivers/iio/
+imu/inv_mpu6050/  Parent-locked
+
+In drivers/media/
+dvb-frontends/m88ds3103   Parent-locked
+dvb-frontends/rtl2830 Parent-locked
+dvb-frontends/rtl2832 Parent-locked
+dvb-frontends/si2168  Parent-locked
+usb/cx231xx/  Parent-locked
+
+
+Mux-locked muxes
+
+
+Mux-locked muxes does not lock the entire parent adapter during the
+full select-transfer-deselect transaction, only the muxes on the parent
+adapter are locked. Mux-locked muxes are mostly interesting if the
+select and/or deselect operations must use i2c transfers to complete
+their tasks. Since the parent adapter is not fully locked during the
+full transaction, unrelated i2c transfers may interleave the different
+stages of the transaction. This has the benefit that the mux driver
+may be easier and cleaner to implement, but it has some caveats.
+
+ML1. If you build a topology with a mux-locked mux being the parent
+ of a parent-locked mux, this might break the expectation from the
+ parent-locked mux that the root adapter is locked during the
+ transaction.
+
+ML2. It is not safe to build arbitrary topologies with two (or more)
+ mux-locked muxes that are not siblings, when there are address
+ collisions between the devices on the child adapters of these
+ non-sibling muxes.
+
+ I.e. the select-transfer-deselect transaction targeting e.g. device
+ address 0x42 behind mux-one may be interleaved with a similar
+ operation targeting device address 0x42 behind mux-two. The
+ intension with such a topology would in this hypothetical example
+ be that mux-one and mux-two should not be selected simultaneously,
+ but mux-locked muxes do not guarantee that in all topologies.
+
+ML3. A mux-locked mux cannot be used by a driver for auto-closing
+ gates/muxes, i.e. something that closes automatically after a given
+ number (one, in most cases) of i2c transfers. Unrelated i2c transfers
+ may creep in and close prematurely.
+
+ML4. If any non-i2c operation in the mux driver changes the i2c mux state,
+ the driver has to lock the root adapter during that operation.
+ Otherwise garbage may appear on the bu

[PATCH v6 22/24] [media] rtl2832: change the i2c gate to be mux-locked

2016-04-03 Thread Peter Rosin
From: Peter Rosin <p...@axentia.se>

The root i2c adapter lock is then no longer held by the i2c mux during
accesses behind the i2c gate, and such accesses need to take that lock
just like any other ordinary i2c accesses do.

So, declare the i2c gate mux-locked, and zap the regmap overrides
that makes the i2c accesses unlocked and use plain old regmap
accesses. This also removes the need for the regmap wrappers used by
rtl2832_sdr, so deconvolute the code further and provide the regmap
handle directly instead of the wrapper functions.

Signed-off-by: Peter Rosin <p...@axentia.se>
---
 Documentation/i2c/i2c-topology|   2 +-
 drivers/media/dvb-frontends/rtl2832.c | 191 +-
 drivers/media/dvb-frontends/rtl2832.h |   4 +-
 drivers/media/dvb-frontends/rtl2832_sdr.c |  13 +-
 drivers/media/dvb-frontends/rtl2832_sdr.h |   5 +-
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c   |   5 +-
 6 files changed, 38 insertions(+), 182 deletions(-)

diff --git a/Documentation/i2c/i2c-topology b/Documentation/i2c/i2c-topology
index a9ca97df7661..3f359bd93591 100644
--- a/Documentation/i2c/i2c-topology
+++ b/Documentation/i2c/i2c-topology
@@ -55,7 +55,7 @@ imu/inv_mpu6050/  Mux-locked
 In drivers/media/
 dvb-frontends/m88ds3103   Parent-locked
 dvb-frontends/rtl2830 Parent-locked
-dvb-frontends/rtl2832 Parent-locked
+dvb-frontends/rtl2832 Mux-locked
 dvb-frontends/si2168  Mux-locked
 usb/cx231xx/  Parent-locked
 
diff --git a/drivers/media/dvb-frontends/rtl2832.c 
b/drivers/media/dvb-frontends/rtl2832.c
index 545c3bbbc668..ac5ac5f7a335 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -153,43 +153,6 @@ static const struct rtl2832_reg_entry registers[] = {
[DVBT_REG_4MSEL]= {0x013,  0, 0},
 };
 
-/* Our regmap is bypassing I2C adapter lock, thus we do it! */
-static int rtl2832_bulk_write(struct i2c_client *client, unsigned int reg,
- const void *val, size_t val_count)
-{
-   struct rtl2832_dev *dev = i2c_get_clientdata(client);
-   int ret;
-
-   i2c_lock_adapter(client->adapter);
-   ret = regmap_bulk_write(dev->regmap, reg, val, val_count);
-   i2c_unlock_adapter(client->adapter);
-   return ret;
-}
-
-static int rtl2832_update_bits(struct i2c_client *client, unsigned int reg,
-  unsigned int mask, unsigned int val)
-{
-   struct rtl2832_dev *dev = i2c_get_clientdata(client);
-   int ret;
-
-   i2c_lock_adapter(client->adapter);
-   ret = regmap_update_bits(dev->regmap, reg, mask, val);
-   i2c_unlock_adapter(client->adapter);
-   return ret;
-}
-
-static int rtl2832_bulk_read(struct i2c_client *client, unsigned int reg,
-void *val, size_t val_count)
-{
-   struct rtl2832_dev *dev = i2c_get_clientdata(client);
-   int ret;
-
-   i2c_lock_adapter(client->adapter);
-   ret = regmap_bulk_read(dev->regmap, reg, val, val_count);
-   i2c_unlock_adapter(client->adapter);
-   return ret;
-}
-
 static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, int reg, u32 *val)
 {
struct i2c_client *client = dev->client;
@@ -204,7 +167,7 @@ static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, 
int reg, u32 *val)
len = (msb >> 3) + 1;
mask = REG_MASK(msb - lsb);
 
-   ret = rtl2832_bulk_read(client, reg_start_addr, reading, len);
+   ret = regmap_bulk_read(dev->regmap, reg_start_addr, reading, len);
if (ret)
goto err;
 
@@ -234,7 +197,7 @@ static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, 
int reg, u32 val)
len = (msb >> 3) + 1;
mask = REG_MASK(msb - lsb);
 
-   ret = rtl2832_bulk_read(client, reg_start_addr, reading, len);
+   ret = regmap_bulk_read(dev->regmap, reg_start_addr, reading, len);
if (ret)
goto err;
 
@@ -248,7 +211,7 @@ static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, 
int reg, u32 val)
for (i = 0; i < len; i++)
writing[i] = (writing_tmp >> ((len - 1 - i) * 8)) & 0xff;
 
-   ret = rtl2832_bulk_write(client, reg_start_addr, writing, len);
+   ret = regmap_bulk_write(dev->regmap, reg_start_addr, writing, len);
if (ret)
goto err;
 
@@ -525,7 +488,8 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe)
}
 
for (j = 0; j < sizeof(bw_params[0]); j++) {
-   ret = rtl2832_bulk_write(client, 0x11c + j, _params[i][j], 
1);
+   ret = regmap_bulk_write(dev->regmap,
+   0x11c + j, _params[i][j], 1);
if (ret)
goto err;
}
@@ -581,11 +545,11 @@ static int rtl2832_get_frontend(struct dvb_frontend *fe,
if (dev->sleeping)
return 0;
 
-   ret =

  1   2   >