Hi,

Dynamic loading of modules by udev on startup (aka coldplugging) doesn't
result in deterministic dvb adapter numbers.

V4L drivers have the {radio|vbi|video}_nr module options to allocate
static minor numbers per driver.
Attached patch adds a similiar mechanism to the dvb subsystem. To avoid
problems with device unplugging and repluging each driver holds
a DVB_MAX_ADAPTER long array of the preffered order of adapter numbers.
options dvb-usb-dib0700 adapter_nr=7,6,5,4,3,2,1,0 would result in a
reversed allocation of adapter numbers.
With adapter_nr=2,5 it tries first to get adapter number 2 and 5. If both
are already in use it will allocate the lowest free adapter number.

Besides following changes in dvb-core and dvb-usb core the patch adds to
all drivers 

+static int adapter_nr[] = {[0 ... (DVB_MAX_ADAPTERS - 1)] = DVB_UNSET };
+module_param_array(adapter_nr, int, NULL, 0444);
+MODULE_PARM_DESC(adapter_nr,"DVB adapter numbers");

and modifies the dvb_register_adapter call. Full patch is attached as
compressed file.

With the exception of dvb-usb I have just added the paramter to the module
with the dvb_register_adapter() call. budget-core and videobuf-dvb are
affected for example. I'll push the option to the driver which uses these
modules after we reached consent on the approach.

Janne 

diff -r 8f9147c3bacd linux/drivers/media/dvb/dvb-core/dvbdev.c
--- a/linux/drivers/media/dvb/dvb-core/dvbdev.c Wed Aug 01 12:14:44 2007 -0300
+++ b/linux/drivers/media/dvb/dvb-core/dvbdev.c Thu Aug 02 02:36:40 2007 +0200
@@ -53,7 +53,6 @@ static const char * const dnames[] = {
        "net", "osd"
 };
 
-#define DVB_MAX_ADAPTERS       8
 #define DVB_MAX_IDS            4
 #define nums2minor(num,type,id)        ((num << 6) | (id << 4) | type)
 #define MAX_DVB_MINORS         (DVB_MAX_ADAPTERS*64)
@@ -286,21 +285,25 @@ void dvb_unregister_device(struct dvb_de
 }
 EXPORT_SYMBOL(dvb_unregister_device);
 
+static int dvbdev_check_free_adapter_num(int num)
+{
+       struct list_head *entry;
+       list_for_each (entry, &dvb_adapter_list) {
+               struct dvb_adapter *adap;
+               adap = list_entry (entry, struct dvb_adapter, list_head);
+                if (adap->num == num)
+                       return 0;
+       }
+        return 1;
+}
 
 static int dvbdev_get_free_adapter_num (void)
 {
        int num = 0;
 
        while (num < DVB_MAX_ADAPTERS) {
-               struct list_head *entry;
-               list_for_each (entry, &dvb_adapter_list) {
-                       struct dvb_adapter *adap;
-                       adap = list_entry (entry, struct dvb_adapter, 
list_head);
-                       if (adap->num == num)
-                               goto skip;
-               }
-               return num;
-skip:
+               if (dvbdev_check_free_adapter_num(num))
+                       return num;
                num++;
        }
 
@@ -308,13 +311,27 @@ skip:
 }
 
 
-int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct 
module *module, struct device *device)
-{
-       int num;
+int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct 
module *module, struct device *device, int *adapter_nums)
+{
+       int i, num;
 
        mutex_lock(&dvbdev_register_lock);
 
-       if ((num = dvbdev_get_free_adapter_num ()) < 0) {
+       for (i=0; i<DVB_MAX_ADAPTERS; ++i) {
+               num = adapter_nums[i];
+               if (num >= 0  &&  num < DVB_MAX_ADAPTERS) {
+               /* use the one the driver asked for */
+                       if (dvbdev_check_free_adapter_num(num))
+                               break;
+               }
+               else {
+                       num = dvbdev_get_free_adapter_num();
+                       break;
+               }
+               num = -1;
+       }
+
+       if (num < 0) {
                mutex_unlock(&dvbdev_register_lock);
                return -ENFILE;
        }
diff -r 8f9147c3bacd linux/drivers/media/dvb/dvb-core/dvbdev.h
--- a/linux/drivers/media/dvb/dvb-core/dvbdev.h Wed Aug 01 12:14:44 2007 -0300
+++ b/linux/drivers/media/dvb/dvb-core/dvbdev.h Thu Aug 02 02:36:40 2007 +0200
@@ -31,6 +31,10 @@
 
 #define DVB_MAJOR 212
 
+#define DVB_MAX_ADAPTERS 8
+
+#define DVB_UNSET (-1)
+
 #define DVB_DEVICE_VIDEO      0
 #define DVB_DEVICE_AUDIO      1
 #define DVB_DEVICE_SEC        2
@@ -78,7 +82,9 @@ struct dvb_device {
 };
 
 
-extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, 
struct module *module, struct device *device);
+extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name,
+                                struct module *module, struct device *device,
+                                int *adapter_nums);
 extern int dvb_unregister_adapter (struct dvb_adapter *adap);
 
 extern int dvb_register_device (struct dvb_adapter *adap,
diff -r 8f9147c3bacd linux/drivers/media/dvb/dvb-usb/dvb-usb-common.h
--- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-common.h  Wed Aug 01 12:14:44 
2007 -0300
+++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-common.h  Thu Aug 02 03:00:25 
2007 +0200
@@ -40,7 +40,7 @@ extern int dvb_usb_i2c_init(struct dvb_u
 extern int dvb_usb_i2c_init(struct dvb_usb_device *);
 extern int dvb_usb_i2c_exit(struct dvb_usb_device *);
 
-extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap);
+extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, int 
*adapter_nums);
 extern int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap);
 extern int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap);
 extern int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap);
