diff mbox

[07/21] ASoC: io: Prevent use of regmap if request fails

Message ID 1343298534-13611-8-git-send-email-lee.jones@linaro.org (mailing list archive)
State New, archived
Headers show

Commit Message

Lee Jones July 26, 2012, 10:28 a.m. UTC
If a sound codec fails to request a regmap, the 'using_regmap' is
set as true regardless, despite there being no regmap to use. As a
repercussion, when a latter read function checks to see if we are
using regmaps, it assumes we are and attempts to. Only the kernel
oopes, because regmap_* tries to extract information from a NULL
pointer.

Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 sound/soc/soc-io.c |   14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

Comments

Mark Brown July 26, 2012, 11:32 a.m. UTC | #1
On Thu, Jul 26, 2012 at 11:28:40AM +0100, Lee Jones wrote:

> @@ -52,10 +52,13 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
>  		if (codec->cache_only)
>  			return -1;
>  
> -		ret = regmap_read(codec->control_data, reg, &val);
> -		if (ret == 0)
> -			return val;
> -		else
> +		if (codec->using_regmap) {
> +			ret = regmap_read(codec->control_data, reg, &val);
> +			if (ret == 0)
> +				return val;
> +			else
> +				return -1;
> +		} else

No, this makes no sense.  There is no non-regmap I/O support in soc-io,
anything using the soc-io hw_read() function must be using regmap.

>  	case SND_SOC_REGMAP:
>  		/* Device has made its own regmap arrangements */
> -		codec->using_regmap = true;

Again, this makes no sense.  If we're explicitly being asked to use
regmap then we should be using regmap or just failing to set up I/O
(which is obviously a catastrophic failure).
Lee Jones July 26, 2012, 11:38 a.m. UTC | #2
On 26/07/12 12:32, Mark Brown wrote:
> On Thu, Jul 26, 2012 at 11:28:40AM +0100, Lee Jones wrote:
>
>> @@ -52,10 +52,13 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
>>   		if (codec->cache_only)
>>   			return -1;
>>
>> -		ret = regmap_read(codec->control_data, reg, &val);
>> -		if (ret == 0)
>> -			return val;
>> -		else
>> +		if (codec->using_regmap) {
>> +			ret = regmap_read(codec->control_data, reg, &val);
>> +			if (ret == 0)
>> +				return val;
>> +			else
>> +				return -1;
>> +		} else
>
> No, this makes no sense.  There is no non-regmap I/O support in soc-io,
> anything using the soc-io hw_read() function must be using regmap.
>
>>   	case SND_SOC_REGMAP:
>>   		/* Device has made its own regmap arrangements */
>> -		codec->using_regmap = true;
>
> Again, this makes no sense.  If we're explicitly being asked to use
> regmap then we should be using regmap or just failing to set up I/O
> (which is obviously a catastrophic failure).

How much work is there involved in regmap:ing a device, so that 
dev_get_regmap() doesn't fail?
Mark Brown July 26, 2012, 11:42 a.m. UTC | #3
On Thu, Jul 26, 2012 at 12:38:17PM +0100, Lee Jones wrote:
> On 26/07/12 12:32, Mark Brown wrote:

> >Again, this makes no sense.  If we're explicitly being asked to use
> >regmap then we should be using regmap or just failing to set up I/O
> >(which is obviously a catastrophic failure).

> How much work is there involved in regmap:ing a device, so that
> dev_get_regmap() doesn't fail?

