Message ID | 1399435082-5416-1-git-send-email-cb.xiong@samsung.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, May 6, 2014 at 11:58 PM, <cb.xiong@samsung.com> wrote: > From: Changbing Xiong <cb.xiong@samsung.com> > > The driver crashed when the tuner was disconnected while restart stream > operations are still being performed. Fixed by adding a flag in struct > au0828_dvb to indicate whether restart stream operations can be performed. > > If the stream gets misaligned, the work of restart stream operations are > usually scheduled for many times in a row. If tuner is disconnected at > this time and some of restart stream operations are still not flushed, > then the driver crashed due to accessing the resource which used in > restart stream operations has been released. > > Signed-off-by: Changbing Xiong <cb.xiong@samsung.com> I haven't yet reviewed the logic in detail, but at a minimum this should really be two patches - one to address the disconnect bug and a second to deal with failure to cancel to the worker thread. Also, you need to pick a name for the variable that is more explanatory than "flag". Please resubmit this as two separate patches with "flag" renamed, and I will then look at the actual implementation to see if it causes any problems. Thanks, Devin
Thanks for your comments, and I have resubmit this according Mr. Chehab's comments, please check. Thanks. Changbing Xiong. -- 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
diff --git a/drivers/media/usb/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c old mode 100644 new mode 100755 index 9a6f156..90cdde5 --- a/drivers/media/usb/au0828/au0828-dvb.c +++ b/drivers/media/usb/au0828/au0828-dvb.c @@ -280,6 +280,11 @@ static void au0828_restart_dvb_streaming(struct work_struct *work) mutex_lock(&dvb->lock); + if (dvb->flag == true) { + mutex_unlock(&dvb->lock); + return; + } + /* Stop transport */ stop_urb_transfer(dev); au0828_write(dev, 0x608, 0x00); @@ -304,6 +309,8 @@ static int dvb_register(struct au0828_dev *dev) dprintk(1, "%s()\n", __func__); + dvb->flag = false; + INIT_WORK(&dev->restart_streaming, au0828_restart_dvb_streaming); /* register adapter */ @@ -403,6 +410,10 @@ void au0828_dvb_unregister(struct au0828_dev *dev) if (dvb->frontend == NULL) return; + mutex_lock(&dvb->lock); + dvb->flag = true; + mutex_unlock(&dvb->lock); + dvb_net_release(&dvb->net); dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); @@ -411,6 +422,8 @@ void au0828_dvb_unregister(struct au0828_dev *dev) dvb_unregister_frontend(dvb->frontend); dvb_frontend_detach(dvb->frontend); dvb_unregister_adapter(&dvb->adapter); + + cancel_work_sync(&dev->restart_streaming); } /* All the DVB attach calls go here, this function get's modified diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h old mode 100644 new mode 100755 index ef1f57f..00255d5 --- a/drivers/media/usb/au0828/au0828.h +++ b/drivers/media/usb/au0828/au0828.h @@ -102,6 +102,7 @@ struct au0828_dvb { struct dmx_frontend fe_mem; struct dvb_net net; int feeding; + bool flag; }; enum au0828_stream_state {