Skip to content

Commit

Permalink
V4L/DVB (9361): Dynamic DVB minor allocation
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Andreas Oberritter authored and Mauro Carvalho Chehab committed Dec 29, 2008
1 parent 568e9bb commit 5dd3f30
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 19 deletions.
13 changes: 13 additions & 0 deletions drivers/media/dvb/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@
# 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
bool "DVB/ATSC adapters"
depends on DVB_CORE
Expand Down
57 changes: 38 additions & 19 deletions drivers/media/dvb/dvb-core/dvbdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,33 +50,27 @@ static const char * const dnames[] = {
"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 nums2minor(num,type,id) ((num << 6) | (id << 4) | type)
#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64)
#endif

static struct class *dvb_class;

static struct dvb_device* dvbdev_find_device (int minor)
{
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 struct dvb_device *dvb_minors[MAX_DVB_MINORS];
static DECLARE_RWSEM(minor_rwsem);

static int dvb_device_open(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev;

lock_kernel();
dvbdev = dvbdev_find_device (iminor(inode));
down_read(&minor_rwsem);
dvbdev = dvb_minors[iminor(inode)];

if (dvbdev && dvbdev->fops) {
int err = 0;
Expand All @@ -92,9 +86,11 @@ static int dvb_device_open(struct inode *inode, struct file *file)
file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
up_read(&minor_rwsem);
unlock_kernel();
return err;
}
up_read(&minor_rwsem);
unlock_kernel();
return -ENODEV;
}
Expand Down Expand Up @@ -192,6 +188,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
struct dvb_device *dvbdev;
struct file_operations *dvbdevfops;
struct device *clsdev;
int minor;
int id;

mutex_lock(&dvbdev_register_lock);
Expand Down Expand Up @@ -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);

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);

clsdev = device_create(dvb_class, adap->device,
Expand All @@ -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",
adap->num, dnames[type], id, nums2minor(adap->num, type, id),
nums2minor(adap->num, type, id));
adap->num, dnames[type], id, minor, minor);

return 0;
}
Expand All @@ -256,8 +272,11 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
if (!dvbdev)
return;

device_destroy(dvb_class, MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num,
dvbdev->type, dvbdev->id)));
down_write(&minor_rwsem);
dvb_minors[dvbdev->minor] = NULL;
up_write(&minor_rwsem);

device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));

list_del (&dvbdev->list_head);
kfree (dvbdev->fops);
Expand Down
1 change: 1 addition & 0 deletions drivers/media/dvb/dvb-core/dvbdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ struct dvb_device {
struct file_operations *fops;
struct dvb_adapter *adapter;
int type;
int minor;
u32 id;

/* in theory, 'users' can vanish now,
Expand Down

0 comments on commit 5dd3f30

Please sign in to comment.