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

Commit 00a92746 authored by Ravi Aravamudhan's avatar Ravi Aravamudhan
Browse files

diag: Release wakeup sources correctly



Diag driver is not releasing the wakeup source objects in some
corner error cases. This patch tries to release the wakeup source
objects in those conditions.

Change-Id: Icbc8f4126c8447afe71fb97c1ea13626fb6991d6
Signed-off-by: default avatarRavi Aravamudhan <aravamud@codeaurora.org>
parent cdecac51
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -325,6 +325,7 @@ int diag_usb_write(int id, unsigned char *buf, int len, int ctxt)
	if (err) {
		pr_err_ratelimited("diag: In %s, error writing to usb channel %s, err: %d\n",
				   __func__, usb_info->name, err);
		diag_ws_on_copy_fail(DIAG_WS_MUX);
		diagmem_free(driver, req, usb_info->mempool);
	}

+21 −8
Original line number Diff line number Diff line
@@ -219,8 +219,10 @@ static void diagfwd_data_read_done(struct diagfwd_info *fwd_info,
	unsigned char *write_buf = NULL;
	struct diagfwd_buf_t *temp_buf = NULL;

	if (!fwd_info || !buf || len <= 0)
	if (!fwd_info || !buf || len <= 0) {
		diag_ws_release();
		return;
	}

	switch (fwd_info->type) {
	case TYPE_DATA:
@@ -230,6 +232,7 @@ static void diagfwd_data_read_done(struct diagfwd_info *fwd_info,
		pr_err_ratelimited("diag: In %s, invalid type %d for peripheral %d\n",
				   __func__, fwd_info->type,
				   fwd_info->peripheral);
		diag_ws_release();
		return;
	}

@@ -301,7 +304,6 @@ static void diagfwd_data_read_done(struct diagfwd_info *fwd_info,
		if (err) {
			pr_err_ratelimited("diag: In %s, unable to write to mux error: %d\n",
					   __func__, err);
			diag_ws_release();
			goto end;
		}
	}
@@ -311,6 +313,7 @@ static void diagfwd_data_read_done(struct diagfwd_info *fwd_info,
	return;

end:
	diag_ws_release();
	mutex_unlock(&fwd_info->data_mutex);
	mutex_unlock(&driver->hdlc_disable_mutex);
	if (temp_buf) {
@@ -324,12 +327,15 @@ end:
static void diagfwd_cntl_read_done(struct diagfwd_info *fwd_info,
				   unsigned char *buf, int len)
{
	if (!fwd_info)
	if (!fwd_info) {
		diag_ws_release();
		return;
	}

	if (fwd_info->type != TYPE_CNTL) {
		pr_err("diag: In %s, invalid type %d for peripheral %d\n",
		       __func__, fwd_info->type, fwd_info->peripheral);
		diag_ws_release();
		return;
	}

@@ -808,17 +814,19 @@ int diagfwd_channel_close(struct diagfwd_info *fwd_info)
int diagfwd_channel_read_done(struct diagfwd_info *fwd_info,
			      unsigned char *buf, uint32_t len)
{
	if (!fwd_info)
	if (!fwd_info) {
		diag_ws_release();
		return -EIO;
	}

	/*
	 * Diag peripheral layers should send len as 0 if there is any error
	 * in reading data from the transport. Use this information to reset the
	 * in_busy flags and to queue a read again.
	 * in_busy flags. No need to queue read in this case.
	 */
	if (len == 0) {
		diagfwd_reset_buffers(fwd_info, buf);
		diagfwd_queue_read(fwd_info);
		diag_ws_release();
		return 0;
	}

@@ -854,8 +862,10 @@ void diagfwd_channel_read(struct diagfwd_info *fwd_info)
	unsigned char *read_buf = NULL;
	struct diagfwd_buf_t *temp_buf = NULL;

	if (!fwd_info)
	if (!fwd_info) {
		diag_ws_release();
		return;
	}

	if (!fwd_info->inited || !atomic_read(&fwd_info->opened)) {
		pr_debug("diag: In %s, p: %d, t: %d, inited: %d, opened: %d  ch_open: %d\n",
@@ -895,8 +905,10 @@ void diagfwd_channel_read(struct diagfwd_info *fwd_info)
			 __func__, fwd_info->peripheral, fwd_info->type);
	}

	if (!read_buf)
	if (!read_buf) {
		diag_ws_release();
		return;
	}

	if (!(fwd_info->p_ops && fwd_info->p_ops->read && fwd_info->ctxt))
		goto fail_return;
@@ -910,6 +922,7 @@ void diagfwd_channel_read(struct diagfwd_info *fwd_info)
	return;

fail_return:
	diag_ws_release();
	atomic_set(&temp_buf->in_busy, 0);
	return;
}
+9 −2
Original line number Diff line number Diff line
@@ -395,8 +395,10 @@ static void smd_read_work_fn(struct work_struct *work)
	struct diag_smd_info *smd_info = container_of(work,
						      struct diag_smd_info,
						      read_work);
	if (!smd_info->inited)
	if (!smd_info->inited) {
		diag_ws_release();
		return;
	}

	diagfwd_channel_read(smd_info->fwd_ctxt);
}
@@ -721,10 +723,15 @@ static int diag_smd_read(void *ctxt, unsigned char *buf, int buf_len)
				(smd_cur_packet_size(smd_info->hdl)) ||
				(atomic_read(&smd_info->diag_state) == 0));

	/*
	 * In this case don't reset the buffers as there is no need to further
	 * read over peripherals. Also release the wake source hold earlier.
	 */
	if (atomic_read(&smd_info->diag_state) == 0) {
		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
			 "%s closing read thread. diag state is closed\n",
			 smd_info->name);
		diag_ws_release();
		return 0;
	}

@@ -774,7 +781,7 @@ static int diag_smd_read(void *ctxt, unsigned char *buf, int buf_len)
		}
	} while (pkt_len > 0);

	if (smd_info->type == TYPE_DATA || buf_full)
	if ((smd_info->type == TYPE_DATA && pkt_len) || buf_full)
		err = queue_work(smd_info->wq, &(smd_info->read_work));

	if (total_recd > 0) {
+6 −1
Original line number Diff line number Diff line
@@ -870,10 +870,15 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
	wait_event(info->read_wait_q, (info->data_ready > 0) || (!info->hdl) ||
		   (atomic_read(&info->diag_state) == 0));

	/*
	 * There is no need to continue reading over peripheral in this case.
	 * Release the wake source hold earlier.
	 */
	if (atomic_read(&info->diag_state) == 0) {
		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
			 "%s closing read thread. diag state is closed\n",
			 info->name);
		diag_ws_release();
		return 0;
	}

@@ -934,7 +939,7 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
		bytes_remaining -= read_len;
	} while (info->data_ready > 0);

	if (buf_full || info->type == TYPE_DATA)
	if (buf_full || (info->type == TYPE_DATA && pkt_len))
		err = queue_work(info->wq, &(info->read_work));

	if (total_recd > 0) {