diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-09-22 19:54:53 (GMT) |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-09-22 20:01:40 (GMT) |
commit | ae19ffbadc1b2100285a5b5b3d0a4e0a11390904 (patch) | |
tree | 3c2086ab67398a019089a47ca3f362a4bc6db74f /drivers/staging/iio/ring_sw.h | |
parent | 34e84f39a27d059a3e6ec6e8b94aafa702e6f220 (diff) | |
parent | 9173a8ef24a6b1b8031507b35b8ffe5f85a87692 (diff) | |
download | linux-fsl-qoriq-ae19ffbadc1b2100285a5b5b3d0a4e0a11390904.tar.xz |
Merge branch 'master' into for-linus
Diffstat (limited to 'drivers/staging/iio/ring_sw.h')
-rw-r--r-- | drivers/staging/iio/ring_sw.h | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/drivers/staging/iio/ring_sw.h b/drivers/staging/iio/ring_sw.h new file mode 100644 index 0000000..ae70ee0 --- /dev/null +++ b/drivers/staging/iio/ring_sw.h @@ -0,0 +1,189 @@ +/* The industrial I/O simple minimally locked ring buffer. + * + * Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This code is deliberately kept separate from the main industrialio I/O core + * as it is intended that in the future a number of different software ring + * buffer implementations will exist with different characteristics to suit + * different applications. + * + * This particular one was designed for a data capture application where it was + * particularly important that no userspace reads would interrupt the capture + * process. To this end the ring is not locked during a read. + * + * Comments on this buffer design welcomed. It's far from efficient and some of + * my understanding of the effects of scheduling on this are somewhat limited. + * Frankly, to my mind, this is the current weak point in the industrial I/O + * patch set. + */ + +#ifndef _IIO_RING_SW_H_ +#define _IIO_RING_SW_H_ +/* NEEDS COMMENTS */ +/* The intention is that this should be a separate module from the iio core. + * This is a bit like supporting algorithms dependent on what the device + * driver requests - some may support multiple options */ + + +#include <linux/autoconf.h> +#include "iio.h" +#include "ring_generic.h" + +#if defined CONFIG_IIO_SW_RING || defined CONFIG_IIO_SW_RING_MODULE + +/** + * iio_create_sw_rb() software ring buffer allocation + * @r: pointer to ring buffer pointer + **/ +int iio_create_sw_rb(struct iio_ring_buffer **r); + +/** + * iio_init_sw_rb() initialize the software ring buffer + * @r: pointer to a software ring buffer created by an + * iio_create_sw_rb call. + **/ +int iio_init_sw_rb(struct iio_ring_buffer *r, struct iio_dev *indio_dev); +/** + * iio_exit_sw_rb() reverse what was done in iio_init_sw_rb + **/ +void iio_exit_sw_rb(struct iio_ring_buffer *r); + +/** + * iio_free_sw_rb() free memory occupied by the core ring buffer struct + **/ +void iio_free_sw_rb(struct iio_ring_buffer *r); + +/** + * iio_mark_sw_rb_in_use() reference counting to prevent incorrect chances + **/ +void iio_mark_sw_rb_in_use(struct iio_ring_buffer *r); + +/** + * iio_unmark_sw_rb_in_use() notify the ring buffer that we don't care anymore + **/ +void iio_unmark_sw_rb_in_use(struct iio_ring_buffer *r); + +/** + * iio_read_last_from_sw_rb() attempt to read the last stored datum from the rb + **/ +int iio_read_last_from_sw_rb(struct iio_ring_buffer *r, u8 *data); + +/** + * iio_store_to_sw_rb() store a new datum to the ring buffer + * @rb: pointer to ring buffer instance + * @data: the datum to be stored including timestamp if relevant. + * @timestamp: timestamp which will be attached to buffer events if relevant. + **/ +int iio_store_to_sw_rb(struct iio_ring_buffer *r, u8 *data, s64 timestamp); + +/** + * iio_rip_sw_rb() attempt to read data from the ring buffer + * @r: ring buffer instance + * @count: number of datum's to try and read + * @data: where the data will be stored. + * @dead_offset: how much of the stored data was possibly invalidated by + * the end of the copy. + **/ +int iio_rip_sw_rb(struct iio_ring_buffer *r, + size_t count, + u8 **data, + int *dead_offset); + +/** + * iio_request_update_sw_rb() update params if update needed + **/ +int iio_request_update_sw_rb(struct iio_ring_buffer *r); + +/** + * iio_mark_update_needed_sw_rb() tell the ring buffer it needs a param update + **/ +int iio_mark_update_needed_sw_rb(struct iio_ring_buffer *r); + + +/** + * iio_get_bpd_sw_rb() get the datum size in bytes + **/ +int iio_get_bpd_sw_rb(struct iio_ring_buffer *r); + +/** + * iio_set_bpd_sw_rb() set the datum size in bytes + **/ +int iio_set_bpd_sw_rb(struct iio_ring_buffer *r, size_t bpd); + +/** + * iio_get_length_sw_rb() get how many datums the rb may contain + **/ +int iio_get_length_sw_rb(struct iio_ring_buffer *r); + +/** + * iio_set_length_sw_rb() set how many datums the rb may contain + **/ +int iio_set_length_sw_rb(struct iio_ring_buffer *r, int length); + +/** + * iio_ring_sw_register_funcs() helper function to set up rb access + **/ +static inline void iio_ring_sw_register_funcs(struct iio_ring_access_funcs *ra) +{ + ra->mark_in_use = &iio_mark_sw_rb_in_use; + ra->unmark_in_use = &iio_unmark_sw_rb_in_use; + + ra->store_to = &iio_store_to_sw_rb; + ra->read_last = &iio_read_last_from_sw_rb; + ra->rip_lots = &iio_rip_sw_rb; + + ra->mark_param_change = &iio_mark_update_needed_sw_rb; + ra->request_update = &iio_request_update_sw_rb; + + ra->get_bpd = &iio_get_bpd_sw_rb; + ra->set_bpd = &iio_set_bpd_sw_rb; + + ra->get_length = &iio_get_length_sw_rb; + ra->set_length = &iio_set_length_sw_rb; +}; + +/** + * struct iio_sw_ring_buffer - software ring buffer + * @buf: generic ring buffer elements + * @data: the ring buffer memory + * @read_p: read pointer (oldest available) + * @write_p: write pointer + * @last_written_p: read pointer (newest available) + * @half_p: half buffer length behind write_p (event generation) + * @use_count: reference count to prevent resizing when in use + * @update_needed: flag to indicated change in size requested + * @use_lock: lock to prevent change in size when in use + * + * Note that the first element of all ring buffers must be a + * struct iio_ring_buffer. +**/ + +struct iio_sw_ring_buffer { + struct iio_ring_buffer buf; + unsigned char *data; + unsigned char *read_p; + unsigned char *write_p; + unsigned char *last_written_p; + /* used to act as a point at which to signal an event */ + unsigned char *half_p; + int use_count; + int update_needed; + spinlock_t use_lock; +}; + +#define iio_to_sw_ring(r) container_of(r, struct iio_sw_ring_buffer, buf) + +struct iio_ring_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev); +void iio_sw_rb_free(struct iio_ring_buffer *ring); + + + +#else /* CONFIG_IIO_RING_BUFFER*/ +static inline void iio_ring_sw_register_funcs(struct iio_ring_access_funcs *ra) +{}; +#endif /* !CONFIG_IIO_RING_BUFFER */ +#endif /* _IIO_RING_SW_H_ */ |