diff options
Diffstat (limited to 'drivers/staging/comedi/comedi_fops.c')
-rw-r--r-- | drivers/staging/comedi/comedi_fops.c | 111 |
1 files changed, 82 insertions, 29 deletions
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index c99b28943c7d..c57f853d3c46 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -50,6 +50,8 @@ #include "comedi_internal.h" #define COMEDI_NUM_MINORS 0x100 +#define COMEDI_NUM_SUBDEVICE_MINORS \ + (COMEDI_NUM_MINORS - COMEDI_NUM_BOARD_MINORS) #ifdef CONFIG_COMEDI_DEBUG int comedi_debug; @@ -86,8 +88,14 @@ struct comedi_file_info { struct device *hardware_device; }; -static DEFINE_MUTEX(comedi_file_info_table_lock); -static struct comedi_file_info *comedi_file_info_table[COMEDI_NUM_MINORS]; +static DEFINE_MUTEX(comedi_board_minor_table_lock); +static struct comedi_file_info +*comedi_board_minor_table[COMEDI_NUM_BOARD_MINORS]; + +static DEFINE_MUTEX(comedi_subdevice_minor_table_lock); +/* Note: indexed by minor - COMEDI_NUM_BOARD_MINORS. */ +static struct comedi_file_info +*comedi_subdevice_minor_table[COMEDI_NUM_SUBDEVICE_MINORS]; static struct class *comedi_class; static struct cdev comedi_cdev; @@ -119,17 +127,37 @@ static void comedi_device_cleanup(struct comedi_device *dev) mutex_destroy(&dev->mutex); } -static struct comedi_file_info *comedi_clear_minor(unsigned minor) +static struct comedi_file_info *comedi_clear_board_minor(unsigned minor) { struct comedi_file_info *info; - mutex_lock(&comedi_file_info_table_lock); - info = comedi_file_info_table[minor]; - comedi_file_info_table[minor] = NULL; - mutex_unlock(&comedi_file_info_table_lock); + mutex_lock(&comedi_board_minor_table_lock); + info = comedi_board_minor_table[minor]; + comedi_board_minor_table[minor] = NULL; + mutex_unlock(&comedi_board_minor_table_lock); return info; } +static struct comedi_file_info *comedi_clear_subdevice_minor(unsigned minor) +{ + struct comedi_file_info *info; + unsigned int i = minor - COMEDI_NUM_BOARD_MINORS; + + mutex_lock(&comedi_subdevice_minor_table_lock); + info = comedi_subdevice_minor_table[i]; + comedi_subdevice_minor_table[i] = NULL; + mutex_unlock(&comedi_subdevice_minor_table_lock); + return info; +} + +static struct comedi_file_info *comedi_clear_minor(unsigned minor) +{ + if (minor < COMEDI_NUM_BOARD_MINORS) + return comedi_clear_board_minor(minor); + else + return comedi_clear_subdevice_minor(minor); +} + static void comedi_free_board_file_info(struct comedi_file_info *info) { if (info) { @@ -146,17 +174,39 @@ static void comedi_free_board_file_info(struct comedi_file_info *info) } } -static struct comedi_file_info *comedi_file_info_from_minor(unsigned minor) +static struct comedi_file_info +*comedi_file_info_from_board_minor(unsigned minor) { struct comedi_file_info *info; - BUG_ON(minor >= COMEDI_NUM_MINORS); - mutex_lock(&comedi_file_info_table_lock); - info = comedi_file_info_table[minor]; - mutex_unlock(&comedi_file_info_table_lock); + BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS); + mutex_lock(&comedi_board_minor_table_lock); + info = comedi_board_minor_table[minor]; + mutex_unlock(&comedi_board_minor_table_lock); return info; } +static struct comedi_file_info +*comedi_file_info_from_subdevice_minor(unsigned minor) +{ + struct comedi_file_info *info; + unsigned int i = minor - COMEDI_NUM_BOARD_MINORS; + + BUG_ON(i >= COMEDI_NUM_SUBDEVICE_MINORS); + mutex_lock(&comedi_subdevice_minor_table_lock); + info = comedi_subdevice_minor_table[i]; + mutex_unlock(&comedi_subdevice_minor_table_lock); + return info; +} + +static struct comedi_file_info *comedi_file_info_from_minor(unsigned minor) +{ + if (minor < COMEDI_NUM_BOARD_MINORS) + return comedi_file_info_from_board_minor(minor); + else + return comedi_file_info_from_subdevice_minor(minor); +} + static struct comedi_device * comedi_dev_from_file_info(struct comedi_file_info *info) { @@ -2330,15 +2380,15 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device) comedi_device_init(dev); comedi_set_hw_dev(dev, hardware_device); mutex_lock(&dev->mutex); - mutex_lock(&comedi_file_info_table_lock); + mutex_lock(&comedi_board_minor_table_lock); for (i = hardware_device ? comedi_num_legacy_minors : 0; i < COMEDI_NUM_BOARD_MINORS; ++i) { - if (comedi_file_info_table[i] == NULL) { - comedi_file_info_table[i] = info; + if (comedi_board_minor_table[i] == NULL) { + comedi_board_minor_table[i] = info; break; } } - mutex_unlock(&comedi_file_info_table_lock); + mutex_unlock(&comedi_board_minor_table_lock); if (i == COMEDI_NUM_BOARD_MINORS) { mutex_unlock(&dev->mutex); comedi_device_cleanup(dev); @@ -2371,15 +2421,15 @@ void comedi_release_hardware_device(struct device *hardware_device) for (minor = comedi_num_legacy_minors; minor < COMEDI_NUM_BOARD_MINORS; minor++) { - mutex_lock(&comedi_file_info_table_lock); - info = comedi_file_info_table[minor]; + mutex_lock(&comedi_board_minor_table_lock); + info = comedi_board_minor_table[minor]; if (info && info->hardware_device == hardware_device) { - comedi_file_info_table[minor] = NULL; - mutex_unlock(&comedi_file_info_table_lock); + comedi_board_minor_table[minor] = NULL; + mutex_unlock(&comedi_board_minor_table_lock); comedi_free_board_file_info(info); break; } - mutex_unlock(&comedi_file_info_table_lock); + mutex_unlock(&comedi_board_minor_table_lock); } } @@ -2398,19 +2448,20 @@ int comedi_alloc_subdevice_minor(struct comedi_subdevice *s) info->read_subdevice = s; if (s->subdev_flags & SDF_CMD_WRITE) info->write_subdevice = s; - mutex_lock(&comedi_file_info_table_lock); - for (i = COMEDI_NUM_BOARD_MINORS; i < COMEDI_NUM_MINORS; ++i) { - if (comedi_file_info_table[i] == NULL) { - comedi_file_info_table[i] = info; + mutex_lock(&comedi_subdevice_minor_table_lock); + for (i = 0; i < COMEDI_NUM_SUBDEVICE_MINORS; ++i) { + if (comedi_subdevice_minor_table[i] == NULL) { + comedi_subdevice_minor_table[i] = info; break; } } - mutex_unlock(&comedi_file_info_table_lock); - if (i == COMEDI_NUM_MINORS) { + mutex_unlock(&comedi_subdevice_minor_table_lock); + if (i == COMEDI_NUM_SUBDEVICE_MINORS) { kfree(info); pr_err("comedi: error: ran out of minor numbers for subdevice files.\n"); return -EBUSY; } + i += COMEDI_NUM_BOARD_MINORS; s->minor = i; csdev = device_create(comedi_class, dev->class_dev, MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i_subd%i", @@ -2515,8 +2566,10 @@ static void __exit comedi_cleanup(void) int i; comedi_cleanup_board_minors(); - for (i = 0; i < COMEDI_NUM_MINORS; ++i) - BUG_ON(comedi_file_info_table[i]); + for (i = 0; i < COMEDI_NUM_BOARD_MINORS; ++i) + BUG_ON(comedi_board_minor_table[i]); + for (i = 0; i < COMEDI_NUM_SUBDEVICE_MINORS; ++i) + BUG_ON(comedi_subdevice_minor_table[i]); class_destroy(comedi_class); cdev_del(&comedi_cdev); |