]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/media/dvb-core/dvb_net.c
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211
[karo-tx-linux.git] / drivers / media / dvb-core / dvb_net.c
index c2117688aa23d8aad589d28a1e7a4cc1e0333024..44225b186f6df4a42945a8f9998361558d470451 100644 (file)
@@ -1345,26 +1345,35 @@ static int dvb_net_do_ioctl(struct file *file,
 {
        struct dvb_device *dvbdev = file->private_data;
        struct dvb_net *dvbnet = dvbdev->priv;
+       int ret = 0;
 
        if (((file->f_flags&O_ACCMODE)==O_RDONLY))
                return -EPERM;
 
+       if (mutex_lock_interruptible(&dvbnet->ioctl_mutex))
+               return -ERESTARTSYS;
+
        switch (cmd) {
        case NET_ADD_IF:
        {
                struct dvb_net_if *dvbnetif = parg;
                int result;
 
-               if (!capable(CAP_SYS_ADMIN))
-                       return -EPERM;
+               if (!capable(CAP_SYS_ADMIN)) {
+                       ret = -EPERM;
+                       goto ioctl_error;
+               }
 
-               if (!try_module_get(dvbdev->adapter->module))
-                       return -EPERM;
+               if (!try_module_get(dvbdev->adapter->module)) {
+                       ret = -EPERM;
+                       goto ioctl_error;
+               }
 
                result=dvb_net_add_if(dvbnet, dvbnetif->pid, dvbnetif->feedtype);
                if (result<0) {
                        module_put(dvbdev->adapter->module);
-                       return result;
+                       ret = result;
+                       goto ioctl_error;
                }
                dvbnetif->if_num=result;
                break;
@@ -1376,8 +1385,10 @@ static int dvb_net_do_ioctl(struct file *file,
                struct dvb_net_if *dvbnetif = parg;
 
                if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
-                   !dvbnet->state[dvbnetif->if_num])
-                       return -EINVAL;
+                   !dvbnet->state[dvbnetif->if_num]) {
+                       ret = -EINVAL;
+                       goto ioctl_error;
+               }
 
                netdev = dvbnet->device[dvbnetif->if_num];
 
@@ -1388,16 +1399,18 @@ static int dvb_net_do_ioctl(struct file *file,
        }
        case NET_REMOVE_IF:
        {
-               int ret;
-
-               if (!capable(CAP_SYS_ADMIN))
-                       return -EPERM;
-               if ((unsigned long) parg >= DVB_NET_DEVICES_MAX)
-                       return -EINVAL;
+               if (!capable(CAP_SYS_ADMIN)) {
+                       ret = -EPERM;
+                       goto ioctl_error;
+               }
+               if ((unsigned long) parg >= DVB_NET_DEVICES_MAX) {
+                       ret = -EINVAL;
+                       goto ioctl_error;
+               }
                ret = dvb_net_remove_if(dvbnet, (unsigned long) parg);
                if (!ret)
                        module_put(dvbdev->adapter->module);
-               return ret;
+               break;
        }
 
        /* binary compatibility cruft */
@@ -1406,16 +1419,21 @@ static int dvb_net_do_ioctl(struct file *file,
                struct __dvb_net_if_old *dvbnetif = parg;
                int result;
 
-               if (!capable(CAP_SYS_ADMIN))
-                       return -EPERM;
+               if (!capable(CAP_SYS_ADMIN)) {
+                       ret = -EPERM;
+                       goto ioctl_error;
+               }
 
-               if (!try_module_get(dvbdev->adapter->module))
-                       return -EPERM;
+               if (!try_module_get(dvbdev->adapter->module)) {
+                       ret = -EPERM;
+                       goto ioctl_error;
+               }
 
                result=dvb_net_add_if(dvbnet, dvbnetif->pid, DVB_NET_FEEDTYPE_MPE);
                if (result<0) {
                        module_put(dvbdev->adapter->module);
-                       return result;
+                       ret = result;
+                       goto ioctl_error;
                }
                dvbnetif->if_num=result;
                break;
@@ -1427,8 +1445,10 @@ static int dvb_net_do_ioctl(struct file *file,
                struct __dvb_net_if_old *dvbnetif = parg;
 
                if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
-                   !dvbnet->state[dvbnetif->if_num])
-                       return -EINVAL;
+                   !dvbnet->state[dvbnetif->if_num]) {
+                       ret = -EINVAL;
+                       goto ioctl_error;
+               }
 
                netdev = dvbnet->device[dvbnetif->if_num];
 
@@ -1437,9 +1457,13 @@ static int dvb_net_do_ioctl(struct file *file,
                break;
        }
        default:
-               return -ENOTTY;
+               ret = -ENOTTY;
+               break;
        }
-       return 0;
+
+ioctl_error:
+       mutex_unlock(&dvbnet->ioctl_mutex);
+       return ret;
 }
 
 static long dvb_net_ioctl(struct file *file,
@@ -1505,6 +1529,7 @@ int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet,
 {
        int i;
 
+       mutex_init(&dvbnet->ioctl_mutex);
        dvbnet->demux = dmx;
 
        for (i=0; i<DVB_NET_DEVICES_MAX; i++)