[media] cx18: Only allocate a struct cx18_dvb for the DVB TS stream
Andy Walls [Sat, 11 Dec 2010 23:38:20 +0000 (20:38 -0300)]
The cx18_stream struct contained a struct cx18_dvb for
every stream object, most of which were for analog capture.
Now we only allocate the cx18_dvb object for the DTV TS stream.

Signed-off-by: Andy Walls <awalls@md.metrocast.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

drivers/media/video/cx18/cx18-driver.h
drivers/media/video/cx18/cx18-dvb.c
drivers/media/video/cx18/cx18-mailbox.c
drivers/media/video/cx18/cx18-streams.c
drivers/media/video/cx18/cx18-streams.h

index cf4f20e..f6f3e50 100644 (file)
@@ -325,7 +325,10 @@ struct cx18_queue {
        spinlock_t lock;
 };
 
+struct cx18_stream; /* forward reference */
+
 struct cx18_dvb {
+       struct cx18_stream *stream;
        struct dmx_frontend hw_frontend;
        struct dmx_frontend mem_frontend;
        struct dmxdev dmxdev;
@@ -365,9 +368,10 @@ struct cx18_in_work_order {
 #define CX18_INVALID_TASK_HANDLE 0xffffffff
 
 struct cx18_stream {
-       /* These first four fields are always set, even if the stream
+       /* These first five fields are always set, even if the stream
           is not actually created. */
        struct video_device *video_dev; /* NULL when stream not created */
+       struct cx18_dvb *dvb;           /* DVB / Digital Transport */
        struct cx18 *cx;                /* for ease of use */
        const char *name;               /* name of the stream */
        int type;                       /* stream type */
@@ -397,9 +401,6 @@ struct cx18_stream {
        struct cx18_queue q_idle;       /* idle - not in rotation */
 
        struct work_struct out_work_order;
-
-       /* DVB / Digital Transport */
-       struct cx18_dvb dvb;
 };
 
 struct cx18_open_id {
index c7f0bad..f0381d6 100644 (file)
@@ -137,7 +137,7 @@ static int yuan_mpc718_mt352_init(struct dvb_frontend *fe)
 {
        struct cx18_dvb *dvb = container_of(fe->dvb,
                                            struct cx18_dvb, dvb_adapter);
-       struct cx18_stream *stream = container_of(dvb, struct cx18_stream, dvb);
+       struct cx18_stream *stream = dvb->stream;
        const struct firmware *fw = NULL;
        int ret;
        int i;
@@ -266,22 +266,22 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
        if (!demux->dmx.frontend)
                return -EINVAL;
 
-       mutex_lock(&stream->dvb.feedlock);
-       if (stream->dvb.feeding++ == 0) {
+       mutex_lock(&stream->dvb->feedlock);
+       if (stream->dvb->feeding++ == 0) {
                CX18_DEBUG_INFO("Starting Transport DMA\n");
                mutex_lock(&cx->serialize_lock);
                set_bit(CX18_F_S_STREAMING, &stream->s_flags);
                ret = cx18_start_v4l2_encode_stream(stream);
                if (ret < 0) {
                        CX18_DEBUG_INFO("Failed to start Transport DMA\n");
-                       stream->dvb.feeding--;
-                       if (stream->dvb.feeding == 0)
+                       stream->dvb->feeding--;
+                       if (stream->dvb->feeding == 0)
                                clear_bit(CX18_F_S_STREAMING, &stream->s_flags);
                }
                mutex_unlock(&cx->serialize_lock);
        } else
                ret = 0;
-       mutex_unlock(&stream->dvb.feedlock);
+       mutex_unlock(&stream->dvb->feedlock);
 
        return ret;
 }
@@ -299,15 +299,15 @@ static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed)
                CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n",
                                feed->pid, feed->index);
 
-               mutex_lock(&stream->dvb.feedlock);
-               if (--stream->dvb.feeding == 0) {
+               mutex_lock(&stream->dvb->feedlock);
+               if (--stream->dvb->feeding == 0) {
                        CX18_DEBUG_INFO("Stopping Transport DMA\n");
                        mutex_lock(&cx->serialize_lock);
                        ret = cx18_stop_v4l2_encode_stream(stream, 0);
                        mutex_unlock(&cx->serialize_lock);
                } else
                        ret = 0;
-               mutex_unlock(&stream->dvb.feedlock);
+               mutex_unlock(&stream->dvb->feedlock);
        }
 
        return ret;
@@ -316,7 +316,7 @@ static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed)
 int cx18_dvb_register(struct cx18_stream *stream)
 {
        struct cx18 *cx = stream->cx;
-       struct cx18_dvb *dvb = &stream->dvb;
+       struct cx18_dvb *dvb = stream->dvb;
        struct dvb_adapter *dvb_adapter;
        struct dvb_demux *dvbdemux;
        struct dmx_demux *dmx;
@@ -325,6 +325,9 @@ int cx18_dvb_register(struct cx18_stream *stream)
        if (!dvb)
                return -EINVAL;
 
+       dvb->enabled = 0;
+       dvb->stream = stream;
+
        ret = dvb_register_adapter(&dvb->dvb_adapter,
                        CX18_DRIVER_NAME,
                        THIS_MODULE, &cx->pci_dev->dev, adapter_nr);
@@ -378,7 +381,7 @@ int cx18_dvb_register(struct cx18_stream *stream)
 
        CX18_INFO("DVB Frontend registered\n");
        CX18_INFO("Registered DVB adapter%d for %s (%d x %d.%02d kB)\n",
-                 stream->dvb.dvb_adapter.num, stream->name,
+                 stream->dvb->dvb_adapter.num, stream->name,
                  stream->buffers, stream->buf_size/1024,
                  (stream->buf_size * 100 / 1024) % 100);
 
@@ -405,13 +408,16 @@ err_out:
 void cx18_dvb_unregister(struct cx18_stream *stream)
 {
        struct cx18 *cx = stream->cx;
-       struct cx18_dvb *dvb = &stream->dvb;
+       struct cx18_dvb *dvb = stream->dvb;
        struct dvb_adapter *dvb_adapter;
        struct dvb_demux *dvbdemux;
        struct dmx_demux *dmx;
 
        CX18_INFO("unregister DVB\n");
 
+       if (dvb == NULL || !dvb->enabled)
+               return;
+
        dvb_adapter = &dvb->dvb_adapter;
        dvbdemux = &dvb->demux;
        dmx = &dvbdemux->dmx;
@@ -432,7 +438,7 @@ void cx18_dvb_unregister(struct cx18_stream *stream)
  */
 static int dvb_register(struct cx18_stream *stream)
 {
-       struct cx18_dvb *dvb = &stream->dvb;
+       struct cx18_dvb *dvb = stream->dvb;
        struct cx18 *cx = stream->cx;
        int ret = 0;
 
index 956aa19..c545f3b 100644 (file)
@@ -136,7 +136,7 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl)
 {
        struct cx18_buffer *buf;
 
-       if (!s->dvb.enabled || mdl->bytesused == 0)
+       if (s->dvb == NULL || !s->dvb->enabled || mdl->bytesused == 0)
                return;
 
        /* We ignore mdl and buf readpos accounting here - it doesn't matter */
@@ -146,7 +146,7 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl)
                buf = list_first_entry(&mdl->buf_list, struct cx18_buffer,
                                       list);
                if (buf->bytesused)
-                       dvb_dmx_swfilter(&s->dvb.demux,
+                       dvb_dmx_swfilter(&s->dvb->demux,
                                         buf->buf, buf->bytesused);
                return;
        }
@@ -154,7 +154,7 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl)
        list_for_each_entry(buf, &mdl->buf_list, list) {
                if (buf->bytesused == 0)
                        break;
-               dvb_dmx_swfilter(&s->dvb.demux, buf->buf, buf->bytesused);
+               dvb_dmx_swfilter(&s->dvb->demux, buf->buf, buf->bytesused);
        }
 }
 
index ab461e2..94f5d79 100644 (file)
@@ -107,6 +107,7 @@ static void cx18_stream_init(struct cx18 *cx, int type)
        s->video_dev = video_dev;
 
        /* initialize cx18_stream fields */
+       s->dvb = NULL;
        s->cx = cx;
        s->type = type;
        s->name = cx18_stream_info[type].name;
@@ -140,10 +141,15 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
        int num_offset = cx18_stream_info[type].num_offset;
        int num = cx->instance + cx18_first_minor + num_offset;
 
-       /* These four fields are always initialized. If video_dev == NULL, then
-          this stream is not in use. In that case no other fields but these
-          four can be used. */
+       /*
+        * These five fields are always initialized.
+        * For analog capture related streams, if video_dev == NULL then the
+        * stream is not in use.
+        * For the TS stream, if dvb == NULL then the stream is not in use.
+        * In those cases no other fields but these four can be used.
+        */
        s->video_dev = NULL;
+       s->dvb = NULL;
        s->cx = cx;
        s->type = type;
        s->name = cx18_stream_info[type].name;
@@ -167,6 +173,21 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
 
        cx18_stream_init(cx, type);
 
+       /* Allocate the cx18_dvb struct only for the TS on cards with DTV */
+       if (type == CX18_ENC_STREAM_TYPE_TS) {
+               if (cx->card->hw_all & CX18_HW_DVB) {
+                       s->dvb = kzalloc(sizeof(struct cx18_dvb), GFP_KERNEL);
+                       if (s->dvb == NULL) {
+                               CX18_ERR("Couldn't allocate cx18_dvb structure"
+                                        " for %s\n", s->name);
+                               return -ENOMEM;
+                       }
+               } else {
+                       /* Don't need buffers for the TS, if there is no DVB */
+                       s->buffers = 0;
+               }
+       }
+
        if (num_offset == -1)
                return 0;
 
@@ -222,13 +243,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
        const char *name;
        int num, ret;
 
-       /* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something?
-        * We need a VFL_TYPE_TS defined.
-        */
-       if (strcmp("TS", s->name) == 0) {
-               /* just return if no DVB is supported */
-               if ((cx->card->hw_all & CX18_HW_DVB) == 0)
-                       return 0;
+       if (type == CX18_ENC_STREAM_TYPE_TS && s->dvb != NULL) {
                ret = cx18_dvb_register(s);
                if (ret < 0) {
                        CX18_ERR("DVB failed to register\n");
@@ -320,11 +335,13 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister)
        /* Teardown all streams */
        for (type = 0; type < CX18_MAX_STREAMS; type++) {
 
-               /* No struct video_device, but can have buffers allocated */
+               /* The TS has a cx18_dvb structure, not a video_device */
                if (type == CX18_ENC_STREAM_TYPE_TS) {
-                       if (cx->streams[type].dvb.enabled) {
-                               cx18_dvb_unregister(&cx->streams[type]);
-                               cx->streams[type].dvb.enabled = false;
+                       if (cx->streams[type].dvb != NULL) {
+                               if (unregister)
+                                       cx18_dvb_unregister(&cx->streams[type]);
+                               kfree(cx->streams[type].dvb);
+                               cx->streams[type].dvb = NULL;
                                cx18_stream_free(&cx->streams[type]);
                        }
                        continue;
index 77412be..51765eb 100644 (file)
@@ -33,7 +33,8 @@ void cx18_stream_rotate_idx_mdls(struct cx18 *cx);
 
 static inline bool cx18_stream_enabled(struct cx18_stream *s)
 {
-       return s->video_dev || s->dvb.enabled ||
+       return s->video_dev ||
+              (s->dvb && s->dvb->enabled) ||
               (s->type == CX18_ENC_STREAM_TYPE_IDX &&
                s->cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] != 0);
 }