diff options
author | Amarnath Hullur Subramanyam <amarnath@codeaurora.org> | 2015-08-26 21:02:15 +0530 |
---|---|---|
committer | Vineeta Srivastava <vsrivastava@google.com> | 2015-09-03 15:19:04 -0700 |
commit | eb3d1bfb7ba3935f3d5d31fc25a826760584e474 (patch) | |
tree | c9cd489ff497d2689a04deef8237f10aee339c75 | |
parent | 273ec8f00d5fabae8e41d672042798a84c147309 (diff) | |
download | android_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.cpp | 21 | ||||
-rw-r--r-- | qcwcn/wifi_hal/ring_buffer.cpp | 147 | ||||
-rw-r--r-- | qcwcn/wifi_hal/ring_buffer.h | 2 |
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 { |