summaryrefslogtreecommitdiffstats
path: root/qcwcn/wifi_hal/ring_buffer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qcwcn/wifi_hal/ring_buffer.cpp')
-rw-r--r--qcwcn/wifi_hal/ring_buffer.cpp154
1 files changed, 124 insertions, 30 deletions
diff --git a/qcwcn/wifi_hal/ring_buffer.cpp b/qcwcn/wifi_hal/ring_buffer.cpp
index 771de1a..f346b2d 100644
--- a/qcwcn/wifi_hal/ring_buffer.cpp
+++ b/qcwcn/wifi_hal/ring_buffer.cpp
@@ -46,12 +46,18 @@ enum rb_bool {
RB_FALSE = 1
};
+typedef struct rb_entry_s {
+ u8 *data;
+ unsigned int last_wr_index;
+ u8 full;
+} rb_entry_t;
+
typedef struct ring_buf_cb {
unsigned int rd_buf_no; // Current buffer number to be read from
unsigned int wr_buf_no; // Current buffer number to be written into
unsigned int cur_rd_buf_idx; // Read index within the current read buffer
unsigned int cur_wr_buf_idx; // Write index within the current write buffer
- u8 **bufs; // Array of buffer pointers
+ rb_entry_t *bufs; // Array of buffer pointers
unsigned int max_num_bufs; // Maximum number of buffers that should be used
size_t each_buf_size; // Size of each buffer in bytes
@@ -102,13 +108,13 @@ void * ring_buffer_init(size_t size_of_buf, int num_bufs)
}
memset(rbc, 0, sizeof(struct ring_buf_cb));
- rbc->bufs = (u8 **)malloc(num_bufs * sizeof(void *));
+ rbc->bufs = (rb_entry_t *)malloc(num_bufs * sizeof(rb_entry_t));
if (rbc->bufs == NULL) {
free(rbc);
ALOGE("Failed to alloc rbc->bufs");
return NULL;
}
- memset(rbc->bufs, 0, (num_bufs * sizeof(void *)));
+ memset(rbc->bufs, 0, (num_bufs * sizeof(rb_entry_t)));
rbc->each_buf_size = size_of_buf;
rbc->max_num_bufs = num_bufs;
@@ -134,13 +140,18 @@ void ring_buffer_deinit(void *ctx)
// TODO handle the lock destroy failure
}
for (buf_no = 0; buf_no < rbc->max_num_bufs; buf_no++) {
- free(rbc->bufs[buf_no]);
+ free(rbc->bufs[buf_no].data);
}
free(rbc->bufs);
free(rbc);
}
-enum rb_status rb_write (void *ctx, u8 *buf, size_t length, int overwrite)
+/*
+ * record_length : 0 - byte boundary
+ * : >0 - Ensures to write record_length no.of bytes to the same buffer.
+ */
+enum rb_status rb_write (void *ctx, u8 *buf, size_t length, int overwrite,
+ size_t record_length)
{
rbc_t *rbc = (rbc_t *)ctx;
unsigned int bytes_written = 0; // bytes written into rb so far
@@ -148,24 +159,81 @@ enum rb_status rb_write (void *ctx, u8 *buf, size_t length, int overwrite)
// write in current buffer
unsigned int total_push_in_rd_ptr = 0; // Total amount of push in read pointer in this write
- /* Check if this write fits into remaining ring buffer */
- if ((overwrite == 0) &&
- (length >
- ((rbc->max_num_bufs * rbc->each_buf_size) - rbc->cur_valid_bytes))) {
+ if (record_length > rbc->each_buf_size) {
return RB_FAILURE;
}
+ if (overwrite == 0) {
+ /* Check if the complete RB is full. If the current wr_buf is also
+ * full, it indicates that the complete RB is full
+ */
+ if (rbc->bufs[rbc->wr_buf_no].full == 1)
+ return RB_FULL;
+ /* Check whether record fits in current buffer */
+ if (rbc->wr_buf_no == rbc->rd_buf_no) {
+ if ((rbc->cur_wr_buf_idx == rbc->cur_rd_buf_idx) &&
+ rbc->cur_valid_bytes) {
+ return RB_FULL;
+ } else if (rbc->cur_wr_buf_idx < rbc->cur_rd_buf_idx) {
+ if (record_length >
+ (rbc->cur_rd_buf_idx - rbc->cur_wr_buf_idx)) {
+ return RB_FULL;
+ }
+ } else {
+ if (record_length > (rbc->each_buf_size - rbc->cur_wr_buf_idx)) {
+ /* Check if the next buffer is not full to write this record into
+ * next buffer
+ */
+ unsigned int next_buf_no = rbc->wr_buf_no + 1;
+
+ if (next_buf_no >= rbc->max_num_bufs) {
+ next_buf_no = 0;
+ }
+ if (rbc->bufs[next_buf_no].full == 1) {
+ return RB_FULL;
+ }
+ }
+ }
+ } else if (record_length > (rbc->each_buf_size - rbc->cur_wr_buf_idx)) {
+ /* Check if the next buffer is not full to write this record into
+ * next buffer
+ */
+ unsigned int next_buf_no = rbc->wr_buf_no + 1;
+
+ if (next_buf_no >= rbc->max_num_bufs) {
+ next_buf_no = 0;
+ }
+ if (rbc->bufs[next_buf_no].full == 1) {
+ return RB_FULL;
+ }
+ }
+ }
+
+ /* Go to next buffer if the current buffer is not enough to write the
+ * complete record
+ */
+ if (record_length > (rbc->each_buf_size - rbc->cur_wr_buf_idx)) {
+ rbc->bufs[rbc->wr_buf_no].full = 1;
+ rbc->bufs[rbc->wr_buf_no].last_wr_index = rbc->cur_wr_buf_idx;
+ rbc->wr_buf_no++;
+ if (rbc->wr_buf_no == rbc->max_num_bufs) {
+ rbc->wr_buf_no = 0;
+ }
+ rbc->cur_wr_buf_idx = 0;
+ }
+
+
/* In each iteration of below loop, the data that can be fit into
* buffer @wr_buf_no will be copied from input buf */
while (bytes_written < length) {
unsigned int cur_copy_len;
/* Allocate a buffer if no buf available @ wr_buf_no */
- if (rbc->bufs[rbc->wr_buf_no] == NULL) {
- rbc->bufs[rbc->wr_buf_no] = (u8 *)malloc(rbc->each_buf_size);
- if (rbc->bufs[rbc->wr_buf_no] == NULL) {
+ if (rbc->bufs[rbc->wr_buf_no].data == NULL) {
+ rbc->bufs[rbc->wr_buf_no].data = (u8 *)malloc(rbc->each_buf_size);
+ if (rbc->bufs[rbc->wr_buf_no].data == NULL) {
ALOGE("Failed to alloc write buffer");
- return RB_FAILURE;
+ return RB_RETRY;
}
}
@@ -193,13 +261,18 @@ enum rb_status rb_write (void *ctx, u8 *buf, size_t length, int overwrite)
push_in_rd_ptr += cur_copy_len -
(rbc->cur_rd_buf_idx - rbc->cur_wr_buf_idx);
rbc->cur_rd_buf_idx = rbc->cur_wr_buf_idx + cur_copy_len;
- if (rbc->cur_rd_buf_idx == rbc->each_buf_size) {
+ if (rbc->cur_rd_buf_idx >=
+ rbc->bufs[rbc->rd_buf_no].last_wr_index) {
rbc->cur_rd_buf_idx = 0;
rbc->rd_buf_no++;
if (rbc->rd_buf_no == rbc->max_num_bufs) {
rbc->rd_buf_no = 0;
ALOGD("Pushing read to the start of ring buffer");
}
+ /* the previous buffer might have little more empty room
+ * after overwriting the remaining bytes
+ */
+ rbc->bufs[rbc->wr_buf_no].full = 0;
}
}
}
@@ -209,7 +282,7 @@ enum rb_status rb_write (void *ctx, u8 *buf, size_t length, int overwrite)
/* don't use lock while doing memcpy, so that we don't block the read
* context for too long. There is no harm while writing the memory if
* locking is properly done while upgrading the pointers */
- memcpy((rbc->bufs[rbc->wr_buf_no] + rbc->cur_wr_buf_idx),
+ memcpy((rbc->bufs[rbc->wr_buf_no].data + rbc->cur_wr_buf_idx),
(buf + bytes_written),
cur_copy_len);
@@ -218,6 +291,8 @@ enum rb_status rb_write (void *ctx, u8 *buf, size_t length, int overwrite)
rbc->cur_wr_buf_idx += cur_copy_len;
if (rbc->cur_wr_buf_idx == rbc->each_buf_size) {
/* Increment the wr_buf_no as the current buffer is full */
+ rbc->bufs[rbc->wr_buf_no].full = 1;
+ rbc->bufs[rbc->wr_buf_no].last_wr_index = rbc->cur_wr_buf_idx;
rbc->wr_buf_no++;
if (rbc->wr_buf_no == rbc->max_num_bufs) {
ALOGD("Write rolling over to the start of ring buffer");
@@ -250,6 +325,7 @@ enum rb_status rb_write (void *ctx, u8 *buf, size_t length, int overwrite)
/* check if valid bytes is going more than threshold */
if ((rbc->threshold_reached == RB_FALSE) &&
(rbc->cur_valid_bytes >= rbc->num_min_bytes) &&
+ ((length == record_length) || !record_length) &&
rbc->threshold_cb) {
/* Release the lock before calling threshold_cb as it might call rb_read
* in this same context in order to avoid dead lock
@@ -273,7 +349,7 @@ size_t rb_read (void *ctx, u8 *buf, size_t max_length)
while (bytes_read < max_length) {
unsigned int cur_cpy_len;
- if (rbc->bufs[rbc->rd_buf_no] == NULL) {
+ if (rbc->bufs[rbc->rd_buf_no].data == NULL) {
break;
}
@@ -313,7 +389,7 @@ size_t rb_read (void *ctx, u8 *buf, size_t max_length)
}
memcpy((buf + bytes_read),
- (rbc->bufs[rbc->rd_buf_no] + rbc->cur_rd_buf_idx),
+ (rbc->bufs[rbc->rd_buf_no].data + rbc->cur_rd_buf_idx),
cur_cpy_len);
/* Update the read index */
@@ -321,8 +397,8 @@ size_t rb_read (void *ctx, u8 *buf, size_t max_length)
if (rbc->cur_rd_buf_idx == rbc->each_buf_size) {
/* Increment rd_buf_no as the current buffer is completely read */
if (rbc->rd_buf_no != rbc->wr_buf_no) {
- free(rbc->bufs[rbc->rd_buf_no]);
- rbc->bufs[rbc->rd_buf_no] = NULL;
+ free(rbc->bufs[rbc->rd_buf_no].data);
+ rbc->bufs[rbc->rd_buf_no].data = NULL;
}
rbc->rd_buf_no++;
if (rbc->rd_buf_no == rbc->max_num_bufs) {
@@ -365,12 +441,25 @@ u8 *rb_get_read_buf(void *ctx, size_t *length)
u8 *buf;
/* If no buffer is available for reading */
- if (rbc->bufs[rbc->rd_buf_no] == NULL) {
+ if (rbc->bufs[rbc->rd_buf_no].data == NULL) {
*length = 0;
return NULL;
}
rb_lock(&rbc->rb_rw_lock);
+ if ((rbc->bufs[rbc->rd_buf_no].full == 1) &&
+ (rbc->cur_rd_buf_idx == rbc->bufs[rbc->rd_buf_no].last_wr_index)) {
+ if (rbc->wr_buf_no != rbc->rd_buf_no) {
+ free(rbc->bufs[rbc->rd_buf_no].data);
+ rbc->bufs[rbc->rd_buf_no].data = NULL;
+ }
+ rbc->bufs[rbc->rd_buf_no].full = 0;
+ rbc->rd_buf_no++;
+ if (rbc->rd_buf_no == rbc->max_num_bufs) {
+ rbc->rd_buf_no = 0;
+ }
+ rbc->cur_rd_buf_idx = 0;
+ }
if (rbc->wr_buf_no == rbc->rd_buf_no) {
/* If read and write are happening on the same buffer currently, use
@@ -386,24 +475,26 @@ u8 *rb_get_read_buf(void *ctx, size_t *length)
cur_read_len = rbc->cur_wr_buf_idx - rbc->cur_rd_buf_idx;
} else {
/* write is rolled over and just behind the read */
- cur_read_len = rbc->each_buf_size - rbc->cur_rd_buf_idx;
+ cur_read_len = rbc->bufs[rbc->rd_buf_no].last_wr_index - rbc->cur_rd_buf_idx;
}
} else {
if (rbc->cur_rd_buf_idx == 0) {
/* The complete buffer can be read out */
- cur_read_len = rbc->each_buf_size;
+ cur_read_len = rbc->bufs[rbc->rd_buf_no].last_wr_index;
} else {
/* Read the remaining bytes in this buffer */
- cur_read_len = rbc->each_buf_size - rbc->cur_rd_buf_idx;
+ cur_read_len = rbc->bufs[rbc->rd_buf_no].last_wr_index - rbc->cur_rd_buf_idx;
}
}
- if (cur_read_len == rbc->each_buf_size) {
+ if ((rbc->bufs[rbc->rd_buf_no].full == 1) &&
+ (rbc->cur_rd_buf_idx == 0)) {
/* Pluck out the complete buffer and send it out */
- buf = rbc->bufs[rbc->rd_buf_no];
- rbc->bufs[rbc->rd_buf_no] = NULL;
+ buf = rbc->bufs[rbc->rd_buf_no].data;
+ rbc->bufs[rbc->rd_buf_no].data = NULL;
/* Move to the next buffer */
+ rbc->bufs[rbc->rd_buf_no].full = 0;
rbc->rd_buf_no++;
if (rbc->rd_buf_no == rbc->max_num_bufs) {
ALOGD("Read rolling over to the start of ring buffer");
@@ -414,14 +505,17 @@ u8 *rb_get_read_buf(void *ctx, size_t *length)
* and copy the data into it.
*/
buf = (u8 *)malloc(cur_read_len);
- memcpy(buf, (rbc->bufs[rbc->rd_buf_no] + rbc->cur_rd_buf_idx), cur_read_len);
+ memcpy(buf,
+ (rbc->bufs[rbc->rd_buf_no].data + rbc->cur_rd_buf_idx),
+ cur_read_len);
/* Update the read index */
- if ((cur_read_len + rbc->cur_rd_buf_idx) == rbc->each_buf_size) {
+ if (rbc->bufs[rbc->rd_buf_no].full == 1) {
if (rbc->wr_buf_no != rbc->rd_buf_no) {
- free(rbc->bufs[rbc->rd_buf_no]);
- rbc->bufs[rbc->rd_buf_no] = NULL;
+ free(rbc->bufs[rbc->rd_buf_no].data);
+ rbc->bufs[rbc->rd_buf_no].data = NULL;
}
+ rbc->bufs[rbc->rd_buf_no].full = 0;
rbc->rd_buf_no++;
if (rbc->rd_buf_no == rbc->max_num_bufs) {
rbc->rd_buf_no = 0;