[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