123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017 |
- /* Copyright (c) 2008-2014, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
- #include <linux/slab.h>
- #include <linux/delay.h>
- #include <linux/diagchar.h>
- #include <linux/kmemleak.h>
- #include <linux/workqueue.h>
- #include "diagchar.h"
- #include "diagfwd_cntl.h"
- #include "diag_masks.h"
- int diag_event_num_bytes;
- #define DIAG_CTRL_MASK_INVALID 0
- #define DIAG_CTRL_MASK_ALL_DISABLED 1
- #define DIAG_CTRL_MASK_ALL_ENABLED 2
- #define DIAG_CTRL_MASK_VALID 3
- #define ALL_EQUIP_ID 100
- #define ALL_SSID -1
- #define FEATURE_MASK_LEN_BYTES 2
- struct mask_info {
- int equip_id;
- int num_items;
- int index;
- };
- #define CREATE_MSG_MASK_TBL_ROW(XX) \
- do { \
- *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX; \
- msg_mask_tbl_ptr += 4; \
- *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX ## _LAST; \
- msg_mask_tbl_ptr += 4; \
- /* mimic the last entry as actual_last while creation */ \
- *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX ## _LAST; \
- msg_mask_tbl_ptr += 4; \
- /* increment by MAX_SSID_PER_RANGE cells */ \
- msg_mask_tbl_ptr += MAX_SSID_PER_RANGE * sizeof(int); \
- } while (0)
- static void diag_print_mask_table(void)
- {
- /* Enable this to print mask table when updated */
- #ifdef MASK_DEBUG
- int first, last, actual_last;
- uint8_t *ptr = driver->msg_masks;
- int i = 0;
- pr_info("diag: F3 message mask table\n");
- while (*(uint32_t *)(ptr + 4)) {
- first = *(uint32_t *)ptr;
- ptr += 4;
- last = *(uint32_t *)ptr;
- ptr += 4;
- actual_last = *(uint32_t *)ptr;
- ptr += 4;
- pr_info("diag: SSID %d, %d - %d\n", first, last, actual_last);
- for (i = 0 ; i <= actual_last - first ; i++)
- pr_info("diag: MASK:%x\n", *((uint32_t *)ptr + i));
- ptr += MAX_SSID_PER_RANGE*4;
- }
- #endif
- }
- void diag_create_msg_mask_table(void)
- {
- uint8_t *msg_mask_tbl_ptr = driver->msg_masks;
- CREATE_MSG_MASK_TBL_ROW(0);
- CREATE_MSG_MASK_TBL_ROW(1);
- CREATE_MSG_MASK_TBL_ROW(2);
- CREATE_MSG_MASK_TBL_ROW(3);
- CREATE_MSG_MASK_TBL_ROW(4);
- CREATE_MSG_MASK_TBL_ROW(5);
- CREATE_MSG_MASK_TBL_ROW(6);
- CREATE_MSG_MASK_TBL_ROW(7);
- CREATE_MSG_MASK_TBL_ROW(8);
- CREATE_MSG_MASK_TBL_ROW(9);
- CREATE_MSG_MASK_TBL_ROW(10);
- CREATE_MSG_MASK_TBL_ROW(11);
- CREATE_MSG_MASK_TBL_ROW(12);
- CREATE_MSG_MASK_TBL_ROW(13);
- CREATE_MSG_MASK_TBL_ROW(14);
- CREATE_MSG_MASK_TBL_ROW(15);
- CREATE_MSG_MASK_TBL_ROW(16);
- CREATE_MSG_MASK_TBL_ROW(17);
- CREATE_MSG_MASK_TBL_ROW(18);
- CREATE_MSG_MASK_TBL_ROW(19);
- CREATE_MSG_MASK_TBL_ROW(20);
- CREATE_MSG_MASK_TBL_ROW(21);
- CREATE_MSG_MASK_TBL_ROW(22);
- CREATE_MSG_MASK_TBL_ROW(23);
- }
- static void diag_set_msg_mask(int rt_mask)
- {
- int first_ssid, last_ssid, i;
- uint8_t *parse_ptr, *ptr = driver->msg_masks;
- mutex_lock(&driver->diagchar_mutex);
- driver->msg_status = rt_mask ? DIAG_CTRL_MASK_ALL_ENABLED :
- DIAG_CTRL_MASK_ALL_DISABLED;
- while (*(uint32_t *)(ptr + 4)) {
- first_ssid = *(uint32_t *)ptr;
- ptr += 8; /* increment by 8 to skip 'last' */
- last_ssid = *(uint32_t *)ptr;
- ptr += 4;
- parse_ptr = ptr;
- pr_debug("diag: updating range %d %d\n", first_ssid, last_ssid);
- for (i = 0; i < last_ssid - first_ssid + 1; i++) {
- *(int *)parse_ptr = rt_mask;
- parse_ptr += 4;
- }
- ptr += MAX_SSID_PER_RANGE * 4;
- }
- mutex_unlock(&driver->diagchar_mutex);
- }
- static void diag_update_msg_mask(int start, int end , uint8_t *buf)
- {
- int found = 0, first, last, actual_last;
- uint8_t *actual_last_ptr;
- uint8_t *ptr = driver->msg_masks;
- uint8_t *ptr_buffer_start = &(*(driver->msg_masks));
- uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
- uint32_t copy_len = (end - start + 1) * sizeof(int);
- mutex_lock(&driver->diagchar_mutex);
- /* First SSID can be zero : So check that last is non-zero */
- while (*(uint32_t *)(ptr + 4)) {
- first = *(uint32_t *)ptr;
- ptr += 4;
- last = *(uint32_t *)ptr;
- ptr += 4;
- actual_last = *(uint32_t *)ptr;
- actual_last_ptr = ptr;
- ptr += 4;
- if (start >= first && start <= actual_last) {
- ptr += (start - first)*4;
- if (end > actual_last) {
- pr_info("diag: ssid range mismatch\n");
- actual_last = end;
- *(uint32_t *)(actual_last_ptr) = end;
- }
- if (actual_last-first >= MAX_SSID_PER_RANGE) {
- pr_err("diag: In %s, truncating ssid range, %d-%d to max allowed: %d",
- __func__, first, actual_last,
- MAX_SSID_PER_RANGE);
- copy_len = MAX_SSID_PER_RANGE;
- actual_last = first + MAX_SSID_PER_RANGE;
- *(uint32_t *)actual_last_ptr = actual_last;
- }
- if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
- copy_len)) {
- pr_debug("diag: update ssid start %d, end %d\n",
- start, end);
- memcpy(ptr, buf, copy_len);
- } else
- pr_alert("diag: Not enough space MSG_MASK\n");
- found = 1;
- break;
- } else {
- ptr += MAX_SSID_PER_RANGE*4;
- }
- }
- /* Entry was not found - add new table */
- if (!found) {
- if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
- 8 + ((end - start) + 1)*4)) {
- memcpy(ptr, &(start) , 4);
- ptr += 4;
- memcpy(ptr, &(end), 4);
- ptr += 4;
- memcpy(ptr, &(end), 4); /* create actual_last entry */
- ptr += 4;
- pr_debug("diag: adding NEW ssid start %d, end %d\n",
- start, end);
- memcpy(ptr, buf , ((end - start) + 1)*4);
- } else
- pr_alert("diag: Not enough buffer space for MSG_MASK\n");
- }
- driver->msg_status = DIAG_CTRL_MASK_VALID;
- mutex_unlock(&driver->diagchar_mutex);
- diag_print_mask_table();
- }
- void diag_toggle_event_mask(int toggle)
- {
- uint8_t *ptr = driver->event_masks;
- mutex_lock(&driver->diagchar_mutex);
- if (toggle) {
- driver->event_status = DIAG_CTRL_MASK_ALL_ENABLED;
- memset(ptr, 0xFF, EVENT_MASK_SIZE);
- } else {
- driver->event_status = DIAG_CTRL_MASK_ALL_DISABLED;
- memset(ptr, 0, EVENT_MASK_SIZE);
- }
- mutex_unlock(&driver->diagchar_mutex);
- }
- static void diag_update_event_mask(uint8_t *buf, int num_bytes)
- {
- uint8_t *ptr = driver->event_masks;
- uint8_t *temp = buf + 2;
- mutex_lock(&driver->diagchar_mutex);
- if (CHK_OVERFLOW(ptr, ptr, ptr+EVENT_MASK_SIZE, num_bytes)) {
- memcpy(ptr, temp, num_bytes);
- driver->event_status = DIAG_CTRL_MASK_VALID;
- } else {
- pr_err("diag: In %s, not enough buffer space\n", __func__);
- }
- mutex_unlock(&driver->diagchar_mutex);
- }
- static void diag_disable_log_mask(void)
- {
- int i = 0;
- struct diag_log_mask_t *log_item = NULL;
- mutex_lock(&driver->log_mask_mutex);
- log_item = (struct diag_log_mask_t *)driver->log_masks;
- for (i = 0; i < MAX_EQUIP_ID; i++, log_item++)
- memset(log_item->ptr, 0, MAX_ITEMS_PER_EQUIP_ID);
- driver->log_status = DIAG_CTRL_MASK_ALL_DISABLED;
- mutex_unlock(&driver->log_mask_mutex);
- }
- static int copy_log_mask_equip(int equip_id, uint8_t *buf)
- {
- int i, ret = 0;
- uint8_t *temp = buf;
- struct diag_log_mask_t *log_item = NULL;
- uint32_t mask_size = 0;
- if (!buf)
- return ret;
- log_item = (struct diag_log_mask_t *)driver->log_masks;
- for (i = 0; i < MAX_EQUIP_ID; i++, log_item++) {
- if (log_item->equip_id != equip_id)
- continue;
- *(int *)temp = log_item->equip_id;
- temp += sizeof(int);
- *(int *)(temp) = log_item->num_items;
- temp += sizeof(int);
- mask_size = LOG_ITEMS_TO_SIZE(log_item->num_items);
- if (mask_size > MAX_ITEMS_PER_EQUIP_ID) {
- pr_err("diag: Invalid length: %d in %s, perimissible: %d",
- mask_size, __func__, MAX_ITEMS_PER_EQUIP_ID);
- break;
- }
- if (mask_size > 0) {
- memcpy(temp, log_item->ptr, mask_size);
- /*
- * Return the total number of bytes copied = size of
- * equip_id (int) + size of num_items (int) + mask_size
- */
- ret = (2 * sizeof(int)) + mask_size;
- }
- break;
- }
- return ret;
- }
- static void diag_update_log_mask(int equip_id, uint8_t *buf, int num_items)
- {
- int i = 0;
- struct diag_log_mask_t *log_item = NULL;
- uint32_t mask_size = 0;
- mutex_lock(&driver->log_mask_mutex);
- driver->log_status = DIAG_CTRL_MASK_INVALID;
- if (!buf || (equip_id < 0 || equip_id >= MAX_EQUIP_ID) ||
- num_items < 1) {
- pr_err("diag: Invalid params in %s, buf: %x equip_id: %d, num_items: %d\n",
- __func__, (unsigned int)buf, equip_id, num_items);
- mutex_unlock(&driver->log_mask_mutex);
- return;
- }
- mask_size = LOG_ITEMS_TO_SIZE(num_items);
- if (mask_size > MAX_ITEMS_PER_EQUIP_ID) {
- pr_err("diag: In %s, Invalid mask_size %d\n", __func__,
- mask_size);
- mutex_unlock(&driver->log_mask_mutex);
- return;
- }
- log_item = (struct diag_log_mask_t *)driver->log_masks;
- for (i = 0; i < MAX_EQUIP_ID; i++, log_item++) {
- if (log_item->equip_id != equip_id)
- continue;
- /* Found the equip id */
- log_item->num_items = num_items;
- if (mask_size > 0)
- memcpy(log_item->ptr, buf, mask_size);
- driver->log_status = DIAG_CTRL_MASK_VALID;
- break;
- }
- mutex_unlock(&driver->log_mask_mutex);
- }
- void diag_mask_update_fn(struct work_struct *work)
- {
- struct diag_smd_info *smd_info = container_of(work,
- struct diag_smd_info,
- diag_notify_update_smd_work);
- if (!smd_info) {
- pr_err("diag: In %s, smd info is null, cannot update masks for the peripheral\n",
- __func__);
- return;
- }
- diag_send_feature_mask_update(smd_info);
- diag_send_msg_mask_update(smd_info, ALL_SSID, ALL_SSID,
- smd_info->peripheral);
- diag_send_log_mask_update(smd_info, ALL_EQUIP_ID);
- diag_send_event_mask_update(smd_info, diag_event_num_bytes);
- if (smd_info->notify_context == SMD_EVENT_OPEN)
- diag_send_diag_mode_update_by_smd(smd_info,
- driver->real_time_mode);
- smd_info->notify_context = 0;
- }
- void diag_send_log_mask_update(struct diag_smd_info *smd_info, int equip_id)
- {
- void *buf = driver->buf_log_mask_update;
- struct diag_log_mask_t *log_item = NULL;
- struct diag_ctrl_log_mask ctrl_pkt;
- uint32_t log_mask_size = 0;
- int wr_size = -ENOMEM, retry_count = 0;
- int i, header_size, send_once = 0;
- if (!smd_info) {
- pr_err("diag: In %s, null smd info pointer\n",
- __func__);
- return;
- }
- header_size = sizeof(struct diag_ctrl_log_mask);
- log_item = (struct diag_log_mask_t *)driver->log_masks;
- mutex_lock(&driver->diag_cntl_mutex);
- for (i = 0; i < MAX_EQUIP_ID; i++, log_item++) {
- if (equip_id != i && equip_id != ALL_EQUIP_ID)
- continue;
- log_mask_size = LOG_ITEMS_TO_SIZE(log_item->num_items);
- ctrl_pkt.cmd_type = DIAG_CTRL_MSG_LOG_MASK;
- ctrl_pkt.data_len = 11 + log_mask_size;
- ctrl_pkt.stream_id = 1;
- ctrl_pkt.status = driver->log_status;
- switch (driver->log_status) {
- case DIAG_CTRL_MASK_ALL_DISABLED:
- ctrl_pkt.equip_id = 0;
- ctrl_pkt.num_items = 0;
- ctrl_pkt.log_mask_size = 0;
- send_once = 1;
- break;
- case DIAG_CTRL_MASK_ALL_ENABLED:
- ctrl_pkt.equip_id = 0;
- ctrl_pkt.num_items = 0;
- ctrl_pkt.log_mask_size = 0;
- send_once = 1;
- break;
- case DIAG_CTRL_MASK_VALID:
- ctrl_pkt.equip_id = i;
- ctrl_pkt.num_items = log_item->num_items;
- ctrl_pkt.log_mask_size = log_mask_size;
- send_once = 0;
- break;
- default:
- pr_err("diag: In %s, invalid status %d", __func__,
- driver->log_status);
- mutex_unlock(&driver->diag_cntl_mutex);
- return;
- }
- memcpy(buf, &ctrl_pkt, header_size);
- if (log_mask_size > 0) {
- memcpy(buf + header_size, log_item->ptr,
- log_mask_size);
- }
- if (smd_info->ch) {
- while (retry_count < 3) {
- mutex_lock(&smd_info->smd_ch_mutex);
- wr_size = smd_write(smd_info->ch, buf,
- header_size + log_mask_size);
- mutex_unlock(&smd_info->smd_ch_mutex);
- if (wr_size == -ENOMEM) {
- retry_count++;
- usleep_range(10000, 10100);
- } else
- break;
- }
- if (wr_size != header_size + log_mask_size)
- pr_err("diag: log mask update failed %d, tried %d",
- wr_size, header_size + log_mask_size);
- else
- pr_debug("diag: updated log equip ID %d,len %d\n",
- i, log_mask_size);
- } else
- pr_err("diag: ch not valid for log update\n");
- if (send_once)
- break;
- }
- mutex_unlock(&driver->diag_cntl_mutex);
- }
- void diag_send_event_mask_update(struct diag_smd_info *smd_info, int num_bytes)
- {
- void *buf = driver->buf_event_mask_update;
- int header_size = sizeof(struct diag_ctrl_event_mask);
- int wr_size = -ENOMEM, retry_count = 0;
- if (!smd_info) {
- pr_err("diag: In %s, null smd info pointer\n",
- __func__);
- return;
- }
- mutex_lock(&driver->diag_cntl_mutex);
- if (num_bytes == 0) {
- pr_debug("diag: event mask not set yet, so no update\n");
- mutex_unlock(&driver->diag_cntl_mutex);
- return;
- }
- /* send event mask update */
- driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
- driver->event_mask->data_len = 7 + num_bytes;
- driver->event_mask->stream_id = 1; /* 2, if dual stream */
- driver->event_mask->status = driver->event_status;
- switch (driver->event_status) {
- case DIAG_CTRL_MASK_ALL_DISABLED:
- driver->event_mask->event_config = 0;
- driver->event_mask->event_mask_size = 0;
- break;
- case DIAG_CTRL_MASK_ALL_ENABLED:
- driver->event_mask->event_config = 1;
- driver->event_mask->event_mask_size = 0;
- break;
- case DIAG_CTRL_MASK_VALID:
- driver->event_mask->event_config = 1;
- driver->event_mask->event_mask_size = num_bytes;
- memcpy(buf + header_size, driver->event_masks, num_bytes);
- break;
- default:
- /* Event status is not set yet or the buffer is corrupted */
- pr_err("diag: In %s, invalid status %d", __func__,
- driver->event_status);
- driver->event_mask->status = DIAG_CTRL_MASK_INVALID;
- }
- if (driver->event_mask->status == DIAG_CTRL_MASK_INVALID) {
- mutex_unlock(&driver->diag_cntl_mutex);
- return;
- }
- memcpy(buf, driver->event_mask, header_size);
- if (smd_info->ch) {
- while (retry_count < 3) {
- mutex_lock(&smd_info->smd_ch_mutex);
- wr_size = smd_write(smd_info->ch, buf,
- header_size + num_bytes);
- mutex_unlock(&smd_info->smd_ch_mutex);
- if (wr_size == -ENOMEM) {
- retry_count++;
- usleep_range(10000, 10100);
- } else
- break;
- }
- if (wr_size != header_size + num_bytes)
- pr_err("diag: error writing event mask %d, tried %d\n",
- wr_size, header_size + num_bytes);
- } else
- pr_err("diag: ch not valid for event update\n");
- mutex_unlock(&driver->diag_cntl_mutex);
- }
- void diag_send_msg_mask_update(struct diag_smd_info *smd_info,
- int updated_ssid_first, int updated_ssid_last,
- int proc)
- {
- void *buf = driver->buf_msg_mask_update;
- int first, last, actual_last, size = -ENOMEM, retry_count = 0;
- int header_size = sizeof(struct diag_ctrl_msg_mask);
- uint8_t *ptr = driver->msg_masks;
- if (!smd_info) {
- pr_err("diag: In %s, null smd info pointer\n",
- __func__);
- return;
- }
- mutex_lock(&driver->diag_cntl_mutex);
- while (*(uint32_t *)(ptr + 4)) {
- first = *(uint32_t *)ptr;
- ptr += 4;
- last = *(uint32_t *)ptr;
- ptr += 4;
- actual_last = *(uint32_t *)ptr;
- ptr += 4;
- if (!((updated_ssid_first >= first && updated_ssid_last <=
- actual_last) || (updated_ssid_first == ALL_SSID))) {
- ptr += MAX_SSID_PER_RANGE*4;
- continue;
- }
- /* send f3 mask update */
- driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
- driver->msg_mask->status = driver->msg_status;
- switch (driver->msg_status) {
- case DIAG_CTRL_MASK_ALL_DISABLED:
- driver->msg_mask->msg_mask_size = 0;
- break;
- case DIAG_CTRL_MASK_ALL_ENABLED:
- driver->msg_mask->msg_mask_size = 1;
- memcpy(buf+header_size, ptr,
- 4 * (driver->msg_mask->msg_mask_size));
- break;
- case DIAG_CTRL_MASK_VALID:
- driver->msg_mask->msg_mask_size = actual_last -
- first + 1;
- /* Limit the msg_mask_size to MAX_SSID_PER_RANGE */
- if (driver->msg_mask->msg_mask_size >
- MAX_SSID_PER_RANGE) {
- pr_err("diag: in %s, Invalid msg mask size %d, max: %d",
- __func__,
- driver->msg_mask->msg_mask_size,
- MAX_SSID_PER_RANGE);
- driver->msg_mask->msg_mask_size =
- MAX_SSID_PER_RANGE;
- }
- memcpy(buf+header_size, ptr,
- 4 * (driver->msg_mask->msg_mask_size));
- break;
- default:
- /* Msg status is not set or the buffer is corrupted */
- pr_err("diag: In %s, invalid status %d", __func__,
- driver->msg_status);
- driver->msg_mask->status = DIAG_CTRL_MASK_INVALID;
- }
- if (driver->msg_mask->status == DIAG_CTRL_MASK_INVALID) {
- mutex_unlock(&driver->diag_cntl_mutex);
- return;
- }
- driver->msg_mask->data_len = 11 +
- 4 * (driver->msg_mask->msg_mask_size);
- driver->msg_mask->stream_id = 1; /* 2, if dual stream */
- driver->msg_mask->msg_mode = 0; /* Legcay mode */
- driver->msg_mask->ssid_first = first;
- driver->msg_mask->ssid_last = actual_last;
- memcpy(buf, driver->msg_mask, header_size);
- if (smd_info->ch) {
- while (retry_count < 3) {
- mutex_lock(&smd_info->smd_ch_mutex);
- size = smd_write(smd_info->ch, buf, header_size
- + 4*(driver->msg_mask->msg_mask_size));
- mutex_unlock(&smd_info->smd_ch_mutex);
- if (size == -ENOMEM) {
- retry_count++;
- usleep_range(10000, 10100);
- } else
- break;
- }
- if (size != header_size +
- 4*(driver->msg_mask->msg_mask_size))
- pr_err("diag: proc %d, msg mask update fail %d, tried %d\n",
- proc, size, (header_size +
- 4*(driver->msg_mask->msg_mask_size)));
- else
- pr_debug("diag: sending mask update for ssid first %d, last %d on PROC %d\n",
- first, actual_last, proc);
- } else
- pr_err("diag: proc %d, ch invalid msg mask update\n",
- proc);
- ptr += MAX_SSID_PER_RANGE*4;
- }
- mutex_unlock(&driver->diag_cntl_mutex);
- }
- void diag_send_feature_mask_update(struct diag_smd_info *smd_info)
- {
- void *buf = driver->buf_feature_mask_update;
- int header_size = sizeof(struct diag_ctrl_feature_mask);
- int wr_size = -ENOMEM, retry_count = 0;
- uint8_t feature_bytes[FEATURE_MASK_LEN_BYTES] = {0, 0};
- int total_len = 0;
- if (!smd_info) {
- pr_err("diag: In %s, null smd info pointer\n",
- __func__);
- return;
- }
- if (!smd_info->ch) {
- pr_err("diag: In %s, smd channel not open for peripheral: %d, type: %d\n",
- __func__, smd_info->peripheral, smd_info->type);
- return;
- }
- mutex_lock(&driver->diag_cntl_mutex);
- /* send feature mask update */
- driver->feature_mask->ctrl_pkt_id = DIAG_CTRL_MSG_FEATURE;
- driver->feature_mask->ctrl_pkt_data_len = 4 + FEATURE_MASK_LEN_BYTES;
- driver->feature_mask->feature_mask_len = FEATURE_MASK_LEN_BYTES;
- memcpy(buf, driver->feature_mask, header_size);
- feature_bytes[0] |= F_DIAG_INT_FEATURE_MASK;
- feature_bytes[0] |= F_DIAG_LOG_ON_DEMAND_RSP_ON_MASTER;
- feature_bytes[0] |= driver->supports_separate_cmdrsp ?
- F_DIAG_REQ_RSP_CHANNEL : 0;
- feature_bytes[0] |= driver->supports_apps_hdlc_encoding ?
- F_DIAG_HDLC_ENCODE_IN_APPS_MASK : 0;
- feature_bytes[1] |= F_DIAG_OVER_STM;
- memcpy(buf+header_size, &feature_bytes, FEATURE_MASK_LEN_BYTES);
- total_len = header_size + FEATURE_MASK_LEN_BYTES;
- while (retry_count < 3) {
- mutex_lock(&smd_info->smd_ch_mutex);
- wr_size = smd_write(smd_info->ch, buf, total_len);
- mutex_unlock(&smd_info->smd_ch_mutex);
- if (wr_size == -ENOMEM) {
- retry_count++;
- /*
- * The smd channel is full. Delay while
- * smd processes existing data and smd
- * has memory become available. The delay
- * of 10000 was determined empirically as
- * best value to use.
- */
- usleep_range(10000, 10100);
- } else
- break;
- }
- if (wr_size != total_len)
- pr_err("diag: In %s, peripheral %d fail feature update, size: %d, tried: %d",
- __func__, smd_info->peripheral, wr_size, total_len);
- mutex_unlock(&driver->diag_cntl_mutex);
- }
- int diag_process_apps_masks(unsigned char *buf, int len)
- {
- int packet_type = 1;
- int i;
- int ssid_first, ssid_last, ssid_range;
- int rt_mask, rt_first_ssid, rt_last_ssid, rt_mask_size;
- uint8_t *rt_mask_ptr;
- int equip_id, copy_len;
- #if defined(CONFIG_DIAG_OVER_USB)
- int payload_length;
- #endif
- /* Set log masks */
- if (*buf == 0x73 && *(int *)(buf+4) == 3) {
- buf += 8;
- diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
- diag_update_userspace_clients(LOG_MASKS_TYPE);
- #if defined(CONFIG_DIAG_OVER_USB)
- if (chk_apps_only()) {
- driver->apps_rsp_buf[0] = 0x73;
- *(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
- *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
- payload_length = 8 +
- LOG_ITEMS_TO_SIZE(*(int *)(buf + 4));
- if (payload_length > APPS_BUF_SIZE - 12) {
- pr_err("diag: log masks: buffer overflow\n");
- return -EIO;
- }
- for (i = 0; i < payload_length; i++)
- *(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
- for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
- if (driver->smd_cntl[i].ch)
- diag_send_log_mask_update(
- &driver->smd_cntl[i],
- *(int *)buf);
- }
- encode_rsp_and_send(12 + payload_length - 1);
- return 0;
- }
- #endif
- } /* Get log masks */
- else if (*buf == 0x73 && *(int *)(buf+4) == 4) {
- #if defined(CONFIG_DIAG_OVER_USB)
- if (!(driver->smd_data[MODEM_DATA].ch) &&
- chk_apps_only()) {
- equip_id = *(int *)(buf + 8);
- driver->apps_rsp_buf[0] = 0x73;
- driver->apps_rsp_buf[1] = 0x0;
- driver->apps_rsp_buf[2] = 0x0;
- driver->apps_rsp_buf[3] = 0x0;
- *(int *)(driver->apps_rsp_buf + 4) = 0x4;
- copy_len = copy_log_mask_equip(equip_id,
- driver->apps_rsp_buf + 12);
- *(int *)(driver->apps_rsp_buf + 8) =
- (copy_len == 0) ? 1 : 0;
- encode_rsp_and_send(12 + copy_len);
- return 0;
- }
- #endif
- } /* Disable log masks */
- else if (*buf == 0x73 && *(int *)(buf+4) == 0) {
- /* Disable mask for each log code */
- diag_disable_log_mask();
- diag_update_userspace_clients(LOG_MASKS_TYPE);
- #if defined(CONFIG_DIAG_OVER_USB)
- if (chk_apps_only()) {
- driver->apps_rsp_buf[0] = 0x73;
- driver->apps_rsp_buf[1] = 0x0;
- driver->apps_rsp_buf[2] = 0x0;
- driver->apps_rsp_buf[3] = 0x0;
- *(int *)(driver->apps_rsp_buf + 4) = 0x0;
- *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* status */
- for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
- if (driver->smd_cntl[i].ch)
- diag_send_log_mask_update(
- &driver->smd_cntl[i],
- ALL_EQUIP_ID);
- }
- encode_rsp_and_send(11);
- return 0;
- }
- #endif
- } /* Get runtime message mask */
- else if ((*buf == 0x7d) && (*(buf+1) == 0x3)) {
- ssid_first = *(uint16_t *)(buf + 2);
- ssid_last = *(uint16_t *)(buf + 4);
- #if defined(CONFIG_DIAG_OVER_USB)
- if (!(driver->smd_data[MODEM_DATA].ch) &&
- chk_apps_only()) {
- driver->apps_rsp_buf[0] = 0x7d;
- driver->apps_rsp_buf[1] = 0x3;
- *(uint16_t *)(driver->apps_rsp_buf+2) = ssid_first;
- *(uint16_t *)(driver->apps_rsp_buf+4) = ssid_last;
- driver->apps_rsp_buf[6] = 0x1; /* Success Status */
- driver->apps_rsp_buf[7] = 0x0;
- rt_mask_ptr = driver->msg_masks;
- while (*(uint32_t *)(rt_mask_ptr + 4)) {
- rt_first_ssid = *(uint32_t *)rt_mask_ptr;
- rt_mask_ptr += 8; /* +8 to skip 'last' */
- rt_last_ssid = *(uint32_t *)rt_mask_ptr;
- rt_mask_ptr += 4;
- if (ssid_first == rt_first_ssid && ssid_last ==
- rt_last_ssid) {
- rt_mask_size = 4 * (rt_last_ssid -
- rt_first_ssid + 1);
- if (rt_mask_size > APPS_BUF_SIZE - 8) {
- pr_err("diag: rt masks: buffer overflow\n");
- return -EIO;
- }
- memcpy(driver->apps_rsp_buf+8,
- rt_mask_ptr, rt_mask_size);
- encode_rsp_and_send(8+rt_mask_size-1);
- return 0;
- }
- rt_mask_ptr += MAX_SSID_PER_RANGE*4;
- }
- }
- #endif
- } /* Set runtime message mask */
- else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
- ssid_first = *(uint16_t *)(buf + 2);
- ssid_last = *(uint16_t *)(buf + 4);
- if (ssid_last < ssid_first) {
- pr_err("diag: Invalid msg mask ssid values, first: %d, last: %d\n",
- ssid_first, ssid_last);
- return -EIO;
- }
- ssid_range = 4 * (ssid_last - ssid_first + 1);
- if (ssid_range > APPS_BUF_SIZE - 8) {
- pr_err("diag: Not enough space for message mask, ssid_range: %d\n",
- ssid_range);
- return -EIO;
- }
- pr_debug("diag: received mask update for ssid_first = %d, ssid_last = %d",
- ssid_first, ssid_last);
- diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
- diag_update_userspace_clients(MSG_MASKS_TYPE);
- #if defined(CONFIG_DIAG_OVER_USB)
- if (chk_apps_only()) {
- for (i = 0; i < 8 + ssid_range; i++)
- *(driver->apps_rsp_buf + i) = *(buf+i);
- *(driver->apps_rsp_buf + 6) = 0x1;
- for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
- if (driver->smd_cntl[i].ch)
- diag_send_msg_mask_update(
- &driver->smd_cntl[i],
- ssid_first, ssid_last,
- driver->smd_cntl[i].peripheral);
- }
- encode_rsp_and_send(8 + ssid_range - 1);
- return 0;
- }
- #endif
- } /* Set ALL runtime message mask */
- else if ((*buf == 0x7d) && (*(buf+1) == 0x5)) {
- rt_mask = *(int *)(buf + 4);
- diag_set_msg_mask(rt_mask);
- diag_update_userspace_clients(MSG_MASKS_TYPE);
- #if defined(CONFIG_DIAG_OVER_USB)
- if (chk_apps_only()) {
- driver->apps_rsp_buf[0] = 0x7d; /* cmd_code */
- driver->apps_rsp_buf[1] = 0x5; /* set subcommand */
- driver->apps_rsp_buf[2] = 1; /* success */
- driver->apps_rsp_buf[3] = 0; /* rsvd */
- *(int *)(driver->apps_rsp_buf + 4) = rt_mask;
- /* send msg mask update to peripheral */
- for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
- if (driver->smd_cntl[i].ch)
- diag_send_msg_mask_update(
- &driver->smd_cntl[i],
- ALL_SSID, ALL_SSID,
- driver->smd_cntl[i].peripheral);
- }
- encode_rsp_and_send(7);
- return 0;
- }
- #endif
- } else if (*buf == 0x82) { /* event mask change */
- buf += 4;
- diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
- diag_update_event_mask(buf, diag_event_num_bytes);
- diag_update_userspace_clients(EVENT_MASKS_TYPE);
- #if defined(CONFIG_DIAG_OVER_USB)
- if (chk_apps_only()) {
- driver->apps_rsp_buf[0] = 0x82;
- driver->apps_rsp_buf[1] = 0x0;
- *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
- *(uint16_t *)(driver->apps_rsp_buf + 4) =
- EVENT_LAST_ID + 1;
- memcpy(driver->apps_rsp_buf+6, driver->event_masks,
- EVENT_LAST_ID/8+1);
- for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
- if (driver->smd_cntl[i].ch)
- diag_send_event_mask_update(
- &driver->smd_cntl[i],
- diag_event_num_bytes);
- }
- encode_rsp_and_send(6 + EVENT_LAST_ID/8);
- return 0;
- }
- #endif
- } else if (*buf == 0x60) {
- diag_toggle_event_mask(*(buf+1));
- diag_update_userspace_clients(EVENT_MASKS_TYPE);
- #if defined(CONFIG_DIAG_OVER_USB)
- if (chk_apps_only()) {
- driver->apps_rsp_buf[0] = 0x60;
- driver->apps_rsp_buf[1] = 0x0;
- driver->apps_rsp_buf[2] = 0x0;
- for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
- if (driver->smd_cntl[i].ch)
- diag_send_event_mask_update(
- &driver->smd_cntl[i],
- diag_event_num_bytes);
- }
- encode_rsp_and_send(2);
- return 0;
- }
- #endif
- } else if (*buf == 0x78) {
- if (!(driver->smd_cntl[MODEM_DATA].ch) ||
- (driver->log_on_demand_support)) {
- driver->apps_rsp_buf[0] = 0x78;
- /* Copy log code received */
- *(uint16_t *)(driver->apps_rsp_buf + 1) =
- *(uint16_t *)(buf + 1);
- driver->apps_rsp_buf[3] = 0x1;/* Unknown */
- encode_rsp_and_send(3);
- }
- }
- return packet_type;
- }
- static void diag_log_mask_init(void)
- {
- struct diag_log_mask_t *log_item = NULL;
- uint8_t i;
- mutex_init(&driver->log_mask_mutex);
- log_item = (struct diag_log_mask_t *)driver->log_masks;
- for (i = 0; i < MAX_EQUIP_ID; i++, log_item++) {
- log_item->equip_id = i;
- log_item->num_items = LOG_GET_ITEM_NUM(log_code_last_tbl[i]);
- }
- }
- void diag_masks_init(void)
- {
- driver->event_status = DIAG_CTRL_MASK_INVALID;
- driver->msg_status = DIAG_CTRL_MASK_INVALID;
- driver->log_status = DIAG_CTRL_MASK_INVALID;
- if (driver->event_mask == NULL) {
- driver->event_mask = kzalloc(sizeof(
- struct diag_ctrl_event_mask), GFP_KERNEL);
- if (driver->event_mask == NULL)
- goto err;
- kmemleak_not_leak(driver->event_mask);
- }
- if (driver->msg_mask == NULL) {
- driver->msg_mask = kzalloc(sizeof(
- struct diag_ctrl_msg_mask), GFP_KERNEL);
- if (driver->msg_mask == NULL)
- goto err;
- kmemleak_not_leak(driver->msg_mask);
- }
- if (driver->log_mask == NULL) {
- driver->log_mask = kzalloc(sizeof(
- struct diag_ctrl_log_mask), GFP_KERNEL);
- if (driver->log_mask == NULL)
- goto err;
- kmemleak_not_leak(driver->log_mask);
- }
- if (driver->buf_msg_mask_update == NULL) {
- driver->buf_msg_mask_update = kzalloc(APPS_BUF_SIZE,
- GFP_KERNEL);
- if (driver->buf_msg_mask_update == NULL)
- goto err;
- kmemleak_not_leak(driver->buf_msg_mask_update);
- }
- if (driver->buf_log_mask_update == NULL) {
- driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
- GFP_KERNEL);
- if (driver->buf_log_mask_update == NULL)
- goto err;
- kmemleak_not_leak(driver->buf_log_mask_update);
- }
- if (driver->buf_event_mask_update == NULL) {
- driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
- GFP_KERNEL);
- if (driver->buf_event_mask_update == NULL)
- goto err;
- kmemleak_not_leak(driver->buf_event_mask_update);
- }
- if (driver->msg_masks == NULL) {
- driver->msg_masks = kzalloc(MSG_MASK_SIZE, GFP_KERNEL);
- if (driver->msg_masks == NULL)
- goto err;
- kmemleak_not_leak(driver->msg_masks);
- }
- if (driver->buf_feature_mask_update == NULL) {
- driver->buf_feature_mask_update = kzalloc(sizeof(
- struct diag_ctrl_feature_mask) +
- FEATURE_MASK_LEN_BYTES, GFP_KERNEL);
- if (driver->buf_feature_mask_update == NULL)
- goto err;
- kmemleak_not_leak(driver->buf_feature_mask_update);
- }
- if (driver->feature_mask == NULL) {
- driver->feature_mask = kzalloc(sizeof(
- struct diag_ctrl_feature_mask), GFP_KERNEL);
- if (driver->feature_mask == NULL)
- goto err;
- kmemleak_not_leak(driver->feature_mask);
- }
- diag_create_msg_mask_table();
- diag_event_num_bytes = 0;
- if (driver->log_masks == NULL) {
- driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL);
- if (driver->log_masks == NULL)
- goto err;
- kmemleak_not_leak(driver->log_masks);
- }
- diag_log_mask_init();
- if (driver->event_masks == NULL) {
- driver->event_masks = kzalloc(EVENT_MASK_SIZE, GFP_KERNEL);
- if (driver->event_masks == NULL)
- goto err;
- kmemleak_not_leak(driver->event_masks);
- }
- return;
- err:
- pr_err("diag: Could not initialize diag mask buffers");
- kfree(driver->event_mask);
- kfree(driver->log_mask);
- kfree(driver->msg_mask);
- kfree(driver->msg_masks);
- kfree(driver->log_masks);
- kfree(driver->event_masks);
- kfree(driver->feature_mask);
- kfree(driver->buf_feature_mask_update);
- }
- void diag_masks_exit(void)
- {
- kfree(driver->event_mask);
- kfree(driver->log_mask);
- kfree(driver->msg_mask);
- kfree(driver->msg_masks);
- kfree(driver->log_masks);
- kfree(driver->event_masks);
- kfree(driver->feature_mask);
- kfree(driver->buf_feature_mask_update);
- }
|