[linux-dvb] [PATCH] dvb_net - Fix oops when stopping multiple dvb interfaces

Johannes Stezenbach js at linuxtv.org
Sun Nov 13 20:23:30 CET 2005


Hi Ralph,

On Fri, Nov 04, 2005 Holger Kiehl wrote:
> This patch is from Ralph Metzler <rjkm at metzlerbros.de> (see discussion under
> the thread: [Patch] Error in dvb_net.c on 64bit platforms) and has not made
> it into CVS nor into linux-kernel. It fixes a serious issue when removing
> multiple dvb network interfaces at once and the card does have hardware
> PID filters. These systems cannot be rebooted because they always hang
> when kernel or some scripts want to remove the interfaces. With this patch
> applied systems reboot without problems and there are no more oopses.
> 
> Please, please apply this patch.

would it be possible for you to provide your Signed-off-by: 
on this patch?

TIA,
Johannes


> --- dvb-kernel/linux/drivers/media/dvb/dvb-core/dvb_net.c.orig	2005-08-12 
> 17:37:59.000000000 +0200
> +++ dvb-kernel/linux/drivers/media/dvb/dvb-core/dvb_net.c	2005-11-04 
> 10:55:21.000000000 +0100
> @@ -62,6 +62,7 @@
>  #include <linux/uio.h>
>  #include <asm/uaccess.h>
>  #include <linux/crc32.h>
> +#include <linux/version.h>
> 
>  #include "dvb_demux.h"
>  #include "dvb_net.h"
> @@ -151,6 +152,9 @@
>  	unsigned char ule_bridged;		/* Whether the ULE_BRIDGED 
>  	extension header was found. */
>  	int ule_sndu_remain;			/* Nr. of bytes still 
>  	required for current ULE SNDU. */
>  	unsigned long ts_count;			/* Current ts cell counter. 
>  	*/
> +
> +	struct semaphore mutex;
> +	spinlock_t lock;
>  };
> 
> 
> @@ -170,7 +174,11 @@
> 
>  	skb->mac.raw=skb->data;
>  	skb_pull(skb,dev->hard_header_len);
> +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,8)
> +	eth = skb->mac.ethernet;
> +#else
>  	eth = eth_hdr(skb);
> +#endif
> 
>  	if (*eth->h_dest & 1) {
>  		if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
> @@ -881,12 +889,13 @@
> 
>  static int dvb_net_feed_start(struct net_device *dev)
>  {
> -	int ret, i;
> +	int ret=0, i;
>  	struct dvb_net_priv *priv = dev->priv;
>          struct dmx_demux *demux = priv->demux;
>          unsigned char *mac = (unsigned char *) dev->dev_addr;
> 
>  	dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode);
> +	down(&priv->mutex);
>  	if (priv->tsfeed || priv->secfeed || priv->secfilter || 
>  	priv->multi_secfilter[0])
>  		printk("%s: BUG %d\n", __FUNCTION__, __LINE__);
> 
> @@ -900,7 +909,7 @@
>  					 dvb_net_sec_callback);
>  		if (ret<0) {
>  			printk("%s: could not allocate section feed\n", 
>  			dev->name);
> -			return ret;
> +			goto error;
>  		}
> 
>  		ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 1);
> @@ -909,7 +918,7 @@
>  			printk("%s: could not set section feed\n", 
>  			dev->name);
>  			priv->demux->release_section_feed(priv->demux, 
>  			priv->secfeed);
>  			priv->secfeed=NULL;
> -			return ret;
> +			goto error;
>  		}
> 
>  		if (priv->rx_mode != RX_MODE_PROMISC) {
> @@ -948,7 +957,7 @@
>  		ret = demux->allocate_ts_feed(demux, &priv->tsfeed, 
>  		dvb_net_ts_callback);
>  		if (ret < 0) {
>  			printk("%s: could not allocate ts feed\n", 
>  			dev->name);
> -			return ret;
> +			goto error;
>  		}
> 
>  		/* Set netdevice pointer for ts decaps callback. */
> @@ -962,23 +971,26 @@
>  			printk("%s: could not set ts feed\n", dev->name);
>  			priv->demux->release_ts_feed(priv->demux, 
>  			priv->tsfeed);
>  			priv->tsfeed = NULL;
> -			return ret;
> +			goto error;
>  		}
> 
>  		dprintk("%s: start filtering\n", __FUNCTION__);
>  		priv->tsfeed->start_filtering(priv->tsfeed);
>  	} else
> -		return -EINVAL;
> +		ret=-EINVAL;
> 
> -	return 0;
> +error:
> +	up(&priv->mutex);
> +	return ret;
>  }
> 
>  static int dvb_net_feed_stop(struct net_device *dev)
>  {
>  	struct dvb_net_priv *priv = dev->priv;
> -	int i;
> +	int i, ret=0;
> 
>  	dprintk("%s\n", __FUNCTION__);
> +	down(&priv->mutex);
>  	if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
>  		if (priv->secfeed) {
>  			if (priv->secfeed->is_filtering) {
> @@ -1019,8 +1031,9 @@
>  		else
>  			printk("%s: no ts feed to stop\n", dev->name);
>  	} else
> -		return -EINVAL;
> -	return 0;
> +		ret=-EINVAL;
> +	up(&priv->mutex);
> +	return ret;
>  }
> 
> 
> @@ -1047,6 +1060,7 @@
> 
>  	priv->rx_mode = RX_MODE_UNI;
> 
> +	spin_lock_bh(&dev->xmit_lock);
>  	if (dev->flags & IFF_PROMISC) {
>  		dprintk("%s: promiscuous mode\n", dev->name);
>  		priv->rx_mode = RX_MODE_PROMISC;
> @@ -1069,7 +1083,7 @@
>  			dvb_set_mc_filter(dev, mc);
>  		}
>  	}
> -
> +	spin_unlock_bh(&dev->xmit_lock);
>  	dvb_net_feed_start(dev);
>  }
> 
> @@ -1183,7 +1197,6 @@
>  		/* compatibility fix to keep dvb0_0 format */
>  		snprintf(net->name, IFNAMSIZ, "dvb%d_%d",
>  			 dvbnet->dvbdev->adapter->num, if_num);
> -
>  	net->addr_len = 6;
>  	memcpy(net->dev_addr, dvbnet->dvbdev->adapter->proposed_mac, 6);
> 
> @@ -1200,6 +1213,8 @@
> 
>  	INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list, net);
>  	INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed, net);
> +	sema_init(&priv->mutex, 1);
> +	spin_lock_init(&priv->lock);
> 
>  	net->base_addr = pid;
> 
> 
> 
> _______________________________________________
> linux-dvb mailing list
> linux-dvb at linuxtv.org
> http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
> 



More information about the linux-dvb mailing list