[6/6] EM28xx - don't sleep on disconnect
Commit Message
The DVB framework will try to power-down an adapter that no-one is using any
more, but this assumes that the adapter is still connected to the machine.
That's not always true for a USB adapter, so disable the sleep operations when
the adapter has been physically unplugged.
This prevents I2C write failures with error -19 from appearing occasionally in
the dmesg log.
Signed-off-by: Chris Rankin <rankincj@yahoo.com>
Comments
Em 20-08-2011 04:37, Chris Rankin escreveu:
> +
> + if (dev->state & DEV_DISCONNECTED) {
> + /* We cannot tell the device to sleep
> + * once it has been unplugged. */
> + prevent_sleep(&dvb->fe[0]->ops);
> + prevent_sleep(&dvb->fe[1]->ops);
This will cause an OOPS if dvb->fe[n] == NULL.
> + }
> +
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
--- On Sat, 20/8/11, Mauro Carvalho Chehab <mchehab@redhat.com> wrot
>
> This will cause an OOPS if dvb->fe[n] == NULL.
>
OK, that's trivially fixable. I'll send you an updated patch. Is it safe to assume that dvb->fe[0] at least will always be non-NULL?
Cheers,
Chris
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Em 20-08-2011 06:46, Chris Rankin escreveu:
> --- On Sat, 20/8/11, Mauro Carvalho Chehab <mchehab@redhat.com> wrot
>>
>> This will cause an OOPS if dvb->fe[n] == NULL.
>>
>
> OK, that's trivially fixable. I'll send you an updated patch. Is it safe to assume that dvb->fe[0] at least will always be non-NULL?
No, it isn't. The dvb initialization may fail or the device can be analog only,
but somebody might manually load em28xx-dvb (or two devices were plugged).
Regards,
Mauro
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
@@ -1230,7 +1230,7 @@
return 0;
}
-static struct dvb_tuner_ops tda18271_tuner_ops = {
+static const struct dvb_tuner_ops tda18271_tuner_ops = {
.info = {
.name = "NXP TDA18271HD",
.frequency_min = 45000000,
@@ -778,7 +778,7 @@
}
EXPORT_SYMBOL(cxd2820r_get_tuner_i2c_adapter);
-static struct dvb_frontend_ops cxd2820r_ops[2];
+static const struct dvb_frontend_ops cxd2820r_ops[2];
struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
struct i2c_adapter *i2c, struct dvb_frontend *fe)
@@ -844,7 +844,7 @@
}
EXPORT_SYMBOL(cxd2820r_attach);
-static struct dvb_frontend_ops cxd2820r_ops[2] = {
+static const struct dvb_frontend_ops cxd2820r_ops[2] = {
{
/* DVB-T/T2 */
.info = {
@@ -720,6 +720,12 @@
goto ret;
}
+static inline void prevent_sleep(struct dvb_frontend_ops *ops) {
+ ops->set_voltage = NULL;
+ ops->sleep = NULL;
+ ops->tuner_ops.sleep = NULL;
+}
+
static int dvb_fini(struct em28xx *dev)
{
if (!dev->board.has_dvb) {
@@ -728,8 +734,17 @@
}
if (dev->dvb) {
- unregister_dvb(dev->dvb);
- kfree(dev->dvb);
+ struct em28xx_dvb *dvb = dev->dvb;
+
+ if (dev->state & DEV_DISCONNECTED) {
+ /* We cannot tell the device to sleep
+ * once it has been unplugged. */
+ prevent_sleep(&dvb->fe[0]->ops);
+ prevent_sleep(&dvb->fe[1]->ops);
+ }
+
+ unregister_dvb(dvb);
+ kfree(dvb);
dev->dvb = NULL;
}