Trivial if it's on a supported bus, otherwise you just need to write the
bus.  But why do you care if dev_get_regmap() fails?  We only try to use
regmap if the driver asked for regmap I/O (or doesn't have registers at
all in which case it doesn't matter since we never do any I/O).  What
you appear to be saying here is that you're using regmap on a device
which doesn't have a regmap set up which is clearly never going to work
terribly well...
Lee Jones July 26, 2012, 2:51 p.m. UTC | #4
On 26/07/12 12:42, Mark Brown wrote:
> On Thu, Jul 26, 2012 at 12:38:17PM +0100, Lee Jones wrote:
>> On 26/07/12 12:32, Mark Brown wrote:
>
>>> Again, this makes no sense.  If we're explicitly being asked to use
>>> regmap then we should be using regmap or just failing to set up I/O
>>> (which is obviously a catastrophic failure).
>
>> How much work is there involved in regmap:ing a device, so that
>> dev_get_regmap() doesn't fail?
>
> Trivial if it's on a supported bus, otherwise you just need to write the
> bus.  But why do you care if dev_get_regmap() fails?  We only try to use
> regmap if the driver asked for regmap I/O (or doesn't have registers at
> all in which case it doesn't matter since we never do any I/O).  What
> you appear to be saying here is that you're using regmap on a device
> which doesn't have a regmap set up which is clearly never going to work
> terribly well...

I don't think we want to use regmap at all, but we're forced to by 
soc-core. How do we over-ride that behavior? By writing some nonsense 
into codec->control_data?
Mark Brown July 26, 2012, 3:12 p.m. UTC | #5
On Thu, Jul 26, 2012 at 03:51:13PM +0100, Lee Jones wrote:

> I don't think we want to use regmap at all, but we're forced to by
> soc-core. How do we over-ride that behavior? By writing some
> nonsense into codec->control_data?

You should use that for your control data, yes - you're not forced to
use regmap at all.  Like I say we've got a bunch of drivers doing so
already.
Lee Jones July 26, 2012, 3:23 p.m. UTC | #6
On 26/07/12 16:12, Mark Brown wrote:
> On Thu, Jul 26, 2012 at 03:51:13PM +0100, Lee Jones wrote:
>
>> I don't think we want to use regmap at all, but we're forced to by
>> soc-core. How do we over-ride that behavior? By writing some
>> nonsense into codec->control_data?
>
> You should use that for your control data, yes - you're not forced to
> use regmap at all.  Like I say we've got a bunch of drivers doing so
> already.

What's my 'control data'? It's not used in the original codec patch.

The old way wants to go:

snd_soc_update_bits() -> snd_soc_read() -> ab8500_codec_read_reg()

When then calls back into the abx500.

So what 'control data' should I be storing in the codec struct?
Mark Brown July 26, 2012, 3:25 p.m. UTC | #7
On Thu, Jul 26, 2012 at 04:23:33PM +0100, Lee Jones wrote:

> What's my 'control data'? It's not used in the original codec patch.

> The old way wants to go:

> snd_soc_update_bits() -> snd_soc_read() -> ab8500_codec_read_reg()

> When then calls back into the abx500.

> So what 'control data' should I be storing in the codec struct?

You're supposed to use it for the data you use to call back into the
underlying I/O code.
Lee Jones July 26, 2012, 4:05 p.m. UTC | #8
On 26/07/12 16:25, Mark Brown wrote:
> On Thu, Jul 26, 2012 at 04:23:33PM +0100, Lee Jones wrote:
>
>> What's my 'control data'? It's not used in the original codec patch.
>
>> The old way wants to go:
>
>> snd_soc_update_bits() -> snd_soc_read() -> ab8500_codec_read_reg()
>
>> When then calls back into the abx500.
>
>> So what 'control data' should I be storing in the codec struct?
>
> You're supposed to use it for the data you use to call back into the
> underlying I/O code.

I don't understand. What 'data'?

Surely if .read and .write are populated in 'struct 
snd_soc_codec_driver', then it should just call back into those?
Mark Brown July 26, 2012, 8:23 p.m. UTC | #9
On Thu, Jul 26, 2012 at 05:05:51PM +0100, Lee Jones wrote:
> On 26/07/12 16:25, Mark Brown wrote:

> >You're supposed to use it for the data you use to call back into the
> >underlying I/O code.

> I don't understand. What 'data'?

Whatever your I/O layer so desires, the core doesn't care.  It's
generally whatever the lower layer that does your I/O takes to identify
the device.

> Surely if .read and .write are populated in 'struct
> snd_soc_codec_driver', then it should just call back into those?

Yes, and in fact that's what we do!
diff mbox

Patch

diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
index 29183ef..601cb7f 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -52,10 +52,13 @@  static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
 		if (codec->cache_only)
 			return -1;
 
-		ret = regmap_read(codec->control_data, reg, &val);
-		if (ret == 0)
-			return val;
-		else
+		if (codec->using_regmap) {
+			ret = regmap_read(codec->control_data, reg, &val);
+			if (ret == 0)
+				return val;
+			else
+				return -1;
+		} else
 			return -1;
 	}
 
@@ -141,11 +144,12 @@  int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
 
 	case SND_SOC_REGMAP:
 		/* Device has made its own regmap arrangements */
-		codec->using_regmap = true;
 		if (!codec->control_data)
 			codec->control_data = dev_get_regmap(codec->dev, NULL);
 
 		if (codec->control_data) {
+			codec->using_regmap = true;
+
 			ret = regmap_get_val_bytes(codec->control_data);
 			/* Errors are legitimate for non-integer byte
 			 * multiples */