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

Commit 1c0a616a authored by Hardik Arya's avatar Hardik Arya
Browse files

diag: Close the read when buffer is already marked free



Currently there is a possibility of reading the data for
read queued by md session which is already closed and buffer
is marked free. The patch adds check for buffer busy status
and close the read thread if buffer is marked free. The patch
also modify the checks for keeping buffer busy for multi logging
mode at starting of session.

CRs-Fixed: 2203013
Change-Id: If97cf3c64fa6cbc4a496b6ca1ee4471e4e336012
Signed-off-by: default avatarHardik Arya <harya@codeaurora.org>
parent 463d8c28
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-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
@@ -257,7 +257,8 @@ struct diag_glink_info glink_dci_cmd[NUM_PERIPHERALS] = {
static void diag_state_open_glink(void *ctxt);
static void diag_state_close_glink(void *ctxt);
static int diag_glink_write(void *ctxt, unsigned char *buf, int len);
static int diag_glink_read(void *ctxt, unsigned char *buf, int buf_len);
static int diag_glink_read(void *ctxt, unsigned char *buf, int buf_len,
			struct diagfwd_buf_t *fwd_buf);
static void diag_glink_queue_read(void *ctxt);

static struct diag_peripheral_ops glink_ops = {
@@ -320,7 +321,8 @@ int diag_glink_check_state(void *ctxt)
	return (int)(atomic_read(&info->diag_state));
}

static int diag_glink_read(void *ctxt, unsigned char *buf, int buf_len)
static int diag_glink_read(void *ctxt, unsigned char *buf, int buf_len,
			struct diagfwd_buf_t *fwd_buf)
{
	struct diag_glink_info *glink_info =  NULL;
	int ret_val = 0;
+4 −4
Original line number Diff line number Diff line
@@ -1286,11 +1286,10 @@ static void __diag_fwd_open(struct diagfwd_info *fwd_info)
	 * Logging mode here is reflecting previous mode
	 * status and will be updated to new mode later.
	 *
	 * Keeping the buffers busy for Memory Device Mode.
	 * Keeping the buffers busy for Memory Device and Multi Mode.
	 */

	if ((driver->logging_mode != DIAG_USB_MODE) ||
		driver->usb_connected) {
	if (driver->logging_mode != DIAG_USB_MODE) {
		if (fwd_info->buf_1) {
			atomic_set(&fwd_info->buf_1->in_busy, 0);
			DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
@@ -1701,7 +1700,8 @@ void diagfwd_channel_read(struct diagfwd_info *fwd_info)

	DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "issued a read p: %d t: %d buf: %pK\n",
		 fwd_info->peripheral, fwd_info->type, read_buf);
	err = fwd_info->p_ops->read(fwd_info->ctxt, read_buf, read_len);
	err = fwd_info->p_ops->read(fwd_info->ctxt, read_buf, read_len,
			temp_buf);
	if (err)
		goto fail_return;

+3 −2
Original line number Diff line number Diff line
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-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
@@ -65,7 +65,8 @@ struct diag_peripheral_ops {
	void (*open)(void *ctxt);
	void (*close)(void *ctxt);
	int (*write)(void *ctxt, unsigned char *buf, int len);
	int (*read)(void *ctxt, unsigned char *buf, int len);
	int (*read)(void *ctxt, unsigned char *buf, int len,
			struct diagfwd_buf_t *fwd_buf);
	void (*queue_read)(void *ctxt);
};

+15 −5
Original line number Diff line number Diff line
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-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
@@ -198,7 +198,8 @@ static void diag_state_open_smd(void *ctxt);
static void diag_state_close_smd(void *ctxt);
static void smd_notify(void *ctxt, unsigned int event);
static int diag_smd_write(void *ctxt, unsigned char *buf, int len);
static int diag_smd_read(void *ctxt, unsigned char *buf, int buf_len);
static int diag_smd_read(void *ctxt, unsigned char *buf, int buf_len,
			struct diagfwd_buf_t *fwd_buf);
static void diag_smd_queue_read(void *ctxt);

static struct diag_peripheral_ops smd_ops = {
@@ -780,7 +781,8 @@ static int diag_smd_write(void *ctxt, unsigned char *buf, int len)
	return 0;
}

static int diag_smd_read(void *ctxt, unsigned char *buf, int buf_len)
static int diag_smd_read(void *ctxt, unsigned char *buf, int buf_len,
			struct diagfwd_buf_t *fwd_buf)
{
	int pkt_len = 0;
	int err = 0;
@@ -791,7 +793,7 @@ static int diag_smd_read(void *ctxt, unsigned char *buf, int buf_len)
	uint32_t read_len = 0;
	struct diag_smd_info *smd_info = NULL;

	if (!ctxt || !buf || buf_len <= 0)
	if (!ctxt || !buf || buf_len <= 0 || !fwd_buf)
		return -EIO;

	smd_info = (struct diag_smd_info *)ctxt;
@@ -810,7 +812,15 @@ static int diag_smd_read(void *ctxt, unsigned char *buf, int buf_len)
		diagfwd_channel_read_done(smd_info->fwd_ctxt, buf, 0);
		return -ERESTARTSYS;
	}

	if (atomic_read(&fwd_buf->in_busy) == 0) {
		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
			"%s closing read thread. Buffer is already marked freed p: %d t: %d buf_num: %d\n",
			 smd_info->name, GET_BUF_PERIPHERAL(fwd_buf->ctxt),
			 GET_BUF_TYPE(fwd_buf->ctxt),
			 GET_BUF_NUM(fwd_buf->ctxt));
		diag_ws_release();
		return 0;
	}
	/*
	 * Reset the buffers. Also release the wake source hold earlier.
	 */
+18 −15
Original line number Diff line number Diff line
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-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
@@ -224,7 +224,8 @@ struct diag_socket_info socket_dci_cmd[NUM_PERIPHERALS] = {
static void diag_state_open_socket(void *ctxt);
static void diag_state_close_socket(void *ctxt);
static int diag_socket_write(void *ctxt, unsigned char *buf, int len);
static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len);
static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len,
			struct diagfwd_buf_t *fwd_buf);
static void diag_socket_queue_read(void *ctxt);
static void socket_init_work_fn(struct work_struct *work);
static int socket_ready_notify(struct notifier_block *nb,
@@ -1062,7 +1063,8 @@ void diag_socket_exit(void)
	}
}

static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len,
			struct diagfwd_buf_t *fwd_buf)
{
	int err = 0;
	int pkt_len = 0;
@@ -1082,7 +1084,7 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
	if (!info)
		return -ENODEV;

