All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] lgdt3306a: fix bugs in usb disconnect/reconnect
@ 2018-01-05 14:57 Brad Love
  2018-01-05 14:57 ` [PATCH 1/2] lgdt3306a: Fix module count mismatch on usb unplug Brad Love
  2018-01-05 14:57 ` [PATCH 2/2] lgdt3306a: Fix a double kfree on i2c device remove Brad Love
  0 siblings, 2 replies; 5+ messages in thread
From: Brad Love @ 2018-01-05 14:57 UTC (permalink / raw)
  To: linux-media; +Cc: Brad Love

There are a couple problems currently in this driver, when used as
an i2c_device. This patch set addresses the issues one at a time.

First during process of dvb frontend detach release is called, then
if CONFIG_MEDIA_ATTACH is enabled, the usage count is decremented.
Remove is then called, further decrementing the usage count, to negative
if a single device was attached. Patch one uses dvb_attach to keep the
usage count in sync on removal. I'm not sure if there is a less
'hacky' way to handle this. On a previous attempt I just NULL'd out
release in probe, which just hid the issue. Another way of sorting
out was doing a symbol_get on _attach, but the included patch seems
most consistent behaviour.

Next, there is a double kfree of state which can cause oops/GPF/etc
randomly on removal. In the process of dvb frontend detach release
is called before remove. The problem is _release kfree's state, then
right after _remove cleans up members of state, before kfree'ing
state itself. Patch 2 does not kfree state in _release if the
driver was probed and therefore _remove will be called.


Brad Love (2):
  lgdt3306a: Fix module count mismatch on usb unplug
  lgdt3306a: Fix a double kfree on i2c device remove

 drivers/media/dvb-frontends/lgdt3306a.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

-- 
2.7.4

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

* [PATCH 1/2] lgdt3306a: Fix module count mismatch on usb unplug
  2018-01-05 14:57 [PATCH 0/2] lgdt3306a: fix bugs in usb disconnect/reconnect Brad Love
@ 2018-01-05 14:57 ` Brad Love
  2018-01-05 14:57 ` [PATCH 2/2] lgdt3306a: Fix a double kfree on i2c device remove Brad Love
  1 sibling, 0 replies; 5+ messages in thread
From: Brad Love @ 2018-01-05 14:57 UTC (permalink / raw)
  To: linux-media; +Cc: Brad Love

When used as an i2c device there is a module usage count mismatch on
removal, preventing the driver from being used thereafter. dvb_attach
increments the usage count so it is properly balanced on removal.

On disconnect of Hauppauge SoloHD/DualHD before:

lsmod | grep lgdt3306a
lgdt3306a              28672  -1
i2c_mux                16384  1 lgdt3306a

On disconnect of Hauppauge SoloHD/DualHD after:

lsmod | grep lgdt3306a
lgdt3306a              28672  0
i2c_mux                16384  1 lgdt3306a

Signed-off-by: Brad Love <brad@nextdimension.cc>
---
 drivers/media/dvb-frontends/lgdt3306a.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c
index 6356815..d370671 100644
--- a/drivers/media/dvb-frontends/lgdt3306a.c
+++ b/drivers/media/dvb-frontends/lgdt3306a.c
@@ -2169,7 +2169,7 @@ static int lgdt3306a_probe(struct i2c_client *client,
 			sizeof(struct lgdt3306a_config));
 
 	config->i2c_addr = client->addr;
