diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index bc064803b6c7..082ae6ba492f 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -153,6 +153,14 @@ static void au0828_usb_disconnect(struct usb_interface *interface) dprintk(1, "%s()\n", __func__); + /* there is a small window after disconnect, before + dev->usbdev is NULL, for poll (e.g: IR) try to access + the device and fill the dmesg with error messages. + Set the status so poll routines can check and avoid + access after disconnect. + */ + dev->dev_state = DEV_DISCONNECTED; + au0828_rc_unregister(dev); /* Digital TV */ au0828_dvb_unregister(dev); diff --git a/drivers/media/usb/au0828/au0828-input.c b/drivers/media/usb/au0828/au0828-input.c index 11a8daec5939..b0f067971979 100644 --- a/drivers/media/usb/au0828/au0828-input.c +++ b/drivers/media/usb/au0828/au0828-input.c @@ -129,6 +129,10 @@ static int au0828_get_key_au8522(struct au0828_rc *ir) int prv_bit, bit, width; bool first = true; + /* do nothing if device is disconnected */ + if (ir->dev->dev_state == DEV_DISCONNECTED) + return 0; + /* Check IR int */ rc = au8522_rc_read(ir, 0xe1, -1, buf, 1); if (rc < 0 || !(buf[0] & (1 << 4))) { @@ -255,8 +259,11 @@ static void au0828_rc_stop(struct rc_dev *rc) cancel_delayed_work_sync(&ir->work); - /* Disable IR */ - au8522_rc_clear(ir, 0xe0, 1 << 4); + /* do nothing if device is disconnected */ + if (ir->dev->dev_state != DEV_DISCONNECTED) { + /* Disable IR */ + au8522_rc_clear(ir, 0xe0, 1 << 4); + } } static int au0828_probe_i2c_ir(struct au0828_dev *dev)