// SPDX-License-Identifier: GPL-2.0+ /* * comedi_buf.c * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef <[email protected]> * Copyright (C) 2002 Frank Mori Hess <[email protected]> */ #include <linux/vmalloc.h> #include <linux/slab.h> #include <linux/comedi/comedidev.h> #include "comedi_internal.h" #ifdef PAGE_KERNEL_NOCACHE #define COMEDI_PAGE_PROTECTION … #else #define COMEDI_PAGE_PROTECTION … #endif static void comedi_buf_map_kref_release(struct kref *kref) { … } static void __comedi_buf_free(struct comedi_device *dev, struct comedi_subdevice *s) { … } static struct comedi_buf_map * comedi_buf_map_alloc(struct comedi_device *dev, enum dma_data_direction dma_dir, unsigned int n_pages) { … } static void __comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int n_pages) { … } void comedi_buf_map_get(struct comedi_buf_map *bm) { … } int comedi_buf_map_put(struct comedi_buf_map *bm) { … } /* helper for "access" vm operation */ int comedi_buf_map_access(struct comedi_buf_map *bm, unsigned long offset, void *buf, int len, int write) { … } /* returns s->async->buf_map and increments its kref refcount */ struct comedi_buf_map * comedi_buf_map_from_subdev_get(struct comedi_subdevice *s) { … } bool comedi_buf_is_mmapped(struct comedi_subdevice *s) { … } int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size) { … } void comedi_buf_reset(struct comedi_subdevice *s) { … } static unsigned int comedi_buf_write_n_unalloc(struct comedi_subdevice *s) { … } unsigned int comedi_buf_write_n_available(struct comedi_subdevice *s) { … } /** * comedi_buf_write_alloc() - Reserve buffer space for writing * @s: COMEDI subdevice. * @nbytes: Maximum space to reserve in bytes. * * Reserve up to @nbytes bytes of space to be written in the COMEDI acquisition * data buffer associated with the subdevice. The amount reserved is limited * by the space available. * * Return: The amount of space reserved in bytes. */ unsigned int comedi_buf_write_alloc(struct comedi_subdevice *s, unsigned int nbytes) { … } EXPORT_SYMBOL_GPL(…); /* * munging is applied to data by core as it passes between user * and kernel space */ static unsigned int comedi_buf_munge(struct comedi_subdevice *s, unsigned int num_bytes) { … } unsigned int comedi_buf_write_n_allocated(struct comedi_subdevice *s) { … } /** * comedi_buf_write_free() - Free buffer space after it is written * @s: COMEDI subdevice. * @nbytes: Maximum space to free in bytes. * * Free up to @nbytes bytes of space previously reserved for writing in the * COMEDI acquisition data buffer associated with the subdevice. The amount of * space freed is limited to the amount that was reserved. The freed space is * assumed to have been filled with sample data by the writer. * * If the samples in the freed space need to be "munged", do so here. The * freed space becomes available for allocation by the reader. * * Return: The amount of space freed in bytes. */ unsigned int comedi_buf_write_free(struct comedi_subdevice *s, unsigned int nbytes) { … } EXPORT_SYMBOL_GPL(…); /** * comedi_buf_read_n_available() - Determine amount of readable buffer space * @s: COMEDI subdevice. * * Determine the amount of readable buffer space in the COMEDI acquisition data * buffer associated with the subdevice. The readable buffer space is that * which has been freed by the writer and "munged" to the sample data format * expected by COMEDI if necessary. * * Return: The amount of readable buffer space. */ unsigned int comedi_buf_read_n_available(struct comedi_subdevice *s) { … } EXPORT_SYMBOL_GPL(…); /** * comedi_buf_read_alloc() - Reserve buffer space for reading * @s: COMEDI subdevice. * @nbytes: Maximum space to reserve in bytes. * * Reserve up to @nbytes bytes of previously written and "munged" buffer space * for reading in the COMEDI acquisition data buffer associated with the * subdevice. The amount reserved is limited to the space available. The * reader can read from the reserved space and then free it. A reader is also * allowed to read from the space before reserving it as long as it determines * the amount of readable data available, but the space needs to be marked as * reserved before it can be freed. * * Return: The amount of space reserved in bytes. */ unsigned int comedi_buf_read_alloc(struct comedi_subdevice *s, unsigned int nbytes) { … } EXPORT_SYMBOL_GPL(…); static unsigned int comedi_buf_read_n_allocated(struct comedi_async *async) { … } /** * comedi_buf_read_free() - Free buffer space after it has been read * @s: COMEDI subdevice. * @nbytes: Maximum space to free in bytes. * * Free up to @nbytes bytes of buffer space previously reserved for reading in * the COMEDI acquisition data buffer associated with the subdevice. The * amount of space freed is limited to the amount that was reserved. * * The freed space becomes available for allocation by the writer. * * Return: The amount of space freed in bytes. */ unsigned int comedi_buf_read_free(struct comedi_subdevice *s, unsigned int nbytes) { … } EXPORT_SYMBOL_GPL(…); static void comedi_buf_memcpy_to(struct comedi_subdevice *s, const void *data, unsigned int num_bytes) { … } static void comedi_buf_memcpy_from(struct comedi_subdevice *s, void *dest, unsigned int nbytes) { … } /** * comedi_buf_write_samples() - Write sample data to COMEDI buffer * @s: COMEDI subdevice. * @data: Pointer to source samples. * @nsamples: Number of samples to write. * * Write up to @nsamples samples to the COMEDI acquisition data buffer * associated with the subdevice, mark it as written and update the * acquisition scan progress. If there is not enough room for the specified * number of samples, the number of samples written is limited to the number * that will fit and the %COMEDI_CB_OVERFLOW event flag is set to cause the * acquisition to terminate with an overrun error. Set the %COMEDI_CB_BLOCK * event flag if any samples are written to cause waiting tasks to be woken * when the event flags are processed. * * Return: The amount of data written in bytes. */ unsigned int comedi_buf_write_samples(struct comedi_subdevice *s, const void *data, unsigned int nsamples) { … } EXPORT_SYMBOL_GPL(…); /** * comedi_buf_read_samples() - Read sample data from COMEDI buffer * @s: COMEDI subdevice. * @data: Pointer to destination. * @nsamples: Maximum number of samples to read. * * Read up to @nsamples samples from the COMEDI acquisition data buffer * associated with the subdevice, mark it as read and update the acquisition * scan progress. Limit the number of samples read to the number available. * Set the %COMEDI_CB_BLOCK event flag if any samples are read to cause waiting * tasks to be woken when the event flags are processed. * * Return: The amount of data read in bytes. */ unsigned int comedi_buf_read_samples(struct comedi_subdevice *s, void *data, unsigned int nsamples) { … } EXPORT_SYMBOL_GPL(…);