diff options
Diffstat (limited to 'drivers/staging/iio/ring_sw.c')
-rw-r--r-- | drivers/staging/iio/ring_sw.c | 151 |
1 files changed, 33 insertions, 118 deletions
diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c index 66a34ad..3e24ec4 100644 --- a/drivers/staging/iio/ring_sw.c +++ b/drivers/staging/iio/ring_sw.c @@ -23,11 +23,8 @@ * @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_buffer. @@ -37,12 +34,9 @@ struct iio_sw_ring_buffer { 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) @@ -56,38 +50,15 @@ static inline int __iio_allocate_sw_ring_buffer(struct iio_sw_ring_buffer *ring, ring->data = kmalloc(length*ring->buf.bytes_per_datum, GFP_ATOMIC); ring->read_p = NULL; ring->write_p = NULL; - ring->last_written_p = NULL; ring->half_p = NULL; return ring->data ? 0 : -ENOMEM; } -static inline void __iio_init_sw_ring_buffer(struct iio_sw_ring_buffer *ring) -{ - spin_lock_init(&ring->use_lock); -} - static inline void __iio_free_sw_ring_buffer(struct iio_sw_ring_buffer *ring) { kfree(ring->data); } -static void iio_mark_sw_rb_in_use(struct iio_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); -} - -static void iio_unmark_sw_rb_in_use(struct iio_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); -} - - /* Ring buffer related functionality */ /* Store to ring is typically called in the bh of a data ready interrupt handler * in the device driver */ @@ -115,7 +86,6 @@ static int iio_store_to_sw_ring(struct iio_sw_ring_buffer *ring, * Always valid as either points to latest or second latest value. * Before this runs it is null and read attempts fail with -EAGAIN. */ - ring->last_written_p = ring->write_p; barrier(); /* temp_ptr used to ensure we never have an invalid pointer * it may be slightly lagging, but never invalid @@ -174,6 +144,7 @@ static int iio_read_first_n_sw_rb(struct iio_buffer *r, u8 *initial_read_p, *initial_write_p, *current_read_p, *end_read_p; u8 *data; int ret, max_copied, bytes_to_rip, dead_offset; + size_t data_available, buffer_size; /* A userspace program has probably made an error if it tries to * read something that is not a whole number of bpds. @@ -186,9 +157,11 @@ static int iio_read_first_n_sw_rb(struct iio_buffer *r, n, ring->buf.bytes_per_datum); goto error_ret; } + + buffer_size = ring->buf.bytes_per_datum*ring->buf.length; + /* Limit size to whole of ring buffer */ - bytes_to_rip = min((size_t)(ring->buf.bytes_per_datum*ring->buf.length), - n); + bytes_to_rip = min_t(size_t, buffer_size, n); data = kmalloc(bytes_to_rip, GFP_KERNEL); if (data == NULL) { @@ -217,38 +190,24 @@ static int iio_read_first_n_sw_rb(struct iio_buffer *r, goto error_free_data_cpy; } - if (initial_write_p >= initial_read_p + bytes_to_rip) { - /* write_p is greater than necessary, all is easy */ - max_copied = bytes_to_rip; - memcpy(data, initial_read_p, max_copied); - end_read_p = initial_read_p + max_copied; - } else if (initial_write_p > initial_read_p) { - /*not enough data to cpy */ - max_copied = initial_write_p - initial_read_p; + if (initial_write_p >= initial_read_p) + data_available = initial_write_p - initial_read_p; + else + data_available = buffer_size - (initial_read_p - initial_write_p); + + if (data_available < bytes_to_rip) + bytes_to_rip = data_available; + + if (initial_read_p + bytes_to_rip >= ring->data + buffer_size) { + max_copied = ring->data + buffer_size - initial_read_p; memcpy(data, initial_read_p, max_copied); - end_read_p = initial_write_p; + memcpy(data + max_copied, ring->data, bytes_to_rip - max_copied); + end_read_p = ring->data + bytes_to_rip - max_copied; } else { - /* going through 'end' of ring buffer */ - max_copied = ring->data - + ring->buf.length*ring->buf.bytes_per_datum - initial_read_p; - memcpy(data, initial_read_p, max_copied); - /* possible we are done if we align precisely with end */ - if (max_copied == bytes_to_rip) - end_read_p = ring->data; - else if (initial_write_p - > ring->data + bytes_to_rip - max_copied) { - /* enough data to finish */ - memcpy(data + max_copied, ring->data, - bytes_to_rip - max_copied); - max_copied = bytes_to_rip; - end_read_p = ring->data + (bytes_to_rip - max_copied); - } else { /* not enough data */ - memcpy(data + max_copied, ring->data, - initial_write_p - ring->data); - max_copied += initial_write_p - ring->data; - end_read_p = initial_write_p; - } + memcpy(data, initial_read_p, bytes_to_rip); + end_read_p = initial_read_p + bytes_to_rip; } + /* Now to verify which section was cleanly copied - i.e. how far * read pointer has been pushed */ current_read_p = ring->read_p; @@ -256,15 +215,14 @@ static int iio_read_first_n_sw_rb(struct iio_buffer *r, if (initial_read_p <= current_read_p) dead_offset = current_read_p - initial_read_p; else - dead_offset = ring->buf.length*ring->buf.bytes_per_datum - - (initial_read_p - current_read_p); + dead_offset = buffer_size - (initial_read_p - current_read_p); /* possible issue if the initial write has been lapped or indeed * the point we were reading to has been passed */ /* No valid data read. * In this case the read pointer is already correct having been * pushed further than we would look. */ - if (max_copied - dead_offset < 0) { + if (bytes_to_rip - dead_offset < 0) { ret = 0; goto error_free_data_cpy; } @@ -280,7 +238,7 @@ static int iio_read_first_n_sw_rb(struct iio_buffer *r, while (ring->read_p != end_read_p) ring->read_p = end_read_p; - ret = max_copied - dead_offset; + ret = bytes_to_rip - dead_offset; if (copy_to_user(buf, data + dead_offset, ret)) { ret = -EFAULT; @@ -305,52 +263,18 @@ static int iio_store_to_sw_rb(struct iio_buffer *r, return iio_store_to_sw_ring(ring, data, timestamp); } -static int iio_read_last_from_sw_ring(struct iio_sw_ring_buffer *ring, - unsigned char *data) -{ - unsigned char *last_written_p_copy; - - iio_mark_sw_rb_in_use(&ring->buf); -again: - barrier(); - last_written_p_copy = ring->last_written_p; - barrier(); /*unnessecary? */ - /* Check there is anything here */ - if (last_written_p_copy == NULL) - return -EAGAIN; - memcpy(data, last_written_p_copy, ring->buf.bytes_per_datum); - - if (unlikely(ring->last_written_p != last_written_p_copy)) - goto again; - - iio_unmark_sw_rb_in_use(&ring->buf); - return 0; -} - -static int iio_read_last_from_sw_rb(struct iio_buffer *r, - unsigned char *data) -{ - return iio_read_last_from_sw_ring(iio_to_sw_ring(r), data); -} - static int iio_request_update_sw_rb(struct iio_buffer *r) { int ret = 0; struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); r->stufftoread = false; - spin_lock(&ring->use_lock); if (!ring->update_needed) goto error_ret; - if (ring->use_count) { - ret = -EAGAIN; - goto error_ret; - } __iio_free_sw_ring_buffer(ring); ret = __iio_allocate_sw_ring_buffer(ring, ring->buf.bytes_per_datum, ring->buf.length); error_ret: - spin_unlock(&ring->use_lock); return ret; } @@ -360,12 +284,18 @@ static int iio_get_bytes_per_datum_sw_rb(struct iio_buffer *r) return ring->buf.bytes_per_datum; } +static int iio_mark_update_needed_sw_rb(struct iio_buffer *r) +{ + struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); + ring->update_needed = true; + return 0; +} + static int iio_set_bytes_per_datum_sw_rb(struct iio_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); + iio_mark_update_needed_sw_rb(r); } return 0; } @@ -379,27 +309,17 @@ static int iio_set_length_sw_rb(struct iio_buffer *r, int length) { if (r->length != length) { r->length = length; - if (r->access->mark_param_change) - r->access->mark_param_change(r); + iio_mark_update_needed_sw_rb(r); } return 0; } -static int iio_mark_update_needed_sw_rb(struct iio_buffer *r) -{ - struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); - ring->update_needed = true; - return 0; -} - static IIO_BUFFER_ENABLE_ATTR; -static IIO_BUFFER_BYTES_PER_DATUM_ATTR; static IIO_BUFFER_LENGTH_ATTR; /* Standard set of ring buffer attributes */ static struct attribute *iio_ring_attributes[] = { &dev_attr_length.attr, - &dev_attr_bytes_per_datum.attr, &dev_attr_enable.attr, NULL, }; @@ -419,8 +339,7 @@ struct iio_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev) return NULL; ring->update_needed = true; buf = &ring->buf; - iio_buffer_init(buf, indio_dev); - __iio_init_sw_ring_buffer(ring); + iio_buffer_init(buf); buf->attrs = &iio_ring_attribute_group; return buf; @@ -434,12 +353,8 @@ void iio_sw_rb_free(struct iio_buffer *r) EXPORT_SYMBOL(iio_sw_rb_free); const struct iio_buffer_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, |