	if (!buf || !ctxt || buf_len <= 0)
	if (!buf || !ctxt || buf_len <= 0 || !fwd_buf)
		return -EINVAL;

	temp = buf;
@@ -1091,13 +1093,17 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
	err = wait_event_interruptible(info->read_wait_q,
				      (info->data_ready > 0) || (!info->hdl) ||
				      (atomic_read(&info->diag_state) == 0));
	if (err) {
		mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
		diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
		mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
		return -ERESTARTSYS;
	if (err)
		goto fail;
	if (atomic_read(&fwd_buf->in_busy) == 0) {
		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
			"%s closing read thread. Buffer is already marked freed p: %d t: %d buf_num: %d\n",
			 info->name, GET_BUF_PERIPHERAL(fwd_buf->ctxt),
			 GET_BUF_TYPE(fwd_buf->ctxt),
			 GET_BUF_NUM(fwd_buf->ctxt));
		diag_ws_release();
		return 0;
	}

	/*
	 * There is no need to continue reading over peripheral in this case.
	 * Release the wake source hold earlier.
@@ -1106,10 +1112,7 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
			 "%s closing read thread. diag state is closed\n",
			 info->name);
		mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
		diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
		mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
		return 0;
		goto fail;
	}

	if (!info->hdl) {
@@ -1211,7 +1214,7 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
	mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
	diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
	mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
	return -EIO;
	return 0;
}

static int diag_socket_write(void *ctxt, unsigned char *buf, int len)