diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-03 18:37:57 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-03 18:37:57 (GMT) |
commit | 751144271f4b63d5de9005ea4e5e6e5c7c6fd629 (patch) | |
tree | 2e5cb8223d4f6146f01f123a9f33cf6d468205c6 /drivers/staging/comedi/drivers.c | |
parent | 542a086ac72fb193cbc1b996963a572269e57743 (diff) | |
parent | 91121c103ae93ef117e58712786864270d7f488e (diff) | |
download | linux-751144271f4b63d5de9005ea4e5e6e5c7c6fd629.tar.xz |
Merge tag 'staging-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
Pull staging tree merge from Greg KH:
"Here's the bit staging tree pull request for 3.12-rc1.
Lots of staging driver updates, and fixes. Lustre is finally enabled
in the build, and lots of cleanup started happening in it. There's a
new wireless driver in here, and 2 new TTY drivers, which cause the
overall lines added/removed to be quite large on the "added" side.
The IIO driver updates are also coming through here, as they are tied
to the staging iio drivers"
* tag 'staging-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (942 commits)
staging: dwc2: make dwc2_core_params documentation more complete
staging: dwc2: validate the value for phy_utmi_width
staging: dwc2: interpret all hwcfg and related register at init time
staging: dwc2: properly mask the GRXFSIZ register
staging: dwc2: remove redundant register reads
staging: dwc2: re-use hptxfsiz variable
staging: dwc2: simplify debug output in dwc_hc_init
staging: dwc2: add missing shift
staging: dwc2: simplify register shift expressions
staging: dwc2: only read the snpsid register once
staging: dwc2: unshift non-bool register value constants
staging: dwc2: fix off-by-one in check for max_packet_count parameter
staging: dwc2: remove specific fifo size constants
Staging:BCM:DDRInit.c:Renaming __FUNCTION__
staging: bcm: remove Version.h file.
staging: rtl8188eu: off by one in rtw_set_802_11_add_wep()
staging: r8188eu: copying one byte too much
staging: rtl8188eu: || vs && typo
staging: r8188eu: off by one bugs
staging: crystalhd: Resolve sparse 'different base types' warnings.
...
Diffstat (limited to 'drivers/staging/comedi/drivers.c')
-rw-r--r-- | drivers/staging/comedi/drivers.c | 94 |
1 files changed, 77 insertions, 17 deletions
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index b3b5125..317a821 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -23,7 +23,6 @@ #include <linux/kernel.h> #include <linux/sched.h> #include <linux/fcntl.h> -#include <linux/delay.h> #include <linux/ioport.h> #include <linux/mm.h> #include <linux/slab.h> @@ -39,6 +38,7 @@ #include "comedi_internal.h" struct comedi_driver *comedi_drivers; +DEFINE_MUTEX(comedi_drivers_list_lock); int comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev) { @@ -57,6 +57,18 @@ static void comedi_clear_hw_dev(struct comedi_device *dev) dev->hw_dev = NULL; } +/** + * comedi_alloc_devpriv() - Allocate memory for the device private data. + * @dev: comedi_device struct + * @size: size of the memory to allocate + */ +void *comedi_alloc_devpriv(struct comedi_device *dev, size_t size) +{ + dev->private = kzalloc(size, GFP_KERNEL); + return dev->private; +} +EXPORT_SYMBOL_GPL(comedi_alloc_devpriv); + int comedi_alloc_subdevices(struct comedi_device *dev, int num_subdevices) { struct comedi_subdevice *s; @@ -138,6 +150,46 @@ int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s, return -EINVAL; } +/** + * comedi_dio_insn_config() - boilerplate (*insn_config) for DIO subdevices. + * @dev: comedi_device struct + * @s: comedi_subdevice struct + * @insn: comedi_insn struct + * @data: parameters for the @insn + * @mask: io_bits mask for grouped channels + */ +int comedi_dio_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data, + unsigned int mask) +{ + unsigned int chan_mask = 1 << CR_CHAN(insn->chanspec); + + if (!mask) + mask = chan_mask; + + switch (data[0]) { + case INSN_CONFIG_DIO_INPUT: + s->io_bits &= ~mask; + break; + + case INSN_CONFIG_DIO_OUTPUT: + s->io_bits |= mask; + break; + + case INSN_CONFIG_DIO_QUERY: + data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT; + return insn->n; + + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(comedi_dio_insn_config); + static int insn_rw_emulate_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -442,6 +494,7 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (dev->attached) return -EBUSY; + mutex_lock(&comedi_drivers_list_lock); for (driv = comedi_drivers; driv; driv = driv->next) { if (!try_module_get(driv->module)) continue; @@ -462,7 +515,8 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) comedi_report_boards(driv); module_put(driv->module); } - return -EIO; + ret = -EIO; + goto out; } if (driv->attach == NULL) { /* driver does not support manual configuration */ @@ -470,7 +524,8 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) "driver '%s' does not support attach using comedi_config\n", driv->driver_name); module_put(driv->module); - return -ENOSYS; + ret = -ENOSYS; + goto out; } /* initialize dev->driver here so * comedi_error() can be called from attach */ @@ -485,6 +540,8 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) module_put(driv->module); } /* On success, the driver module count has been incremented. */ +out: + mutex_unlock(&comedi_drivers_list_lock); return ret; } @@ -541,18 +598,34 @@ EXPORT_SYMBOL_GPL(comedi_auto_unconfig); int comedi_driver_register(struct comedi_driver *driver) { + mutex_lock(&comedi_drivers_list_lock); driver->next = comedi_drivers; comedi_drivers = driver; + mutex_unlock(&comedi_drivers_list_lock); return 0; } EXPORT_SYMBOL_GPL(comedi_driver_register); -int comedi_driver_unregister(struct comedi_driver *driver) +void comedi_driver_unregister(struct comedi_driver *driver) { struct comedi_driver *prev; int i; + /* unlink the driver */ + mutex_lock(&comedi_drivers_list_lock); + if (comedi_drivers == driver) { + comedi_drivers = driver->next; + } else { + for (prev = comedi_drivers; prev->next; prev = prev->next) { + if (prev->next == driver) { + prev->next = driver->next; + break; + } + } + } + mutex_unlock(&comedi_drivers_list_lock); + /* check for devices using this driver */ for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) { struct comedi_device *dev = comedi_dev_from_minor(i); @@ -570,18 +643,5 @@ int comedi_driver_unregister(struct comedi_driver *driver) } mutex_unlock(&dev->mutex); } - - if (comedi_drivers == driver) { - comedi_drivers = driver->next; - return 0; - } - - for (prev = comedi_drivers; prev->next; prev = prev->next) { - if (prev->next == driver) { - prev->next = driver->next; - return 0; - } - } - return -EINVAL; } EXPORT_SYMBOL_GPL(comedi_driver_unregister); |