aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorRalph Metzler <rjkm@metzlerbros.de>2005-12-01 03:51:54 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-12-01 18:48:59 -0500
commit1130ca45c719fe788fa544a54a82ea53ef5ea87a (patch)
tree423a0eb692c0e14a8b1c6462a8dfdfc402e93753 /drivers/media
parent9b9225f0f002c39f340da2ed1e7efec6885ca312 (diff)
[PATCH] DVB: Fix locking to prevent Oops on SMP systems
Fix locking to prevent Oops on SMP systems when starting/stopping dvb network interfaces. Signed-off-by: Ralph Metzler <rjkm@metzlerbros.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c31
1 files changed, 20 insertions, 11 deletions
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 87935490bfb2..df536bd2e103 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -151,6 +151,8 @@ struct dvb_net_priv {
151 unsigned char ule_bridged; /* Whether the ULE_BRIDGED extension header was found. */ 151 unsigned char ule_bridged; /* Whether the ULE_BRIDGED extension header was found. */
152 int ule_sndu_remain; /* Nr. of bytes still required for current ULE SNDU. */ 152 int ule_sndu_remain; /* Nr. of bytes still required for current ULE SNDU. */
153 unsigned long ts_count; /* Current ts cell counter. */ 153 unsigned long ts_count; /* Current ts cell counter. */
154
155 struct semaphore mutex;
154}; 156};
155 157
156 158
@@ -881,12 +883,13 @@ static int dvb_net_filter_sec_set(struct net_device *dev,
881 883
882static int dvb_net_feed_start(struct net_device *dev) 884static int dvb_net_feed_start(struct net_device *dev)
883{ 885{
884 int ret, i; 886 int ret = 0, i;
885 struct dvb_net_priv *priv = dev->priv; 887 struct dvb_net_priv *priv = dev->priv;
886 struct dmx_demux *demux = priv->demux; 888 struct dmx_demux *demux = priv->demux;
887 unsigned char *mac = (unsigned char *) dev->dev_addr; 889 unsigned char *mac = (unsigned char *) dev->dev_addr;
888 890
889 dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode); 891 dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode);
892 down(&priv->mutex);
890 if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0]) 893 if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0])
891 printk("%s: BUG %d\n", __FUNCTION__, __LINE__); 894 printk("%s: BUG %d\n", __FUNCTION__, __LINE__);
892 895
@@ -900,7 +903,7 @@ static int dvb_net_feed_start(struct net_device *dev)
900 dvb_net_sec_callback); 903 dvb_net_sec_callback);
901 if (ret<0) { 904 if (ret<0) {
902 printk("%s: could not allocate section feed\n", dev->name); 905 printk("%s: could not allocate section feed\n", dev->name);
903 return ret; 906 goto error;
904 } 907 }
905 908
906 ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 1); 909 ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 1);
@@ -909,7 +912,7 @@ static int dvb_net_feed_start(struct net_device *dev)
909 printk("%s: could not set section feed\n", dev->name); 912 printk("%s: could not set section feed\n", dev->name);
910 priv->demux->release_section_feed(priv->demux, priv->secfeed); 913 priv->demux->release_section_feed(priv->demux, priv->secfeed);
911 priv->secfeed=NULL; 914 priv->secfeed=NULL;
912 return ret; 915 goto error;
913 } 916 }
914 917
915 if (priv->rx_mode != RX_MODE_PROMISC) { 918 if (priv->rx_mode != RX_MODE_PROMISC) {
@@ -948,7 +951,7 @@ static int dvb_net_feed_start(struct net_device *dev)
948 ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback); 951 ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback);
949 if (ret < 0) { 952 if (ret < 0) {
950 printk("%s: could not allocate ts feed\n", dev->name); 953 printk("%s: could not allocate ts feed\n", dev->name);
951 return ret; 954 goto error;
952 } 955 }
953 956
954 /* Set netdevice pointer for ts decaps callback. */ 957 /* Set netdevice pointer for ts decaps callback. */
@@ -962,23 +965,26 @@ static int dvb_net_feed_start(struct net_device *dev)
962 printk("%s: could not set ts feed\n", dev->name); 965 printk("%s: could not set ts feed\n", dev->name);
963 priv->demux->release_ts_feed(priv->demux, priv->tsfeed); 966 priv->demux->release_ts_feed(priv->demux, priv->tsfeed);
964 priv->tsfeed = NULL; 967 priv->tsfeed = NULL;
965 return ret; 968 goto error;
966 } 969 }
967 970
968 dprintk("%s: start filtering\n", __FUNCTION__); 971 dprintk("%s: start filtering\n", __FUNCTION__);
969 priv->tsfeed->start_filtering(priv->tsfeed); 972 priv->tsfeed->start_filtering(priv->tsfeed);
970 } else 973 } else
971 return -EINVAL; 974 ret = -EINVAL;
972 975
973 return 0; 976error:
977 up(&priv->mutex);
978 return ret;
974} 979}
975 980
976static int dvb_net_feed_stop(struct net_device *dev) 981static int dvb_net_feed_stop(struct net_device *dev)
977{ 982{
978 struct dvb_net_priv *priv = dev->priv; 983 struct dvb_net_priv *priv = dev->priv;
979 int i; 984 int i, ret = 0;
980 985
981 dprintk("%s\n", __FUNCTION__); 986 dprintk("%s\n", __FUNCTION__);
987 down(&priv->mutex);
982 if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) { 988 if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
983 if (priv->secfeed) { 989 if (priv->secfeed) {
984 if (priv->secfeed->is_filtering) { 990 if (priv->secfeed->is_filtering) {
@@ -1019,8 +1025,9 @@ static int dvb_net_feed_stop(struct net_device *dev)
1019 else 1025 else
1020 printk("%s: no ts feed to stop\n", dev->name); 1026 printk("%s: no ts feed to stop\n", dev->name);
1021 } else 1027 } else
1022 return -EINVAL; 1028 ret = -EINVAL;
1023 return 0; 1029 up(&priv->mutex);
1030 return ret;
1024} 1031}
1025 1032
1026 1033
@@ -1044,8 +1051,8 @@ static void wq_set_multicast_list (void *data)
1044 struct dvb_net_priv *priv = dev->priv; 1051 struct dvb_net_priv *priv = dev->priv;
1045 1052
1046 dvb_net_feed_stop(dev); 1053 dvb_net_feed_stop(dev);
1047
1048 priv->rx_mode = RX_MODE_UNI; 1054 priv->rx_mode = RX_MODE_UNI;
1055 spin_lock_bh(&dev->xmit_lock);
1049 1056
1050 if (dev->flags & IFF_PROMISC) { 1057 if (dev->flags & IFF_PROMISC) {
1051 dprintk("%s: promiscuous mode\n", dev->name); 1058 dprintk("%s: promiscuous mode\n", dev->name);
@@ -1070,6 +1077,7 @@ static void wq_set_multicast_list (void *data)
1070 } 1077 }
1071 } 1078 }
1072 1079
1080 spin_unlock_bh(&dev->xmit_lock);
1073 dvb_net_feed_start(dev); 1081 dvb_net_feed_start(dev);
1074} 1082}
1075 1083
@@ -1200,6 +1208,7 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype)
1200 1208
1201 INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list, net); 1209 INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list, net);
1202 INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed, net); 1210 INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed, net);
1211 init_MUTEX(&priv->mutex);
1203 1212
1204 net->base_addr = pid; 1213 net->base_addr = pid;
1205 1214