Hi Ralph, On Fri, Nov 04, 2005 Holger Kiehl wrote: > 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. 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@xxxxxxxxxxx > http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb >