mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-19 02:04:19 +08:00
V4L/DVB (9361): Dynamic DVB minor allocation
Implement dynamic minor allocation for DVB, to allow more than four devices of the same type per adapter, based on drivers/usb/core/file.c. Add a new config option, DVB_DYNAMIC_MINORS, to make use of this feature, which defaults to no for backwards compatibility. Signed-off-by: Andreas Oberritter <obi@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
568e9bb8d7
commit
5dd3f30710
@ -2,6 +2,19 @@
|
|||||||
# DVB device configuration
|
# DVB device configuration
|
||||||
#
|
#
|
||||||
|
|
||||||
|
config DVB_DYNAMIC_MINORS
|
||||||
|
bool "Dynamic DVB minor allocation"
|
||||||
|
depends on DVB_CORE
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
If you say Y here, the DVB subsystem will use dynamic minor
|
||||||
|
allocation for any device that uses the DVB major number.
|
||||||
|
This means that you can have more than 4 of a single type
|
||||||
|
of device (like demuxes and frontends) per adapter, but udev
|
||||||
|
will be required to manage the device nodes.
|
||||||
|
|
||||||
|
If you are unsure about this, say N here.
|
||||||
|
|
||||||
menuconfig DVB_CAPTURE_DRIVERS
|
menuconfig DVB_CAPTURE_DRIVERS
|
||||||
bool "DVB/ATSC adapters"
|
bool "DVB/ATSC adapters"
|
||||||
depends on DVB_CORE
|
depends on DVB_CORE
|
||||||
|
@ -50,33 +50,27 @@ static const char * const dnames[] = {
|
|||||||
"net", "osd"
|
"net", "osd"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_DVB_DYNAMIC_MINORS
|
||||||
|
#define MAX_DVB_MINORS 256
|
||||||
|
#define DVB_MAX_IDS MAX_DVB_MINORS
|
||||||
|
#else
|
||||||
#define DVB_MAX_IDS 4
|
#define DVB_MAX_IDS 4
|
||||||
#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type)
|
#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type)
|
||||||
#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64)
|
#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64)
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct class *dvb_class;
|
static struct class *dvb_class;
|
||||||
|
|
||||||
static struct dvb_device* dvbdev_find_device (int minor)
|
static struct dvb_device *dvb_minors[MAX_DVB_MINORS];
|
||||||
{
|
static DECLARE_RWSEM(minor_rwsem);
|
||||||
struct dvb_adapter *adap;
|
|
||||||
|
|
||||||
list_for_each_entry(adap, &dvb_adapter_list, list_head) {
|
|
||||||
struct dvb_device *dev;
|
|
||||||
list_for_each_entry(dev, &adap->device_list, list_head)
|
|
||||||
if (nums2minor(adap->num, dev->type, dev->id) == minor)
|
|
||||||
return dev;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int dvb_device_open(struct inode *inode, struct file *file)
|
static int dvb_device_open(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
struct dvb_device *dvbdev;
|
struct dvb_device *dvbdev;
|
||||||
|
|
||||||
lock_kernel();
|
lock_kernel();
|
||||||
dvbdev = dvbdev_find_device (iminor(inode));
|
down_read(&minor_rwsem);
|
||||||
|
dvbdev = dvb_minors[iminor(inode)];
|
||||||
|
|
||||||
if (dvbdev && dvbdev->fops) {
|
if (dvbdev && dvbdev->fops) {
|
||||||
int err = 0;
|
int err = 0;
|
||||||
@ -92,9 +86,11 @@ static int dvb_device_open(struct inode *inode, struct file *file)
|
|||||||
file->f_op = fops_get(old_fops);
|
file->f_op = fops_get(old_fops);
|
||||||
}
|
}
|
||||||
fops_put(old_fops);
|
fops_put(old_fops);
|
||||||
|
up_read(&minor_rwsem);
|
||||||
unlock_kernel();
|
unlock_kernel();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
up_read(&minor_rwsem);
|
||||||
unlock_kernel();
|
unlock_kernel();
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
@ -192,6 +188,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
|||||||
struct dvb_device *dvbdev;
|
struct dvb_device *dvbdev;
|
||||||
struct file_operations *dvbdevfops;
|
struct file_operations *dvbdevfops;
|
||||||
struct device *clsdev;
|
struct device *clsdev;
|
||||||
|
int minor;
|
||||||
int id;
|
int id;
|
||||||
|
|
||||||
mutex_lock(&dvbdev_register_lock);
|
mutex_lock(&dvbdev_register_lock);
|
||||||
@ -231,6 +228,26 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
|||||||
|
|
||||||
list_add_tail (&dvbdev->list_head, &adap->device_list);
|
list_add_tail (&dvbdev->list_head, &adap->device_list);
|
||||||
|
|
||||||
|
down_write(&minor_rwsem);
|
||||||
|
#ifdef CONFIG_DVB_DYNAMIC_MINORS
|
||||||
|
for (minor = 0; minor < MAX_DVB_MINORS; minor++)
|
||||||
|
if (dvb_minors[minor] == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (minor == MAX_DVB_MINORS) {
|
||||||
|
kfree(dvbdevfops);
|
||||||
|
kfree(dvbdev);
|
||||||
|
mutex_unlock(&dvbdev_register_lock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
minor = nums2minor(adap->num, type, id);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dvbdev->minor = minor;
|
||||||
|
dvb_minors[minor] = dvbdev;
|
||||||
|
up_write(&minor_rwsem);
|
||||||
|
|
||||||
mutex_unlock(&dvbdev_register_lock);
|
mutex_unlock(&dvbdev_register_lock);
|
||||||
|
|
||||||
clsdev = device_create(dvb_class, adap->device,
|
clsdev = device_create(dvb_class, adap->device,
|
||||||
@ -243,8 +260,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
|
dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
|
||||||
adap->num, dnames[type], id, nums2minor(adap->num, type, id),
|
adap->num, dnames[type], id, minor, minor);
|
||||||
nums2minor(adap->num, type, id));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -256,8 +272,11 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
|
|||||||
if (!dvbdev)
|
if (!dvbdev)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
device_destroy(dvb_class, MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num,
|
down_write(&minor_rwsem);
|
||||||
dvbdev->type, dvbdev->id)));
|
dvb_minors[dvbdev->minor] = NULL;
|
||||||
|
up_write(&minor_rwsem);
|
||||||
|
|
||||||
|
device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
|
||||||
|
|
||||||
list_del (&dvbdev->list_head);
|
list_del (&dvbdev->list_head);
|
||||||
kfree (dvbdev->fops);
|
kfree (dvbdev->fops);
|
||||||
|
@ -74,6 +74,7 @@ struct dvb_device {
|
|||||||
struct file_operations *fops;
|
struct file_operations *fops;
|
||||||
struct dvb_adapter *adapter;
|
struct dvb_adapter *adapter;
|
||||||
int type;
|
int type;
|
||||||
|
int minor;
|
||||||
u32 id;
|
u32 id;
|
||||||
|
|
||||||
/* in theory, 'users' can vanish now,
|
/* in theory, 'users' can vanish now,
|
||||||
|
Loading…
Reference in New Issue
Block a user