-	fe = lgdt3306a_attach(config, client->adapter);
+	fe = dvb_attach(lgdt3306a_attach, config, client->adapter);
 	if (fe == NULL) {
 		ret = -ENODEV;
 		goto err_fe;
-- 
2.7.4

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

* [PATCH 2/2] lgdt3306a: Fix a double kfree on i2c device remove
  2018-01-05 14:57 [PATCH 0/2] lgdt3306a: fix bugs in usb disconnect/reconnect Brad Love
  2018-01-05 14:57 ` [PATCH 1/2] lgdt3306a: Fix module count mismatch on usb unplug Brad Love
@ 2018-01-05 14:57 ` Brad Love
  2018-01-08 20:34   ` Matthias Schwarzott
  1 sibling, 1 reply; 5+ messages in thread
From: Brad Love @ 2018-01-05 14:57 UTC (permalink / raw)
  To: linux-media; +Cc: Brad Love

Both lgdt33606a_release and lgdt3306a_remove kfree state, but _release is
called first, then _remove operates on states members before kfree'ing it.
This can lead to random oops/GPF/etc on USB disconnect.

Signed-off-by: Brad Love <brad@nextdimension.cc>
---
 drivers/media/dvb-frontends/lgdt3306a.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c
index d370671..3642e6e 100644
--- a/drivers/media/dvb-frontends/lgdt3306a.c
+++ b/drivers/media/dvb-frontends/lgdt3306a.c
@@ -1768,7 +1768,13 @@ static void lgdt3306a_release(struct dvb_frontend *fe)
 	struct lgdt3306a_state *state = fe->demodulator_priv;
 
 	dbg_info("\n");
-	kfree(state);
+
+	/*
+	 * If state->muxc is not NULL, then we are an i2c device
+	 * and lgdt3306a_remove will clean up state
+	 */
+	if (!state->muxc)
+		kfree(state);
 }
 
 static const struct dvb_frontend_ops lgdt3306a_ops;
-- 
2.7.4

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

* Re: [PATCH 2/2] lgdt3306a: Fix a double kfree on i2c device remove
  2018-01-05 14:57 ` [PATCH 2/2] lgdt3306a: Fix a double kfree on i2c device remove Brad Love
@ 2018-01-08 20:34   ` Matthias Schwarzott
  2018-01-08 20:43     ` Brad Love
  0 siblings, 1 reply; 5+ messages in thread
From: Matthias Schwarzott @ 2018-01-08 20:34 UTC (permalink / raw)
  To: Brad Love, linux-media

Am 05.01.2018 um 15:57 schrieb Brad Love:
> Both lgdt33606a_release and lgdt3306a_remove kfree state, but _release is
> called first, then _remove operates on states members before kfree'ing it.
> This can lead to random oops/GPF/etc on USB disconnect.
> 
lgdt3306a_release does nothing but the kfree. So the exact same effect
can be archived by setting state->frontend.ops.release to NULL. This
need to be done already at probe time I think.
lgdt3306a_remove does this, but too late (after the call to release).

Regards
Matthias

> Signed-off-by: Brad Love <brad@nextdimension.cc>
> ---
>  drivers/media/dvb-frontends/lgdt3306a.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c
> index d370671..3642e6e 100644
> --- a/drivers/media/dvb-frontends/lgdt3306a.c
> +++ b/drivers/media/dvb-frontends/lgdt3306a.c
> @@ -1768,7 +1768,13 @@ static void lgdt3306a_release(struct dvb_frontend *fe)
>  	struct lgdt3306a_state *state = fe->demodulator_priv;
>  
>  	dbg_info("\n");
> -	kfree(state);
> +
> +	/*
> +	 * If state->muxc is not NULL, then we are an i2c device
> +	 * and lgdt3306a_remove will clean up state
> +	 */
> +	if (!state->muxc)
> +		kfree(state);
>  }
>  
>  static const struct dvb_frontend_ops lgdt3306a_ops;
> 

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

* Re: [PATCH 2/2] lgdt3306a: Fix a double kfree on i2c device remove
  2018-01-08 20:34   ` Matthias Schwarzott
@ 2018-01-08 20:43     ` Brad Love
  0 siblings, 0 replies; 5+ messages in thread
From: Brad Love @ 2018-01-08 20:43 UTC (permalink / raw)
  To: Matthias Schwarzott, Brad Love, linux-media


On 2018-01-08 14:34, Matthias Schwarzott wrote:
> Am 05.01.2018 um 15:57 schrieb Brad Love:
>> Both lgdt33606a_release and lgdt3306a_remove kfree state, but _release is
>> called first, then _remove operates on states members before kfree'ing it.
>> This can lead to random oops/GPF/etc on USB disconnect.
>>
> lgdt3306a_release does nothing but the kfree. So the exact same effect
> can be archived by setting state->frontend.ops.release to NULL. This
> need to be done already at probe time I think.
> lgdt3306a_remove does this, but too late (after the call to release).
>
> Regards
> Matthias

Hi Matthias,

I agree. This was my rationale in the previous patch:

/patch/46328

Both methods handle the issue. I thought the previous
attempt was fairly clean, but it did not pass review, so
I provided this solution.

Cheers,

Brad







>> Signed-off-by: Brad Love <brad@nextdimension.cc>
>> ---
>>  drivers/media/dvb-frontends/lgdt3306a.c | 8 +++++++-
>>  1 file changed, 7 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c
>> index d370671..3642e6e 100644
>> --- a/drivers/media/dvb-frontends/lgdt3306a.c
>> +++ b/drivers/media/dvb-frontends/lgdt3306a.c
>> @@ -1768,7 +1768,13 @@ static void lgdt3306a_release(struct dvb_frontend *fe)
>>  	struct lgdt3306a_state *state = fe->demodulator_priv;
>>  
>>  	dbg_info("\n");
>> -	kfree(state);
>> +
>> +	/*
>> +	 * If state->muxc is not NULL, then we are an i2c device
>> +	 * and lgdt3306a_remove will clean up state
>> +	 */
>> +	if (!state->muxc)
>> +		kfree(state);
>>  }
>>  
>>  static const struct dvb_frontend_ops lgdt3306a_ops;
>>

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

end of thread, other threads:[~2018-01-08 20:43 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-05 14:57 [PATCH 0/2] lgdt3306a: fix bugs in usb disconnect/reconnect Brad Love
2018-01-05 14:57 ` [PATCH 1/2] lgdt3306a: Fix module count mismatch on usb unplug Brad Love
2018-01-05 14:57 ` [PATCH 2/2] lgdt3306a: Fix a double kfree on i2c device remove Brad Love
2018-01-08 20:34   ` Matthias Schwarzott
2018-01-08 20:43     ` Brad Love

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.