From b449c1cad7e3acf80834d4bdb1b6241d5d8dd249 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:33 +0000 Subject: [PATCH] staging: comedi: add comedi_dev_get_from_minor() Add function `struct comedi_device *comedi_dev_get_from_minor(unsigned minor)`. This behaves like the existing `comedi_dev_from_minor()` except that it also increments the `struct kref refcount` member (via new helper function `comedi_dev_get()`) to prevent it being freed. If it returns a valid pointer, the caller is responsible for calling `comedi_dev_put()` to decrement the reference count. Export `comedi_dev_get_from_minor()` and `comedi_dev_put()` as they will be used by the "kcomedilib" module in addition to the "comedi" module itself. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 42 ++++++++++++++++++++++++++++ drivers/staging/comedi/comedidev.h | 2 ++ 2 files changed, 44 insertions(+) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 403324c895b1..5e5ddbdbad0b 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -111,6 +111,14 @@ int comedi_dev_put(struct comedi_device *dev) return kref_put(&dev->refcount, comedi_dev_kref_release); return 1; } +EXPORT_SYMBOL_GPL(comedi_dev_put); + +static struct comedi_device *comedi_dev_get(struct comedi_device *dev) +{ + if (dev) + kref_get(&dev->refcount); + return dev; +} static void comedi_device_cleanup(struct comedi_device *dev) { @@ -209,6 +217,40 @@ struct comedi_device *comedi_dev_from_minor(unsigned minor) } EXPORT_SYMBOL_GPL(comedi_dev_from_minor); +static struct comedi_device *comedi_dev_get_from_board_minor(unsigned minor) +{ + struct comedi_device *dev; + + BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS); + mutex_lock(&comedi_board_minor_table_lock); + dev = comedi_dev_get(comedi_board_minor_table[minor]); + mutex_unlock(&comedi_board_minor_table_lock); + return dev; +} + +static struct comedi_device *comedi_dev_get_from_subdevice_minor(unsigned minor) +{ + struct comedi_device *dev; + struct comedi_subdevice *s; + unsigned int i = minor - COMEDI_NUM_BOARD_MINORS; + + BUG_ON(i >= COMEDI_NUM_SUBDEVICE_MINORS); + mutex_lock(&comedi_subdevice_minor_table_lock); + s = comedi_subdevice_minor_table[i]; + dev = comedi_dev_get(s ? s->device : NULL); + mutex_unlock(&comedi_subdevice_minor_table_lock); + return dev; +} + +struct comedi_device *comedi_dev_get_from_minor(unsigned minor) +{ + if (minor < COMEDI_NUM_BOARD_MINORS) + return comedi_dev_get_from_board_minor(minor); + else + return comedi_dev_get_from_subdevice_minor(minor); +} +EXPORT_SYMBOL_GPL(comedi_dev_get_from_minor); + static struct comedi_subdevice * comedi_read_subdevice(const struct comedi_device *dev, unsigned int minor) { diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 08652dfa8c03..a9b1468aa17c 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -236,6 +236,8 @@ static const unsigned COMEDI_SUBDEVICE_MINOR_SHIFT = 4; static const unsigned COMEDI_SUBDEVICE_MINOR_OFFSET = 1; struct comedi_device *comedi_dev_from_minor(unsigned minor); +struct comedi_device *comedi_dev_get_from_minor(unsigned minor); +int comedi_dev_put(struct comedi_device *dev); void init_polling(void); void cleanup_polling(void); -- 2.39.5