diff options
Diffstat (limited to 'drivers/staging/iio/ring_sw.c')
-rw-r--r-- | drivers/staging/iio/ring_sw.c | 120 |
1 files changed, 66 insertions, 54 deletions
diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c index d55757b..35896cbb 100644 --- a/drivers/staging/iio/ring_sw.c +++ b/drivers/staging/iio/ring_sw.c @@ -17,6 +17,36 @@ #include "ring_sw.h" #include "trigger.h" +/** + * 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) + static inline int __iio_allocate_sw_ring_buffer(struct iio_sw_ring_buffer *ring, int bytes_per_datum, int length) { @@ -41,23 +71,21 @@ static inline void __iio_free_sw_ring_buffer(struct iio_sw_ring_buffer *ring) kfree(ring->data); } -void iio_mark_sw_rb_in_use(struct iio_ring_buffer *r) +static void iio_mark_sw_rb_in_use(struct iio_ring_buffer *r) { struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); spin_lock(&ring->use_lock); ring->use_count++; spin_unlock(&ring->use_lock); } -EXPORT_SYMBOL(iio_mark_sw_rb_in_use); -void iio_unmark_sw_rb_in_use(struct iio_ring_buffer *r) +static void iio_unmark_sw_rb_in_use(struct iio_ring_buffer *r) { struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); spin_lock(&ring->use_lock); ring->use_count--; spin_unlock(&ring->use_lock); } -EXPORT_SYMBOL(iio_unmark_sw_rb_in_use); /* Ring buffer related functionality */ @@ -138,8 +166,8 @@ static int iio_store_to_sw_ring(struct iio_sw_ring_buffer *ring, return ret; } -int iio_read_first_n_sw_rb(struct iio_ring_buffer *r, - size_t n, char __user *buf) +static int iio_read_first_n_sw_rb(struct iio_ring_buffer *r, + size_t n, char __user *buf) { struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); @@ -268,14 +296,14 @@ error_ret: return ret; } -EXPORT_SYMBOL(iio_read_first_n_sw_rb); -int iio_store_to_sw_rb(struct iio_ring_buffer *r, u8 *data, s64 timestamp) +static int iio_store_to_sw_rb(struct iio_ring_buffer *r, + u8 *data, + s64 timestamp) { struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); return iio_store_to_sw_ring(ring, data, timestamp); } -EXPORT_SYMBOL(iio_store_to_sw_rb); static int iio_read_last_from_sw_ring(struct iio_sw_ring_buffer *ring, unsigned char *data) @@ -299,14 +327,13 @@ again: return 0; } -int iio_read_last_from_sw_rb(struct iio_ring_buffer *r, +static int iio_read_last_from_sw_rb(struct iio_ring_buffer *r, unsigned char *data) { return iio_read_last_from_sw_ring(iio_to_sw_ring(r), data); } -EXPORT_SYMBOL(iio_read_last_from_sw_rb); -int iio_request_update_sw_rb(struct iio_ring_buffer *r) +static int iio_request_update_sw_rb(struct iio_ring_buffer *r) { int ret = 0; struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); @@ -326,50 +353,44 @@ error_ret: spin_unlock(&ring->use_lock); return ret; } -EXPORT_SYMBOL(iio_request_update_sw_rb); -int iio_get_bytes_per_datum_sw_rb(struct iio_ring_buffer *r) +static int iio_get_bytes_per_datum_sw_rb(struct iio_ring_buffer *r) { struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); return ring->buf.bytes_per_datum; } -EXPORT_SYMBOL(iio_get_bytes_per_datum_sw_rb); -int iio_set_bytes_per_datum_sw_rb(struct iio_ring_buffer *r, size_t bpd) +static int iio_set_bytes_per_datum_sw_rb(struct iio_ring_buffer *r, size_t bpd) { if (r->bytes_per_datum != bpd) { r->bytes_per_datum = bpd; - if (r->access.mark_param_change) - r->access.mark_param_change(r); + if (r->access->mark_param_change) + r->access->mark_param_change(r); } return 0; } -EXPORT_SYMBOL(iio_set_bytes_per_datum_sw_rb); -int iio_get_length_sw_rb(struct iio_ring_buffer *r) +static int iio_get_length_sw_rb(struct iio_ring_buffer *r) { return r->length; } -EXPORT_SYMBOL(iio_get_length_sw_rb); -int iio_set_length_sw_rb(struct iio_ring_buffer *r, int length) +static int iio_set_length_sw_rb(struct iio_ring_buffer *r, int length) { if (r->length != length) { r->length = length; - if (r->access.mark_param_change) - r->access.mark_param_change(r); + if (r->access->mark_param_change) + r->access->mark_param_change(r); } return 0; } -EXPORT_SYMBOL(iio_set_length_sw_rb); -int iio_mark_update_needed_sw_rb(struct iio_ring_buffer *r) +static int iio_mark_update_needed_sw_rb(struct iio_ring_buffer *r) { struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); ring->update_needed = true; return 0; } -EXPORT_SYMBOL(iio_mark_update_needed_sw_rb); static void iio_sw_rb_release(struct device *dev) { @@ -412,6 +433,7 @@ struct iio_ring_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev) ring = kzalloc(sizeof *ring, GFP_KERNEL); if (!ring) return NULL; + ring->update_needed = true; buf = &ring->buf; iio_ring_buffer_init(buf, indio_dev); __iio_init_sw_ring_buffer(ring); @@ -430,36 +452,11 @@ void iio_sw_rb_free(struct iio_ring_buffer *r) } EXPORT_SYMBOL(iio_sw_rb_free); -int iio_sw_ring_preenable(struct iio_dev *indio_dev) -{ - struct iio_ring_buffer *ring = indio_dev->ring; - size_t size; - dev_dbg(&indio_dev->dev, "%s\n", __func__); - /* Check if there are any scan elements enabled, if not fail*/ - if (!(ring->scan_count || ring->scan_timestamp)) - return -EINVAL; - if (ring->scan_timestamp) - if (ring->scan_count) - /* Timestamp (aligned to s64) and data */ - size = (((ring->scan_count * ring->bpe) - + sizeof(s64) - 1) - & ~(sizeof(s64) - 1)) - + sizeof(s64); - else /* Timestamp only */ - size = sizeof(s64); - else /* Data only */ - size = ring->scan_count * ring->bpe; - ring->access.set_bytes_per_datum(ring, size); - - return 0; -} -EXPORT_SYMBOL(iio_sw_ring_preenable); - void iio_sw_trigger_to_ring(struct iio_sw_ring_helper_state *st) { struct iio_ring_buffer *ring = st->indio_dev->ring; int len = 0; - size_t datasize = ring->access.get_bytes_per_datum(ring); + size_t datasize = ring->access->get_bytes_per_datum(ring); char *data = kmalloc(datasize, GFP_KERNEL); if (data == NULL) { @@ -476,7 +473,7 @@ void iio_sw_trigger_to_ring(struct iio_sw_ring_helper_state *st) *(s64 *)(((phys_addr_t)data + len + sizeof(s64) - 1) & ~(sizeof(s64) - 1)) = st->last_timestamp; - ring->access.store_to(ring, + ring->access->store_to(ring, (u8 *)data, st->last_timestamp); @@ -504,5 +501,20 @@ void iio_sw_poll_func_th(struct iio_dev *indio_dev, s64 time) } EXPORT_SYMBOL(iio_sw_poll_func_th); +const struct iio_ring_access_funcs ring_sw_access_funcs = { + .mark_in_use = &iio_mark_sw_rb_in_use, + .unmark_in_use = &iio_unmark_sw_rb_in_use, + .store_to = &iio_store_to_sw_rb, + .read_last = &iio_read_last_from_sw_rb, + .read_first_n = &iio_read_first_n_sw_rb, + .mark_param_change = &iio_mark_update_needed_sw_rb, + .request_update = &iio_request_update_sw_rb, + .get_bytes_per_datum = &iio_get_bytes_per_datum_sw_rb, + .set_bytes_per_datum = &iio_set_bytes_per_datum_sw_rb, + .get_length = &iio_get_length_sw_rb, + .set_length = &iio_set_length_sw_rb, +}; +EXPORT_SYMBOL(ring_sw_access_funcs); + MODULE_DESCRIPTION("Industrialio I/O software ring buffer"); MODULE_LICENSE("GPL"); |