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@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb