summaryrefslogtreecommitdiffstats
path: root/drivers/staging/comedi/comedi_internal.h
Commit message (Collapse)AuthorAgeFilesLines
* staging: comedi: add new comedi_buf_write_n_available()Ian Abbott2015-10-131-0/+1
| | | | | | | | | | | | Add a new function `comedi_buf_write_n_available()` to return the amount of buffer space available for writing, including space already allocated by `comedi_buf_write_alloc()` plus any unallocated space available. This is currently just for internal use by the comedi core, so is not exported. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: wrap COMEDI_SRF_FREE_SPRIV usageIan Abbott2015-04-301-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | The `COMEDI_SRF_FREE_SPRIV` flag in the `runflags` member of `struct comedi_subdevice` indicates that the memory pointed to by the `private` member can be automatically freed by the comedi core on subdevice clean-up (when the low-level comedi device is being "detached"). the flag doesn't really belong in `runflags`, but it was somewhere convenient to keep it without having to add a new member to the structure. Rather than access the `COMEDI_SRF_FREE_SPRIV` flag directly, use some new wrapper functions: * comedi_can_auto_free_spriv(s) - checks whether the subdevice's `s->private` points to memory that can be freed automatically. * comedi_set_spriv_auto_free(s) - marks the subdevice as having a `s->private` that points to memory that can be freed automatically. Export `comedi_set_spriv_auto_free()` for use by the low-level comedi driver modules, in particular the "amplc_dio200_common" module. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: make comedi_internal.h self-reliantIan Abbott2015-04-031-0/+10
| | | | | | | | | Add `#include`s and declare incomplete types to "comedi_internal.h" so that .c files still compile when it is the first file included. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: comedi_internal.h: checkpatch.pl --strict cleanupH Hartley Sweeten2014-07-181-0/+1
| | | | | | | | | | Fix the checkpatch.pl --strict issues: CHECK: Please use a blank line after function/struct/union/enum declarations Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Cc: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: pass subdevice to comedi_buf_is_mmapped()Ian Abbott2014-05-231-1/+1
| | | | | | | | | | | | | | Change the parameters of `comedi_buf_is_mmapped()` to pass a pointer to the comedi subdevice instead of a pointer to the "async" structure belonging to the subdevice. The main aim at the moment is to replace all the `struct comedi_async *` parameters with `struct comedi_subdevice *` parameters in the comedi driver API. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: pass subdevice to comedi_buf_reset()Ian Abbott2014-05-231-1/+1
| | | | | | | | | | | | | | Change the parameters of `comedi_buf_reset()` to pass a pointer to the comedi subdevice instead of a pointer to the "async" structure belonging to the subdevice. The main aim at the moment is to replace all the `struct comedi_async *` parameters with `struct comedi_subdevice *` parameters in the comedi driver API. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: pass subdevice to comedi_buf_write_n_allocated()Ian Abbott2014-05-231-1/+1
| | | | | | | | | | | | | | Change the parameters of `comedi_buf_write_n_allocated()` to pass a pointer to the comedi subdevice instead of a pointer to the "async" structure belonging to the subdevice. The main aim at the moment is to replace all the `struct comedi_async *` parameters with `struct comedi_subdevice *` parameters in the comedi driver API. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: fix circular locking dependency in comedi_mmap()Ian Abbott2014-04-161-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Mmapping a comedi data buffer with lockdep checking enabled produced the following kernel debug messages: ====================================================== [ INFO: possible circular locking dependency detected ] 3.5.0-rc3-ija1+ #9 Tainted: G C ------------------------------------------------------- comedi_test/4160 is trying to acquire lock: (&dev->mutex#2){+.+.+.}, at: [<ffffffffa00313f4>] comedi_mmap+0x57/0x1d9 [comedi] but task is already holding lock: (&mm->mmap_sem){++++++}, at: [<ffffffff810c96fe>] vm_mmap_pgoff+0x41/0x76 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (&mm->mmap_sem){++++++}: [<ffffffff8106d0e8>] lock_acquire+0x97/0x105 [<ffffffff810ce3bc>] might_fault+0x6d/0x90 [<ffffffffa0031ffb>] do_devinfo_ioctl.isra.7+0x11e/0x14c [comedi] [<ffffffffa003227f>] comedi_unlocked_ioctl+0x256/0xe48 [comedi] [<ffffffff810f7fcd>] vfs_ioctl+0x18/0x34 [<ffffffff810f87fd>] do_vfs_ioctl+0x382/0x43c [<ffffffff810f88f9>] sys_ioctl+0x42/0x65 [<ffffffff81415c62>] system_call_fastpath+0x16/0x1b -> #0 (&dev->mutex#2){+.+.+.}: [<ffffffff8106c528>] __lock_acquire+0x101d/0x1591 [<ffffffff8106d0e8>] lock_acquire+0x97/0x105 [<ffffffff8140c894>] mutex_lock_nested+0x46/0x2a4 [<ffffffffa00313f4>] comedi_mmap+0x57/0x1d9 [comedi] [<ffffffff810d5816>] mmap_region+0x281/0x492 [<ffffffff810d5c92>] do_mmap_pgoff+0x26b/0x2a7 [<ffffffff810c971a>] vm_mmap_pgoff+0x5d/0x76 [<ffffffff810d493f>] sys_mmap_pgoff+0xc7/0x10d [<ffffffff81004d36>] sys_mmap+0x16/0x20 [<ffffffff81415c62>] system_call_fastpath+0x16/0x1b other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&mm->mmap_sem); lock(&dev->mutex#2); lock(&mm->mmap_sem); lock(&dev->mutex#2); *** DEADLOCK *** To avoid the circular dependency, just try to get the lock in `comedi_mmap()` instead of blocking. Since the comedi device's main mutex is heavily used, do a down-read of its `attach_lock` rwsemaphore instead. Trying to down-read `attach_lock` should only fail if some task has down-write locked it, and that is only done while the comedi device is being attached to or detached from a low-level hardware device. Unfortunately, acquiring the `attach_lock` doesn't prevent another task replacing the comedi data buffer we are trying to mmap. The details of the buffer are held in a `struct comedi_buf_map` and pointed to by `s->async->buf_map` where `s` is the comedi subdevice whose buffer we are trying to map. The `struct comedi_buf_map` is already reference counted with a `struct kref`, so we can stop it being freed prematurely. Modify `comedi_mmap()` to call new function `comedi_buf_map_from_subdev_get()` to read the subdevice's current buffer map pointer and increment its reference instead of accessing `async->buf_map` directly. Call `comedi_buf_map_put()` to decrement the reference once the buffer map structure has been dealt with. (Note that `comedi_buf_map_put()` does nothing if passed a NULL pointer.) `comedi_buf_map_from_subdev_get()` checks the subdevice's buffer map pointer has been set and the buffer map has been initialized enough for `comedi_mmap()` to deal with it (specifically, check the `n_pages` member has been set to a non-zero value). If all is well, the buffer map's reference is incremented and a pointer to it is returned. The comedi subdevice's spin-lock is used to protect the checks. Also use the spin-lock in `__comedi_buf_alloc()` and `__comedi_buf_free()` to protect changes to the subdevice's buffer map structure pointer and the buffer map structure's `n_pages` member. (This checking of `n_pages` is a bit clunky and I [Ian Abbott] plan to deal with it in the future.) Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Cc: <stable@vger.kernel.org> # 3.14.x, 3.15.x Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: protect buffer from being freed while mmappedIan Abbott2013-11-111-0/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | If a comedi device is automatically detached by `comedi_auto_unconfig()` any data buffers associated with subdevices that support asynchronous commands will be freed. If the buffer is mmapped at the time, bad things are likely to happen! Prevent this by moving some of the buffer details from `struct comedi_async` into a new, dynamically allocated, and kref-counted `struct comedi_buf_map`. This holds a list of pages, a reference count, and enough information to free the pages. The new member `buf_map` of `struct comedi_async` points to a `struct comedi_buf_map` when the buffer size is non-zero. Provide a new helper function `comedi_buf_is_mapped()` to check whether an a buffer is mmapped. If it is mmapped, the buffer is not allowed to be resized and the device is not allowed to be manually detached by the `COMEDI_DEVCONFIG` ioctl. Provide helper functions `comedi_buf_map_get()` and `comedi_buf_map_put()` to manipulate the reference count of the `struct comedi_buf_map`, which will be freed along with its contents via the 'release' callback of the `kref_put()` call. The reference count is manipulated by the vma operations and the mmap file operation. Now, when the comedi device is automatically detached, the buffer will be effectively freed by calling `comedi_buf_alloc()` with a new buffer size of 0. That calls local function `__comedi_buf_free()` which calls `comedi_buf_map_put()` on the `buf_map` member to free it. It won't actually be freed until the final 'put'. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: cancel commands before detaching deviceIan Abbott2013-11-111-0/+1
| | | | | | | | | | | | | The comedi core module's handling of the `COMEDI_DEVCONFIG` ioctl will not allow a device to be detached if it is busy. However, comedi devices can also be auto-detached due to a removal of a hardware device. One of the things we should do in that case is cancel any asynchronous commands that are running. Add a new function `comedi_device_cancel_all()` to do that and call it from `comedi_device_detach()`. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: use a mutex when accessing driver listIan Abbott2013-07-231-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Low-level comedi drivers registered with the comedi core by `comedi_driver_register()` are linked together into a simple linked list headed by the `comedi_drivers` variable and chained by the `next` member of `struct comedi_driver`. A driver is removed from the list by `comedi_driver_unregister()`. The driver list is iterated through by `comedi_device_attach()` when the `COMEDI_DEVCONFIG` ioctl is used to attach a "legacy" device to a driver, and is also iterated through by `comedi_read()` in "proc.c" when reading "/proc/comedi". There is currently no protection against items being added or removed from the list while it is being iterated. Add a mutex `comedi_drivers_list_lock` to be locked while adding or removing an item on the list, or when iterating through the list. `comedi_driver_unregister()` also checks for and detaches any devices using the driver. This is currently done before unlinking the driver from the list, but it makes more sense to unlink the driver from the list first to prevent `comedi_device_attach()` attempting to use it, so move the unlinking part to the start of the function. Also, in `comedi_device_attach()` hold on to the mutex until we've finished attempting to attach the device to avoid it interfering with the detachment in `comedi_driver_unregister()`. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: change comedi_alloc_board_minor() to return pointerIan Abbott2013-04-051-1/+1
| | | | | | | | | | | | | | Change `comedi_alloc_board_minor()` to return a pointer to the allocated `struct comedi_device` instead of a minor device number. Return an `ERR_PTR()` value on error instead of a negative error number. This saves a call to `comedi_dev_from_minor()` in `comedi_auto_config()`. Also change it to use a local variable `dev` to hold the pointer to the `struct comedi_device` instead of using `info->device` all the time. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: make comedi_free_board_minor() staticIan Abbott2013-04-051-1/+0
| | | | | | | | | `comedi_free_board_minor()` is now only called from the same .c file it is defined in, so give it static linkage. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: add comedi_release_hardware_device()Ian Abbott2013-04-051-1/+1
| | | | | | | | | | | | | | Add `comedi_release_hardware_device()` as a replacement for the call sequence `comedi_find_board_minor()`, `comedi_free_board_minor()`. This is slightly safer as we can make sure nothing funny happens to the found `comedi_file_info_table[]` entry in the middle of the sequence. Change `comedi_auto_unconfig()` to call the new function instead of the old sequence. Remove `comedi_find_board_minor()` as it has no other callers. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: remove 'comedi_autoconfig' module parameterH Hartley Sweeten2013-02-051-1/+0
| | | | | | | | | | | | | | | This module parameter is used to enable the auto config mechanism in the comedi core. Most of the PCI, PCMCIA, and USB drivers have been converted to use the auto config mechanism and will not attach if it is disabled. Since the 'comedi_autoconfig' parameter is defaulted to true, just remove it so that the comedi drivers that use auto config will always be able to attach. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Cc: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: change comedi_alloc_subdevice_minor parametersIan Abbott2013-02-031-2/+1
| | | | | | | | | | | `comedi_alloc_subdevice_minor()` doesn't really need a parameter pointing to a `struct comedi_device` as it can get this information from the parameter pointing to a `struct comedi_subdevice`. Just pass the subdevice parameter. Signed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: move comedi_alloc_subdevice_minor declarationsIan Abbott2013-02-031-0/+3
| | | | | | | | | | Move the declarations of `comedi_alloc_subdevice_minor()` and `comedi_free_subdevice_minor()` from "comedidev.h" to "comedi_internal.h" since they are only of interest to the comedi core, and are not exported to the low-level comedi drivers. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: don't expose comedi_proc_{init,cleanup}H Hartley Sweeten2013-01-311-0/+15
| | | | | | | | | | These functions are only used by the comedi core. Move the prototypes to comedi_internal.h so they are not exposed to the comedi drivers. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Cc: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: don't expose comedi_device_{attach,detach}H Hartley Sweeten2013-01-311-2/+9
| | | | | | | | | | | | | These functions are only used by the comedi core. Move the prototypes to comedi_internal.h so they are not exposed to the comedi drivers. Tidy up comedi_internal.h a bit so that all the internal stuff in drivers.c is grouped. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Cc: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: comedi_buf: don't expose comedi_buf_write_n_allocated()H Hartley Sweeten2013-01-171-0/+1
| | | | | | | | | | | This helper function is only called by the comedi core in comedi_buf.c and comedi_fops.c. For aesthetic reasons, move it to comedi_buf.c and remove the inline. Move the prototype from comedidev.h to comedi_internal.h so it's not exposed outside the comedi core. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: comedi_buf: rename comedi_reset_async_buf()H Hartley Sweeten2013-01-171-1/+2
| | | | | | | | | For aesthetic reasons, rename this function to comedi_buf_reset(). This makes all the asynchronous buffer functions have the same namespace. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: remove comedi_fops.hIan Abbott2012-06-201-0/+4
| | | | | | | | | | | | | Move the contents of "comedi_fops.h" into "comedi_internal.h" and delete "comedi_fops.h". It only contains a couple of external variable declarations (and #include <linux/types.h>) and one of those isn't even declared in "comedi_fops.c". The other one is an external declaration of a variable used to store a module parameter and some of those are already externally declared in "comedi_internal.h", so they can keep it company! Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: comedi_internal.h inclusion guardsIan Abbott2012-06-201-0/+5
| | | | | | | Add a multiple inclusion guard macro to "comedi_internal.h". Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* staging: comedi: rename internal.h to comedi_internal.hIan Abbott2012-06-201-0/+16
Use a less generic name for this internal header file included by various parts of the comedi core. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
OpenPOWER on IntegriCloud