summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmarnath Hullur Subramanyam <amarnath@codeaurora.org>2015-08-26 21:02:15 +0530
committerVineeta Srivastava <vsrivastava@google.com>2015-09-03 15:19:04 -0700
commiteb3d1bfb7ba3935f3d5d31fc25a826760584e474 (patch)
treec9cd489ff497d2689a04deef8237f10aee339c75
parent273ec8f00d5fabae8e41d672042798a84c147309 (diff)
downloadandroid_hardware_qcom_wlan-eb3d1bfb7ba3935f3d5d31fc25a826760584e474.tar.gz
android_hardware_qcom_wlan-eb3d1bfb7ba3935f3d5d31fc25a826760584e474.tar.bz2
android_hardware_qcom_wlan-eb3d1bfb7ba3935f3d5d31fc25a826760584e474.zip
WiFi-HAL: Write and read data to/from ring buffers record wise
Currently, ring buffer writes and reads happens with byte boundary. Add support to write only records and do not split any records. BUG=23783279 Change-Id: I2342f86cc4c3a678f21f1595b81e0cdf6d24b2c0
-rw-r--r--qcwcn/wifi_hal/rb_wrapper.cpp21
-rw-r--r--qcwcn/wifi_hal/ring_buffer.cpp147
-rw-r--r--qcwcn/wifi_hal/ring_buffer.h2
3 files changed, 135 insertions, 35 deletions
diff --git a/qcwcn/wifi_hal/rb_wrapper.cpp b/qcwcn/wifi_hal/rb_wrapper.cpp
index 02338c0..3a9b109 100644
--- a/qcwcn/wifi_hal/rb_wrapper.cpp
+++ b/qcwcn/wifi_hal/rb_wrapper.cpp
@@ -88,13 +88,22 @@ int is_rb_name_match(struct rb_info *rb_info, char *name)
wifi_error ring_buffer_write(struct rb_info *rb_info, u8 *buf, size_t length,
int no_of_records)
{
- if (rb_write(rb_info->rb_ctx, buf, length, 0) != RB_SUCCESS) {
- push_out_rb_data(rb_info);
- /* Try writing the data after reading it out */
- if (rb_write(rb_info->rb_ctx, buf, length, 0) != RB_SUCCESS) {
- ALOGE("Failed to write %zu bytes to rb %s", length, rb_info->name);
- return WIFI_ERROR_OUT_OF_MEMORY;
+ enum rb_status status;
+
+ status = rb_write(rb_info->rb_ctx, buf, length, 0);
+ if ((status == RB_FULL) || (status == RB_RETRY)) {
+ push_out_rb_data(rb_info);
+ /* Try writing the data after reading it out */
+ status = rb_write(rb_info->rb_ctx, buf, length, 0);
+ if (status != RB_SUCCESS) {
+ ALOGE("Failed to rewrite %zu bytes to rb %s with error %d", length,
+ rb_info->name, status);
+ return WIFI_ERROR_UNKNOWN;
}
+ } else if (status == RB_FAILURE) {
+ ALOGE("Failed to write %zu bytes to rb %s with error %d", length,
+ rb_info->name, status);
+ return WIFI_ERROR_UNKNOWN;
}
rb_info->written_records += no_of_records;
diff --git a/qcwcn/wifi_hal/ring_buffer.cpp b/qcwcn/wifi_hal/ring_buffer.cpp
index 771de1a..fa90de1 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,7 +140,7 @@ 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);
@@ -147,25 +153,83 @@ enum rb_status rb_write (void *ctx, u8 *buf, size_t length, int overwrite)
unsigned int push_in_rd_ptr = 0; // push required in read pointer because of
// write in current buffer
unsigned int total_push_in_rd_ptr = 0; // Total amount of push in read pointer in this write
+ size_t record_length = length;
- /* 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 +257,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 +278,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 +287,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");
@@ -273,7 +344,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 +384,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 +392,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 +436,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 +470,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 +500,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;
diff --git a/qcwcn/wifi_hal/ring_buffer.h b/qcwcn/wifi_hal/ring_buffer.h
index 4af5578..d47f8d9 100644
--- a/qcwcn/wifi_hal/ring_buffer.h
+++ b/qcwcn/wifi_hal/ring_buffer.h
@@ -33,6 +33,8 @@
enum rb_status {
RB_SUCCESS = 0,
RB_FAILURE = 1,
+ RB_FULL = 2,
+ RB_RETRY = 3,
};
struct rb_stats {