[linux-dvb] [RFC PATCH] Choose dvb adapter number with a driver specific module option

Janne Grunau janne-dvb at grunau.be
Thu Aug 2 03:15:04 CEST 2007


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 */
-------------- next part --------------
A non-text attachment was scrubbed...
Name: modoption_adapter_numbers.diff.bz2
Type: application/x-bzip2
Size: 6178 bytes
Desc: not available
Url : http://www.linuxtv.org/pipermail/linux-dvb/attachments/20070802/4006fd03/attachment-0001.bin 


More information about the linux-dvb mailing list