From 7a0af6ed97f2f08baecb452e719d9c961d117109 Mon Sep 17 00:00:00 2001 From: Changbing Xiong Date: Wed, 20 Aug 2014 23:04:25 -0300 Subject: [media] media: fix kernel deadlock due to tuner pull-out while playing Normally, ADAP_STREAMING bit is set in dvb_usb_start_feed and cleared in dvb_usb_stop_feed. But in exceptional cases, for example, when the tv is playing programs and the tuner is pulled out, then dvb_usbv2_disconnect is called. In such case, it will first call dvb_usbv2_adapter_frontend_exit to stop dvb_frontend_thread, and then call dvb_usbv2_adapter_dvb_exit to clear ADAP_STREAMING bit. At this point, if dvb_frontend_thread is sleeping and waiting for ADAP_STREAMING to be cleared to get out of sleep. then dvb_frontend_thread can never be stoped, because clearing ADAP_STREAMING bit is performed after dvb_frontend_thread is stopped (i.e. performed in dvb_usbv2_adapter_dvb_exit). So, deadlock: [ 240.822037] INFO: task khubd:497 blocked for more than 120 seconds. [ 240.822655] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 240.830493] khubd D c0013b3c 0 497 2 0x00000000 [ 240.836996] [] (__schedule+0x200/0x54c) from [] (schedule_timeout+0x14c/0x19c) [ 240.845940] [] (schedule_timeout+0x14c/0x19c) from [] (wait_for_common+0xac/0x150) [ 240.855234] [] (wait_for_common+0xac/0x150) from [] (kthread_stop+0x58/0x90) [ 240.864004] [] (kthread_stop+0x58/0x90) from [] (dvb_frontend_stop+0x3c/0x9c) [ 240.872849] [] (dvb_frontend_stop+0x3c/0x9c) from [] (dvb_unregister_frontend+0x20/0xd8) [ 240.882666] [] (dvb_unregister_frontend+0x20/0xd8) from [] (dvb_usbv2_exit+0x68/0xfc) [ 240.892204] [] (dvb_usbv2_exit+0x68/0xfc) from [] (dvb_usbv2_disconnect+0x4c/0x70) [ 240.901499] [] (dvb_usbv2_disconnect+0x4c/0x70) from [] (usb_unbind_interface+0x58/0x188) [ 240.911395] [] (usb_unbind_interface+0x58/0x188) from [] (__device_release_driver+0x74/0xd0) [ 240.921544] [] (__device_release_driver+0x74/0xd0) from [] (device_release_driver+0x1c/0x28) [ 240.931697] [] (device_release_driver+0x1c/0x28) from [] (bus_remove_device+0xc4/0xe4) [ 240.941332] [] (bus_remove_device+0xc4/0xe4) from [] (device_del+0xf4/0x178) [ 240.950106] [] (device_del+0xf4/0x178) from [] (usb_disable_device+0xa0/0x1c8) [ 240.959040] [] (usb_disable_device+0xa0/0x1c8) from [] (usb_disconnect+0x88/0x188) [ 240.968326] [] (usb_disconnect+0x88/0x188) from [] (hub_thread+0x4d0/0x1200) [ 240.977100] [] (hub_thread+0x4d0/0x1200) from [] (kthread+0xa4/0xb0) [ 240.985174] [] (kthread+0xa4/0xb0) from [] (ret_from_fork+0x14/0x3c) [ 240.993259] INFO: task kdvb-ad-0-fe-0:3256 blocked for more than 120 seconds. [ 241.000349] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 241.008162] kdvb-ad-0-fe-0 D c0013b3c 0 3256 2 0x00000000 [ 241.014507] [] (__schedule+0x200/0x54c) from [] (wait_schedule+0x8/0x10) [ 241.022924] [] (wait_schedule+0x8/0x10) from [] (__wait_on_bit+0x74/0xb8) [ 241.031434] [] (__wait_on_bit+0x74/0xb8) from [] (out_of_line_wait_on_bit+0x68/0x70) [ 241.040902] [] (out_of_line_wait_on_bit+0x68/0x70) from [] (dvb_usb_fe_sleep+0xf4/0xfc) [ 241.050618] [] (dvb_usb_fe_sleep+0xf4/0xfc) from [] (dvb_frontend_thread+0x124/0x4e8) [ 241.060164] [] (dvb_frontend_thread+0x124/0x4e8) from [] (kthread+0xa4/0xb0) [ 241.068929] [] (kthread+0xa4/0xb0) from [] (ret_from_fork+0x14/0x3c) Fix it by calling dvb_usbv2_adapter_frontend_exit() latter. Test enviroment: odroidx2 + Hauppauge(WinTV-Aero-M) Signed-off-by: Changbing Xiong Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/usb/dvb-usb-v2/dvb_usb_core.c') diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index 2e90310be2af..6c33d8525454 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -762,9 +762,9 @@ static int dvb_usbv2_adapter_exit(struct dvb_usb_device *d) for (i = MAX_NO_OF_ADAPTER_PER_DEVICE - 1; i >= 0; i--) { if (d->adapter[i].props) { - dvb_usbv2_adapter_frontend_exit(&d->adapter[i]); dvb_usbv2_adapter_dvb_exit(&d->adapter[i]); dvb_usbv2_adapter_stream_exit(&d->adapter[i]); + dvb_usbv2_adapter_frontend_exit(&d->adapter[i]); } } -- cgit v1.2.3-55-g7522 From 6812667381d4e7d1baa93464af6fd02175db96de Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 20 Aug 2014 19:26:47 -0300 Subject: [media] dvb_usb_core: fix sparse warning drivers/media/usb/dvb-usb-v2/dvb_usb_core.c:24:5: warning: symbol 'dvb_usbv2_disable_rc_polling' was not declared. Should it be static? Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/usb/dvb-usb-v2/dvb_usb_core.c') diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index 6c33d8525454..adca05f27fba 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -21,7 +21,7 @@ #include "dvb_usb_common.h" -int dvb_usbv2_disable_rc_polling; +static int dvb_usbv2_disable_rc_polling; module_param_named(disable_rc_polling, dvb_usbv2_disable_rc_polling, int, 0644); MODULE_PARM_DESC(disable_rc_polling, "disable remote control polling (default: 0)"); -- cgit v1.2.3-55-g7522 From ca42129f867fbc427d709408b3ae35988cc08ed4 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 4 Sep 2014 17:04:44 -0300 Subject: [media] dvb-usb-v2: add frontend_detach callback Add frontend_detach callback in order to allow custom detach. It is needed when demod driver is implemented I2C client or some other kernel bus, but not proprietary dvb_attach / dvb_detach. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/dvb_usb.h | 2 ++ drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers/media/usb/dvb-usb-v2/dvb_usb_core.c') diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h index 124b4baa7e97..7e36ee02f957 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h @@ -214,6 +214,7 @@ struct dvb_usb_adapter_properties { * @read_config: called to resolve device configuration * @read_mac_address: called to resolve adapter mac-address * @frontend_attach: called to attach the possible frontends + * @frontend_detach: called to detach the possible frontends * @tuner_attach: called to attach the possible tuners * @frontend_ctrl: called to power on/off active frontend * @streaming_ctrl: called to start/stop the usb streaming of adapter @@ -254,6 +255,7 @@ struct dvb_usb_device_properties { int (*read_config) (struct dvb_usb_device *d); int (*read_mac_address) (struct dvb_usb_adapter *, u8 []); int (*frontend_attach) (struct dvb_usb_adapter *); + int (*frontend_detach)(struct dvb_usb_adapter *); int (*tuner_attach) (struct dvb_usb_adapter *); int (*frontend_ctrl) (struct dvb_frontend *, int); int (*streaming_ctrl) (struct dvb_frontend *, int); diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index adca05f27fba..02c43b52c906 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -664,9 +664,10 @@ err: static int dvb_usbv2_adapter_frontend_exit(struct dvb_usb_adapter *adap) { - int i; - dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__, - adap->id); + int ret, i; + struct dvb_usb_device *d = adap_to_d(adap); + + dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id); for (i = MAX_NO_OF_FE_PER_ADAP - 1; i >= 0; i--) { if (adap->fe[i]) { @@ -675,6 +676,15 @@ static int dvb_usbv2_adapter_frontend_exit(struct dvb_usb_adapter *adap) } } + if (d->props->frontend_detach) { + ret = d->props->frontend_detach(adap); + if (ret < 0) { + dev_dbg(&d->udev->dev, + "%s: frontend_detach() failed=%d\n", + __func__, ret); + } + } + return 0; } -- cgit v1.2.3-55-g7522 From 1066d77f682e84efb56fbd4e5c8bb236532eccc7 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 4 Sep 2014 18:31:40 -0300 Subject: [media] dvb-usb-v2: add tuner_detach callback Add tuner_detach callback in order to allow custom detach. It is needed when tuner driver is implemented I2C client or some other kernel bus, but not proprietary dvb_attach / dvb_detach. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/dvb_usb.h | 1 + drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 8 ++++++++ 2 files changed, 9 insertions(+) (limited to 'drivers/media/usb/dvb-usb-v2/dvb_usb_core.c') diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h index 7e36ee02f957..14e111e13e54 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h @@ -257,6 +257,7 @@ struct dvb_usb_device_properties { int (*frontend_attach) (struct dvb_usb_adapter *); int (*frontend_detach)(struct dvb_usb_adapter *); int (*tuner_attach) (struct dvb_usb_adapter *); + int (*tuner_detach)(struct dvb_usb_adapter *); int (*frontend_ctrl) (struct dvb_frontend *, int); int (*streaming_ctrl) (struct dvb_frontend *, int); int (*init) (struct dvb_usb_device *); diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index 02c43b52c906..1950f37df835 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -676,6 +676,14 @@ static int dvb_usbv2_adapter_frontend_exit(struct dvb_usb_adapter *adap) } } + if (d->props->tuner_detach) { + ret = d->props->tuner_detach(adap); + if (ret < 0) { + dev_dbg(&d->udev->dev, "%s: tuner_detach() failed=%d\n", + __func__, ret); + } + } + if (d->props->frontend_detach) { ret = d->props->frontend_detach(adap); if (ret < 0) { -- cgit v1.2.3-55-g7522