diff --git a/drivers/staging/iio/industrialio-ring.c b/drivers/staging/iio/industrialio-ring.c index 9a98fcdbe109..bd4373ae066b 100644 --- a/drivers/staging/iio/industrialio-ring.c +++ b/drivers/staging/iio/industrialio-ring.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -98,31 +97,13 @@ static ssize_t iio_ring_rip_outer(struct file *filp, char __user *buf, size_t count, loff_t *f_ps) { struct iio_ring_buffer *rb = filp->private_data; - int ret, dead_offset, copied; - u8 *data; + int ret, dead_offset; + /* rip lots must exist. */ if (!rb->access.rip_lots) return -EINVAL; - copied = rb->access.rip_lots(rb, count, &data, &dead_offset); + ret = rb->access.rip_lots(rb, count, buf, &dead_offset); - if (copied <= 0) { - ret = copied; - goto error_ret; - } - if (copy_to_user(buf, data + dead_offset, copied)) { - ret = -EFAULT; - goto error_free_data_cpy; - } - /* In clever ring buffer designs this may not need to be freed. - * When such a design exists I'll add this to ring access funcs. - */ - kfree(data); - - return copied; - -error_free_data_cpy: - kfree(data); -error_ret: return ret; } diff --git a/drivers/staging/iio/ring_generic.h b/drivers/staging/iio/ring_generic.h index 8ecb1895cec2..f21ac09373cf 100644 --- a/drivers/staging/iio/ring_generic.h +++ b/drivers/staging/iio/ring_generic.h @@ -73,7 +73,7 @@ struct iio_ring_access_funcs { int (*read_last)(struct iio_ring_buffer *ring, u8 *data); int (*rip_lots)(struct iio_ring_buffer *ring, size_t count, - u8 **data, + char __user *buf, int *dead_offset); int (*mark_param_change)(struct iio_ring_buffer *ring); diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c index 52624ace0bc5..b71ce3900649 100644 --- a/drivers/staging/iio/ring_sw.c +++ b/drivers/staging/iio/ring_sw.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "ring_sw.h" #include "trigger.h" @@ -152,11 +153,12 @@ error_ret: } int iio_rip_sw_rb(struct iio_ring_buffer *r, - size_t count, u8 **data, int *dead_offset) + size_t count, char __user *buf, int *dead_offset) { struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r); u8 *initial_read_p, *initial_write_p, *current_read_p, *end_read_p; + u8 *data; int ret, max_copied; int bytes_to_rip; @@ -174,8 +176,8 @@ int iio_rip_sw_rb(struct iio_ring_buffer *r, /* Limit size to whole of ring buffer */ bytes_to_rip = min((size_t)(ring->buf.bytes_per_datum*ring->buf.length), count); - *data = kmalloc(bytes_to_rip, GFP_KERNEL); - if (*data == NULL) { + data = kmalloc(bytes_to_rip, GFP_KERNEL); + if (data == NULL) { ret = -ENOMEM; goto error_ret; } @@ -204,30 +206,30 @@ int iio_rip_sw_rb(struct iio_ring_buffer *r, 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); + 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; - memcpy(*data, initial_read_p, max_copied); + memcpy(data, initial_read_p, max_copied); end_read_p = initial_write_p; } 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); + 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, + 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, + memcpy(data + max_copied, ring->data, initial_write_p - ring->data); max_copied += initial_write_p - ring->data; end_read_p = initial_write_p; @@ -264,11 +266,16 @@ int iio_rip_sw_rb(struct iio_ring_buffer *r, while (ring->read_p != end_read_p) ring->read_p = end_read_p; - return max_copied - *dead_offset; + ret = max_copied - *dead_offset; + if (copy_to_user(buf, data + *dead_offset, ret)) { + ret = -EFAULT; + goto error_free_data_cpy; + } error_free_data_cpy: - kfree(*data); + kfree(data); error_ret: + return ret; } EXPORT_SYMBOL(iio_rip_sw_rb); diff --git a/drivers/staging/iio/ring_sw.h b/drivers/staging/iio/ring_sw.h index ad03d832c1b9..13341c1e35f2 100644 --- a/drivers/staging/iio/ring_sw.h +++ b/drivers/staging/iio/ring_sw.h @@ -96,13 +96,13 @@ 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. + * @buf: userspace buffer into which data is copied * @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, + char __user *buf, int *dead_offset); /**