diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index bc064803b6c7f6c2c6fb05b93c8fba7efb5cda22..082ae6ba492fa1eeb35949a9655db14456015047 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 11a8daec5939f52c0be987d132eba270412dc765..b0f0679719798c4b8212b9dabee3f992b018c17a 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)