Hello This patch is from Ralph Metzler <rjkm@xxxxxxxxxxxxxx> (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. Thanks, Holger -- --- 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;