Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[linux-dvb] [PATCH] fix feed list handling



Hi list members,

this patch should fix the oopses occuring when multiple feeds share the
same pid. It maybe needs some additional locking stuff, but that's
another issue.

Can you (yes you, the reader) please test it on the several card types?
If there is no negative feedback during the next few hours, then I will
commit it to cvs.

Regards,
Andreas

P.S.: dvb-kernel, as always
? diff
? dvb-core.diff
Index: dvb_demux.c
===================================================================
RCS file: /cvs/linuxtv/dvb-kernel/linux/drivers/media/dvb/dvb-core/dvb_demux.c,v
retrieving revision 1.43
diff -u -r1.43 dvb_demux.c
--- dvb_demux.c	3 Dec 2003 19:29:32 -0000	1.43
+++ dvb_demux.c	19 Dec 2003 20:08:08 -0000
@@ -544,33 +544,38 @@
 	return &demux->feed[i];
 }
 
-
-static int dmx_pid_set (u16 pid, struct dvb_demux_feed *feed)
+static int dvb_demux_feed_find(struct dvb_demux_feed *feed)
 {
-	struct dvb_demux *demux = feed->demux;
-	struct list_head *pos, *n, *head=&demux->feed_list;
+	struct dvb_demux_feed *entry;
 
-	if (pid > DMX_MAX_PID)
-		return -EINVAL;
+	list_for_each_entry(entry, &feed->demux->feed_list, list_head)
+		if (entry == feed)
+			return 1;
 
-	if (pid == feed->pid)
-		return 0;
+	return 0;
+}
 
-	if (feed->pid <= DMX_MAX_PID) {
-		list_for_each_safe(pos, n, head) {
-			if (DMX_FEED_ENTRY(pos)->pid == feed->pid) {
-				list_del(pos);
-				break;
-			}
-		}
+static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
+{
+	if (dvb_demux_feed_find(feed)) {
+		printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
+				__FUNCTION__, feed->type, feed->state, feed->pid);
+		return;
 	}
 
-	list_add(&feed->list_head, head);
-	feed->pid = pid;
-
-	return 0;
+	list_add(&feed->list_head, &feed->demux->feed_list);
 }
 
+static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
+{
+	if (!(dvb_demux_feed_find(feed))) {
+		printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
+				__FUNCTION__, feed->type, feed->state, feed->pid);
+		return;
+	}
+
+	list_del(&feed->list_head);
+}
 
 static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type, 
 		     enum dmx_ts_pes pes_type, size_t callback_length, 
@@ -579,8 +584,10 @@
 {
 	struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed;
 	struct dvb_demux *demux = feed->demux;
-	int ret;
-	
+
+	if (pid > DMX_MAX_PID)
+		return -EINVAL;
+
 	if (down_interruptible (&demux->mutex))
 		return -ERESTARTSYS;
 
@@ -596,26 +603,13 @@
 			return -EINVAL;
 		}
 
-		if ((pes_type != DMX_TS_PES_PCR0) && 
-		    (pes_type != DMX_TS_PES_PCR1) && 
-		    (pes_type != DMX_TS_PES_PCR2) && 
-		    (pes_type != DMX_TS_PES_PCR3)) {
-			if ((ret = dmx_pid_set(pid, feed))<0) {
-				up(&demux->mutex);
-				return ret;
-			}
-		} else
-			feed->pid = pid;
-				
 		demux->pesfilter[pes_type] = feed;
-		demux->pids[pes_type] = feed->pid;
-	} else {
-		if ((ret = dmx_pid_set(pid, feed))<0) {
-			up(&demux->mutex);
-			return ret;
-		}
+		demux->pids[pes_type] = pid;
 	}
 
+	dvb_demux_feed_add(feed);
+
+	feed->pid = pid;
 	feed->buffer_size = circular_buffer_size;
 	feed->descramble = descramble;
 	feed->timeout = timeout;
@@ -759,7 +753,6 @@
 {
 	struct dvb_demux *demux = (struct dvb_demux *) dmx;
 	struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed;
-	struct list_head *pos, *n, *head=&demux->feed_list;
 
 	if (down_interruptible (&demux->mutex))
 		return -ERESTARTSYS;
@@ -779,15 +772,10 @@
 	feed->state = DMX_STATE_FREE;
 	feed->filter->state = DMX_STATE_FREE;
 
-	if (feed->pid <= DMX_MAX_PID) {
-		list_for_each_safe(pos, n, head)
-			if (DMX_FEED_ENTRY(pos)->pid == feed->pid) {
-				list_del(pos);
-				break;
-			}
-		feed->pid = 0xffff;
-	}
-	
+	dvb_demux_feed_del(feed);
+
+	feed->pid = 0xffff;
+
 	if (feed->ts_type & TS_DECODER)
 		demux->pesfilter[feed->pes_type] = NULL;
 
@@ -838,7 +826,6 @@
 {
 	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	struct list_head *pos, *n, *head=&dvbdmx->feed_list;
 
 	if (pid > 0x1fff)
 		return -EINVAL;
@@ -846,16 +833,7 @@
 	if (down_interruptible (&dvbdmx->mutex))
 		return -ERESTARTSYS;
 	
-	if (dvbdmxfeed->pid <= DMX_MAX_PID) {
-		list_for_each_safe(pos, n, head) {
-			if (DMX_FEED_ENTRY(pos)->pid == dvbdmxfeed->pid) {
-				list_del(pos);
-				break;
-			}
-		}
-	}
-
-	list_add(&dvbdmxfeed->list_head, head);
+	dvb_demux_feed_add(dvbdmxfeed);
 
 	dvbdmxfeed->pid = pid;
 	dvbdmxfeed->buffer_size = circular_buffer_size;
@@ -1058,7 +1036,6 @@
 {
 	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
 	struct dvb_demux *dvbdmx = (struct dvb_demux *) demux;
-	struct list_head *pos, *n, *head = &dvbdmx->feed_list;
 
 	if (down_interruptible (&dvbdmx->mutex))
 		return -ERESTARTSYS;
@@ -1075,15 +1052,9 @@
 #endif
 	dvbdmxfeed->state=DMX_STATE_FREE;
 
-	if (dvbdmxfeed->pid <= DMX_MAX_PID) {
-		list_for_each_safe(pos, n, head) {
-			if (DMX_FEED_ENTRY(pos)->pid == dvbdmxfeed->pid) {
-				list_del(pos);
-				break;
-			}
-		}
-		dvbdmxfeed->pid = 0xffff;
-	}
+	dvb_demux_feed_del(dvbdmxfeed);
+
+	dvbdmxfeed->pid = 0xffff;
 
 	up(&dvbdmx->mutex);
 	return 0;

Attachment: signature.asc
Description: This is a digitally signed message part


Home | Main Index | Thread Index