[media] Mantis: append tasklet maintenance for DVB stream delivery
authorMarko Ristola <marko.ristola@kolumbus.fi>
Sun, 14 Nov 2010 17:09:04 +0000 (14:09 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 29 Dec 2010 10:16:48 +0000 (08:16 -0200)
After dvb-core has called mantis-fe->stop_feed(dvbdmxfeed)
the last time (count to zero), no data should ever be copied
with dvb_dmx_swfilter() by a tasklet: the target structure
might be in an unusable state. Caller of mantis_fe->stop_feed()
assumes that feeding is stopped after stop_feed() has been
called, ie. dvb_dmx_swfilter() isn't running, and won't be called.

There is a risk that dvb_dmx_swfilter() references freed resources
(memory or spinlocks or ???) causing instabilities. Thus
tasklet_disable(&mantis->tasklet) must be called inside of
mantis-fe->stop_feed(dvbdmxfeed) when necessary.

Signed-off-by: Marko Ristola <marko.ristola@kolumbus.fi>
Signed-off-by: Manu Abraham <manu@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/dvb/mantis/mantis_dvb.c

index 99d82eec3b03f01b88d26d432f09708fa45b11d1..a9864f7134e1c9d523deeec5d2030c95326fa6f6 100644 (file)
@@ -117,6 +117,7 @@ static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
        if (mantis->feeds == 1)  {
                dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma");
                mantis_dma_start(mantis);
+               tasklet_enable(&mantis->tasklet);
        }
 
        return mantis->feeds;
@@ -136,6 +137,7 @@ static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
        mantis->feeds--;
        if (mantis->feeds == 0) {
                dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma");
+               tasklet_disable(&mantis->tasklet);
                mantis_dma_stop(mantis);
        }
 
@@ -216,6 +218,7 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis)
 
        dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);
        tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis);
+       tasklet_disable(&mantis->tasklet);
        if (mantis->hwconfig) {
                result = config->frontend_init(mantis, mantis->fe);
                if (result < 0) {