Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 43f15aca authored by Manoj Prabhu B's avatar Manoj Prabhu B Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarManoj Prabhu B <bmanoj@codeaurora.org>
parent bb9c0e0e
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
/* 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
+74 −25
Original line number Diff line number Diff line
@@ -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);
+134 −12
Original line number Diff line number Diff line
@@ -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;
+6 −16
Original line number Diff line number Diff line
@@ -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;