diff -r 8f9147c3bacd linux/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
--- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c     Wed Aug 01 12:14:44 
2007 -0300
+++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c     Thu Aug 02 03:00:25 
2007 +0200
@@ -77,12 +77,12 @@ static int dvb_usb_stop_feed(struct dvb_
        return dvb_usb_ctrl_feed(dvbdmxfeed,0);
 }
 
-int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap)
+int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, int *adapter_nums)
 {
        int ret;
 
        if ((ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
-                       adap->dev->owner, &adap->dev->udev->dev)) < 0) {
+                       adap->dev->owner, &adap->dev->udev->dev, adapter_nums)) 
< 0) {
                deb_info("dvb_register_adapter failed: error %d", ret);
                goto err;
        }
diff -r 8f9147c3bacd linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c
--- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c    Wed Aug 01 12:14:44 
2007 -0300
+++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c    Thu Aug 02 03:00:25 
2007 +0200
@@ -26,7 +26,7 @@ module_param_named(force_pid_filter_usag
 module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, 
int, 0444);
 MODULE_PARM_DESC(disable_rc_polling, "force all dvb-usb-devices to use a PID 
filter, if any (default: 0).");
 
-static int dvb_usb_adapter_init(struct dvb_usb_device *d)
+static int dvb_usb_adapter_init(struct dvb_usb_device *d, int *adapter_nrs)
 {
        struct dvb_usb_adapter *adap;
        int ret,n;
@@ -72,7 +72,7 @@ static int dvb_usb_adapter_init(struct d
                }
 
                if ((ret = dvb_usb_adapter_stream_init(adap)) ||
-                       (ret = dvb_usb_adapter_dvb_init(adap)) ||
+                       (ret = dvb_usb_adapter_dvb_init(adap, adapter_nrs)) ||
                        (ret = dvb_usb_adapter_frontend_init(adap))) {
                        return ret;
                }
@@ -122,7 +122,7 @@ static int dvb_usb_exit(struct dvb_usb_d
        return 0;
 }
 
-static int dvb_usb_init(struct dvb_usb_device *d)
+static int dvb_usb_init(struct dvb_usb_device *d, int *adapter_nums)
 {
        int ret = 0;
 
@@ -143,7 +143,7 @@ static int dvb_usb_init(struct dvb_usb_d
        dvb_usb_device_power_ctrl(d, 1);
 
        if ((ret = dvb_usb_i2c_init(d)) ||
-               (ret = dvb_usb_adapter_init(d))) {
+               (ret = dvb_usb_adapter_init(d, adapter_nums))) {
                dvb_usb_exit(d);
                return ret;
        }
@@ -214,7 +214,7 @@ int dvb_usb_device_power_ctrl(struct dvb
  * USB
  */
 int dvb_usb_device_init(struct usb_interface *intf, struct 
dvb_usb_device_properties
-               *props, struct module *owner,struct dvb_usb_device **du)
+               *props, struct module *owner,struct dvb_usb_device **du, int 
*adapter_nums)
 {
        struct usb_device *udev = interface_to_usbdev(intf);
        struct dvb_usb_device *d = NULL;
@@ -254,7 +254,7 @@ int dvb_usb_device_init(struct usb_inter
        if (du != NULL)
                *du = d;
 
-       ret = dvb_usb_init(d);
+       ret = dvb_usb_init(d, adapter_nums);
 
        if (ret == 0)
                info("%s successfully initialized and connected.",desc->name);
diff -r 8f9147c3bacd linux/drivers/media/dvb/dvb-usb/dvb-usb.h
--- a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h Wed Aug 01 12:14:44 2007 -0300
+++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h Thu Aug 02 03:00:25 2007 +0200
@@ -387,7 +387,7 @@ struct dvb_usb_device {
        void *priv;
 };
 
-extern int dvb_usb_device_init(struct usb_interface *, struct 
dvb_usb_device_properties *, struct module *, struct dvb_usb_device **);
+extern int dvb_usb_device_init(struct usb_interface *, struct 
dvb_usb_device_properties *, struct module *, struct dvb_usb_device **, int 
*adapter_nums);
 extern void dvb_usb_device_exit(struct usb_interface *);
 
 /* the generic read/write method for device control */

Attachment: modoption_adapter_numbers.diff.bz2
Description: BZip2 compressed data

_______________________________________________
linux-dvb mailing list
linux-dvb@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb

Reply via email to