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 */
modoption_adapter_numbers.diff.bz2
Description: BZip2 compressed data
_______________________________________________ linux-dvb mailing list [email protected] http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
