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>
This commit is contained in:
Manoj Prabhu B 2018-03-14 14:53:52 +05:30 committed by Gerrit - the friendly Code Review server
parent bb9c0e0ec8
commit 43f15aca94
4 changed files with 218 additions and 54 deletions

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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;