diff options
author | Manoj Prabhu B <bmanoj@codeaurora.org> | 2018-03-14 14:53:52 +0530 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2018-03-20 21:35:06 -0700 |
commit | 43f15aca94921ffa8c56bc417f014ef01436f203 (patch) | |
tree | 412cd603e312c1aa17c1617537b08de3445d17ee /drivers/char/diag | |
parent | bb9c0e0ec85aa211716bff72ae378e0c87dae4a2 (diff) |
diag: Remove hdlc status dependeny on session_info
The patch removes the hdlc status dependency on session_info
protected by md_session_lock inserting delay in processing data
off peripheral.
CRs-Fixed: 2193991
Change-Id: Ia79c0efe82803c15ccae42b00d95258f52242eee
Signed-off-by: Manoj Prabhu B <bmanoj@codeaurora.org>
Diffstat (limited to 'drivers/char/diag')
-rw-r--r-- | drivers/char/diag/diagchar.h | 5 | ||||
-rw-r--r-- | drivers/char/diag/diagchar_core.c | 99 | ||||
-rw-r--r-- | drivers/char/diag/diagfwd.c | 146 | ||||
-rw-r--r-- | drivers/char/diag/diagfwd_peripheral.c | 22 |
4 files changed, 218 insertions, 54 deletions
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h index 75080f0d4c39..afea5f40bfee 100644 --- a/drivers/char/diag/diagchar.h +++ b/drivers/char/diag/diagchar.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2018, 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 @@ -580,6 +580,7 @@ struct diagchar_dev { /* buffer for updating mask to peripherals */ unsigned char *buf_feature_mask_update; uint8_t hdlc_disabled; + uint8_t p_hdlc_disabled[NUM_MD_SESSIONS]; struct mutex hdlc_disable_mutex; struct mutex hdlc_recovery_mutex; struct timer_list hdlc_reset_timer; @@ -604,6 +605,7 @@ struct diagchar_dev { struct work_struct diag_drain_work; struct work_struct update_user_clients; struct work_struct update_md_clients; + struct work_struct diag_hdlc_reset_work; struct workqueue_struct *diag_cntl_wq; uint8_t log_on_demand_support; uint8_t *apps_req_buf; @@ -683,5 +685,6 @@ void diag_record_stats(int type, int flag); struct diag_md_session_t *diag_md_session_get_pid(int pid); struct diag_md_session_t *diag_md_session_get_peripheral(uint8_t peripheral); +int diag_md_session_match_pid_peripheral(int pid, uint8_t peripheral); #endif diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index ed982f426923..be7a565ca04e 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -252,18 +252,13 @@ static void diag_update_md_client_work_fn(struct work_struct *work) void diag_drain_work_fn(struct work_struct *work) { - struct diag_md_session_t *session_info = NULL; uint8_t hdlc_disabled = 0; timer_in_progress = 0; mutex_lock(&apps_data_mutex); - mutex_lock(&driver->md_session_lock); - session_info = diag_md_session_get_peripheral(APPS_DATA); - if (session_info) - hdlc_disabled = session_info->hdlc_disabled; - else - hdlc_disabled = driver->hdlc_disabled; - mutex_unlock(&driver->md_session_lock); + mutex_lock(&driver->hdlc_disable_mutex); + hdlc_disabled = driver->p_hdlc_disabled[APPS_DATA]; + mutex_unlock(&driver->hdlc_disable_mutex); if (!hdlc_disabled) diag_drain_apps_data(&hdlc_data); else @@ -1029,7 +1024,6 @@ static int diag_send_raw_data_remote(int proc, void *buf, int len, struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 }; struct diag_hdlc_dest_type enc = { NULL, NULL, 0 }; int bridge_index = proc - 1; - struct diag_md_session_t *session_info = NULL; uint8_t hdlc_disabled = 0; if (!buf) @@ -1055,13 +1049,9 @@ static int diag_send_raw_data_remote(int proc, void *buf, int len, if (driver->hdlc_encode_buf_len != 0) return -EAGAIN; - mutex_lock(&driver->md_session_lock); - session_info = diag_md_session_get_peripheral(APPS_DATA); - if (session_info) - hdlc_disabled = session_info->hdlc_disabled; - else - hdlc_disabled = driver->hdlc_disabled; - mutex_unlock(&driver->md_session_lock); + mutex_lock(&driver->hdlc_disable_mutex); + hdlc_disabled = driver->p_hdlc_disabled[APPS_DATA]; + mutex_unlock(&driver->hdlc_disable_mutex); if (hdlc_disabled) { if (len < 4) { pr_err("diag: In %s, invalid len: %d of non_hdlc pkt", @@ -1483,6 +1473,43 @@ struct diag_md_session_t *diag_md_session_get_peripheral(uint8_t peripheral) return driver->md_session_map[peripheral]; } +/* + * diag_md_session_match_pid_peripheral + * + * 1. Pass valid PID and get all the peripherals in logging session + * for that PID + * 2. Pass valid Peipheral and get the pid logging for that peripheral + * + */ + +int diag_md_session_match_pid_peripheral(int pid, + uint8_t peripheral) +{ + int i, flag = 0; + + if (pid <= 0 || peripheral >= NUM_MD_SESSIONS) + return -EINVAL; + + if (!peripheral) { + for (i = 0; i < NUM_MD_SESSIONS; i++) { + if (driver->md_session_map[i] && + driver->md_session_map[i]->pid == pid) { + peripheral |= 1 << i; + flag = 1; + } + } + if (flag) + return peripheral; + } + + if (!pid) { + if (driver->md_session_map[peripheral]) + return driver->md_session_map[peripheral]->pid; + } + + return -EINVAL; +} + static int diag_md_peripheral_switch(int pid, int peripheral_mask, int req_mode) { int i, bit = 0; @@ -1637,6 +1664,13 @@ static int diag_md_session_check(int curr_mode, int req_mode, } err = diag_md_session_create(DIAG_MD_PERIPHERAL, param->peripheral_mask, DIAG_LOCAL_PROC); + mutex_lock(&driver->hdlc_disable_mutex); + for (i = 0; i < NUM_MD_SESSIONS; i++) { + if ((param->peripheral_mask > 0) && + (param->peripheral_mask & (1 << i))) + driver->p_hdlc_disabled[i] = 0; + } + mutex_unlock(&driver->hdlc_disable_mutex); } *change_mode = 1; return err; @@ -2085,11 +2119,14 @@ static int diag_ioctl_dci_support(unsigned long ioarg) static int diag_ioctl_hdlc_toggle(unsigned long ioarg) { - uint8_t hdlc_support; + uint8_t hdlc_support, i; + int peripheral = -EINVAL; struct diag_md_session_t *session_info = NULL; + if (copy_from_user(&hdlc_support, (void __user *)ioarg, sizeof(uint8_t))) return -EFAULT; + mutex_lock(&driver->hdlc_disable_mutex); mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_pid(current->tgid); @@ -2097,6 +2134,25 @@ static int diag_ioctl_hdlc_toggle(unsigned long ioarg) session_info->hdlc_disabled = hdlc_support; else driver->hdlc_disabled = hdlc_support; + + peripheral = + diag_md_session_match_pid_peripheral(current->tgid, + 0); + for (i = 0; i < NUM_MD_SESSIONS; i++) { + if (peripheral > 0 && session_info) { + if (peripheral & (1 << i)) + driver->p_hdlc_disabled[i] = + session_info->hdlc_disabled; + else if (!diag_md_session_get_peripheral(i)) + driver->p_hdlc_disabled[i] = + driver->hdlc_disabled; + } else { + if (!diag_md_session_get_peripheral(i)) + driver->p_hdlc_disabled[i] = + driver->hdlc_disabled; + } + } + mutex_unlock(&driver->md_session_lock); mutex_unlock(&driver->hdlc_disable_mutex); diag_update_md_clients(HDLC_SUPPORT_TYPE); @@ -2970,7 +3026,6 @@ static int diag_user_process_apps_data(const char __user *buf, int len, int stm_size = 0; const int mempool = POOL_TYPE_COPY; unsigned char *user_space_data = NULL; - struct diag_md_session_t *session_info = NULL; uint8_t hdlc_disabled; if (!buf || len <= 0 || len > DIAG_MAX_RSP_SIZE) { @@ -3024,13 +3079,7 @@ static int diag_user_process_apps_data(const char __user *buf, int len, mutex_lock(&apps_data_mutex); mutex_lock(&driver->hdlc_disable_mutex); - mutex_lock(&driver->md_session_lock); - session_info = diag_md_session_get_peripheral(APPS_DATA); - if (session_info) - hdlc_disabled = session_info->hdlc_disabled; - else - hdlc_disabled = driver->hdlc_disabled; - mutex_unlock(&driver->md_session_lock); + hdlc_disabled = driver->p_hdlc_disabled[APPS_DATA]; if (hdlc_disabled) ret = diag_process_apps_data_non_hdlc(user_space_data, len, pkt_type); diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c index f6027ae96833..c7b46304dc84 100644 --- a/drivers/char/diag/diagfwd.c +++ b/drivers/char/diag/diagfwd.c @@ -49,6 +49,11 @@ #define STM_RSP_STATUS_INDEX 8 #define STM_RSP_NUM_BYTES 9 +struct diag_md_hdlc_reset_work { + int pid; + struct work_struct work; +}; + static int timestamp_switch; module_param(timestamp_switch, int, 0644); @@ -436,6 +441,7 @@ static void diag_send_rsp(unsigned char *buf, int len, int pid) { struct diag_md_session_t *session_info = NULL, *info = NULL; uint8_t hdlc_disabled; + mutex_lock(&driver->md_session_lock); info = diag_md_session_get_pid(pid); session_info = (info) ? info : @@ -445,6 +451,7 @@ static void diag_send_rsp(unsigned char *buf, int len, int pid) else hdlc_disabled = driver->hdlc_disabled; mutex_unlock(&driver->md_session_lock); + if (hdlc_disabled) pack_rsp_and_send(buf, len, pid); else @@ -948,7 +955,7 @@ void diag_send_error_rsp(unsigned char *buf, int len, int diag_process_apps_pkt(unsigned char *buf, int len, int pid) { int i, p_mask = 0; - int mask_ret; + int mask_ret, peripheral = -EINVAL; int write_len = 0; unsigned char *temp = NULL; struct diag_cmd_reg_entry_t entry; @@ -1175,6 +1182,22 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid) info->hdlc_disabled = 1; else driver->hdlc_disabled = 1; + peripheral = + diag_md_session_match_pid_peripheral(pid, 0); + for (i = 0; i < NUM_MD_SESSIONS; i++) { + if (peripheral > 0 && info) { + if (peripheral & (1 << i)) + driver->p_hdlc_disabled[i] = + info->hdlc_disabled; + else if (!diag_md_session_get_peripheral(i)) + driver->p_hdlc_disabled[i] = + driver->hdlc_disabled; + } else { + if (!diag_md_session_get_peripheral(i)) + driver->p_hdlc_disabled[i] = + driver->hdlc_disabled; + } + } mutex_unlock(&driver->md_session_lock); diag_update_md_clients(HDLC_SUPPORT_TYPE); mutex_unlock(&driver->hdlc_disable_mutex); @@ -1350,8 +1373,17 @@ static int diagfwd_mux_close(int id, int mode) pr_debug("diag: In %s, re-enabling HDLC encoding\n", __func__); mutex_lock(&driver->hdlc_disable_mutex); - if (driver->md_session_mode == DIAG_MD_NONE) + if (driver->md_session_mode == DIAG_MD_NONE) { driver->hdlc_disabled = 0; + /* + * HDLC encoding is re-enabled when + * there is logical/physical disconnection of diag + * to USB. + */ + for (i = 0; i < NUM_MD_SESSIONS; i++) + driver->p_hdlc_disabled[i] = + driver->hdlc_disabled; + } mutex_unlock(&driver->hdlc_disable_mutex); queue_work(driver->diag_wq, &(driver->update_user_clients)); @@ -1366,6 +1398,7 @@ static uint8_t hdlc_reset; static void hdlc_reset_timer_start(int pid) { struct diag_md_session_t *info = NULL; + mutex_lock(&driver->md_session_lock); info = diag_md_session_get_pid(pid); if (!hdlc_timer_in_progress) { @@ -1380,30 +1413,99 @@ static void hdlc_reset_timer_start(int pid) mutex_unlock(&driver->md_session_lock); } +/* + * diag_timer_work_fn + * Queued in workqueue to protect md_session_info structure + * + * Update hdlc_disabled for each peripheral + * which are not in any md_session_info. + * + */ +static void diag_timer_work_fn(struct work_struct *work) +{ + int i = 0; + struct diag_md_session_t *session_info = NULL; + + mutex_lock(&driver->hdlc_disable_mutex); + driver->hdlc_disabled = 0; + mutex_lock(&driver->md_session_lock); + for (i = 0; i < NUM_MD_SESSIONS; i++) { + session_info = diag_md_session_get_peripheral(i); + if (!session_info) + driver->p_hdlc_disabled[i] = + driver->hdlc_disabled; + } + mutex_unlock(&driver->md_session_lock); + mutex_unlock(&driver->hdlc_disable_mutex); +} + +/* + * diag_md_timer_work_fn + * Queued in workqueue to protect md_session_info structure + * + * Update hdlc_disabled for each peripheral + * which are in any md_session_info + * + */ +static void diag_md_timer_work_fn(struct work_struct *work) +{ + int peripheral = -EINVAL, i = 0; + struct diag_md_session_t *session_info = NULL; + struct diag_md_hdlc_reset_work *hdlc_work = container_of(work, + struct diag_md_hdlc_reset_work, work); + + if (!hdlc_work) + return; + + mutex_lock(&driver->hdlc_disable_mutex); + mutex_lock(&driver->md_session_lock); + session_info = diag_md_session_get_pid(hdlc_work->pid); + if (session_info) + session_info->hdlc_disabled = 0; + peripheral = + diag_md_session_match_pid_peripheral(hdlc_work->pid, 0); + if (peripheral > 0 && session_info) { + for (i = 0; i < NUM_MD_SESSIONS; i++) { + if (peripheral & (1 << i)) + driver->p_hdlc_disabled[i] = + session_info->hdlc_disabled; + } + } + kfree(hdlc_work); + mutex_unlock(&driver->md_session_lock); + mutex_unlock(&driver->hdlc_disable_mutex); +} + static void hdlc_reset_timer_func(unsigned long data) { pr_debug("diag: In %s, re-enabling HDLC encoding\n", __func__); + if (hdlc_reset) { - driver->hdlc_disabled = 0; - queue_work(driver->diag_wq, - &(driver->update_user_clients)); + queue_work(driver->diag_wq, &(driver->diag_hdlc_reset_work)); + queue_work(driver->diag_wq, &(driver->update_user_clients)); } hdlc_timer_in_progress = 0; } void diag_md_hdlc_reset_timer_func(unsigned long pid) { - struct diag_md_session_t *session_info = NULL; + struct diag_md_hdlc_reset_work *hdlc_reset_work = NULL; pr_debug("diag: In %s, re-enabling HDLC encoding\n", __func__); + hdlc_reset_work = kmalloc(sizeof(*hdlc_reset_work), GFP_ATOMIC); + if (!hdlc_reset_work) { + DIAG_LOG(DIAG_DEBUG_PERIPHERALS, + "diag: Could not allocate hdlc_reset_work\n"); + hdlc_timer_in_progress = 0; + return; + } if (hdlc_reset) { - session_info = diag_md_session_get_pid(pid); - if (session_info) - session_info->hdlc_disabled = 0; - queue_work(driver->diag_wq, - &(driver->update_md_clients)); + hdlc_reset_work->pid = pid; + INIT_WORK(&hdlc_reset_work->work, diag_md_timer_work_fn); + queue_work(driver->diag_wq, &(hdlc_reset_work->work)); + queue_work(driver->diag_wq, &(driver->update_md_clients)); } hdlc_timer_in_progress = 0; } @@ -1411,7 +1513,7 @@ void diag_md_hdlc_reset_timer_func(unsigned long pid) static void diag_hdlc_start_recovery(unsigned char *buf, int len, int pid) { - int i; + int i, peripheral = -EINVAL; static uint32_t bad_byte_counter; unsigned char *start_ptr = NULL; struct diag_pkt_frame_t *actual_pkt = NULL; @@ -1443,6 +1545,24 @@ static void diag_hdlc_start_recovery(unsigned char *buf, int len, info->hdlc_disabled = 0; else driver->hdlc_disabled = 0; + + peripheral = + diag_md_session_match_pid_peripheral(pid, 0); + for (i = 0; i < NUM_MD_SESSIONS; i++) { + if (peripheral > 0 && info) { + if (peripheral & (1 << i)) + driver->p_hdlc_disabled[i] = + info->hdlc_disabled; + else if ( + !diag_md_session_get_peripheral(i)) + driver->p_hdlc_disabled[i] = + driver->hdlc_disabled; + } else { + if (!diag_md_session_get_peripheral(i)) + driver->p_hdlc_disabled[i] = + driver->hdlc_disabled; + } + } mutex_unlock(&driver->md_session_lock); mutex_unlock(&driver->hdlc_disable_mutex); diag_update_md_clients(HDLC_SUPPORT_TYPE); @@ -1700,6 +1820,8 @@ int diagfwd_init(void) INIT_LIST_HEAD(&driver->cmd_reg_list); driver->cmd_reg_count = 0; mutex_init(&driver->cmd_reg_mutex); + INIT_WORK(&(driver->diag_hdlc_reset_work), + diag_timer_work_fn); for (i = 0; i < NUM_PERIPHERALS; i++) { driver->feature[i].separate_cmd_rsp = 0; diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c index a7abe3dafb69..6b74c0056d1b 100644 --- a/drivers/char/diag/diagfwd_peripheral.c +++ b/drivers/char/diag/diagfwd_peripheral.c @@ -284,7 +284,6 @@ static void diagfwd_data_process_done(struct diagfwd_info *fwd_info, int err = 0; int write_len = 0, peripheral = 0; unsigned char *write_buf = NULL; - struct diag_md_session_t *session_info = NULL; uint8_t hdlc_disabled = 0; if (!fwd_info || !buf || len <= 0) { @@ -316,13 +315,9 @@ static void diagfwd_data_process_done(struct diagfwd_info *fwd_info, diag_ws_release(); return; } - mutex_lock(&driver->md_session_lock); - session_info = diag_md_session_get_peripheral(peripheral); - if (session_info) - hdlc_disabled = session_info->hdlc_disabled; - else - hdlc_disabled = driver->hdlc_disabled; - mutex_unlock(&driver->md_session_lock); + + hdlc_disabled = driver->p_hdlc_disabled[peripheral]; + if (hdlc_disabled) { /* The data is raw and and on APPS side HDLC is disabled */ if (!buf) { @@ -615,7 +610,6 @@ static void diagfwd_data_read_done(struct diagfwd_info *fwd_info, int write_len = 0; unsigned char *write_buf = NULL; struct diagfwd_buf_t *temp_buf = NULL; - struct diag_md_session_t *session_info = NULL; uint8_t hdlc_disabled = 0; if (!fwd_info || !buf || len <= 0) { @@ -637,13 +631,9 @@ static void diagfwd_data_read_done(struct diagfwd_info *fwd_info, mutex_lock(&driver->hdlc_disable_mutex); mutex_lock(&fwd_info->data_mutex); - mutex_lock(&driver->md_session_lock); - session_info = diag_md_session_get_peripheral(fwd_info->peripheral); - if (session_info) - hdlc_disabled = session_info->hdlc_disabled; - else - hdlc_disabled = driver->hdlc_disabled; - mutex_unlock(&driver->md_session_lock); + + hdlc_disabled = driver->p_hdlc_disabled[fwd_info->peripheral]; + if (!driver->feature[fwd_info->peripheral].encode_hdlc) { if (fwd_info->buf_1 && fwd_info->buf_1->data == buf) { temp_buf = fwd_info->buf_1; |