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

Commit bbd37e68 authored by Dilip Kota's avatar Dilip Kota Committed by Sagar Dharia
Browse files

slim_msm: Reorganise Rx/Tx tear-down during DSP-SSR



Rx/Tx pipe resources are freed during DSP down.
Simultaneously BAM ISR due to Rx/Tx interrupt
may access the Rx/Tx pipe resources leading to
pagingfault.
To overcome this, Rx/Tx activity is reorganised by
disabling the interrupt during ADSP down and
freeing, allocating resources during ADSP up.

Change-Id: Id1b77a05a042ef9ca194f78e700670edf6146db6
Signed-off-by: default avatarDilip Kota <dkota@codeaurora.org>
parent c57b8e5f
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011-2015, 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
@@ -1390,6 +1390,10 @@ err_request_irq_failed:
	kthread_stop(dev->rx_msgq_thread);
err_thread_create_failed:
	msm_slim_sps_exit(dev, true);
	msm_slim_deinit_ep(dev, &dev->rx_msgq,
				&dev->use_rx_msgqs);
	msm_slim_deinit_ep(dev, &dev->tx_msgq,
				&dev->use_tx_msgqs);
err_sps_init_failed:
	if (dev->hclk) {
		clk_disable_unprepare(dev->hclk);
@@ -1435,6 +1439,11 @@ static int msm_slim_remove(struct platform_device *pdev)
	if (dev->hclk)
		clk_put(dev->hclk);
	msm_slim_sps_exit(dev, true);
	msm_slim_deinit_ep(dev, &dev->rx_msgq,
				&dev->use_rx_msgqs);
	msm_slim_deinit_ep(dev, &dev->tx_msgq,
				&dev->use_tx_msgqs);

	kthread_stop(dev->rx_msgq_thread);
	iounmap(dev->bam.base);
	iounmap(dev->base);
+3 −3
Original line number Diff line number Diff line
@@ -576,15 +576,15 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
							i, *(pbuf + i));
			if (idx < MSM_TX_BUFS)
				dev->wr_comp[idx] = NULL;
			/* print BAM debug info for TX pipe */
			sps_get_bam_debug_info(dev->bam.hdl, 93,
						SPS_BAM_PIPE(4), 0, 2);
			/*
			 * disconnect/recoonect pipe so that subsequent
			 * transactions don't timeout due to unavailable
			 * descriptors
			 */
			if (dev->state != MSM_CTRL_DOWN) {
				/* print BAM debug info for TX pipe */
				sps_get_bam_debug_info(dev->bam.hdl, 93,
							SPS_BAM_PIPE(4), 0, 2);
				msm_slim_disconnect_endp(dev, &dev->tx_msgq,
							&dev->use_tx_msgqs);
				msm_slim_connect_endp(dev, &dev->tx_msgq);
+52 −9
Original line number Diff line number Diff line
@@ -178,7 +178,11 @@ int msm_slim_sps_mem_alloc(
void
msm_slim_sps_mem_free(struct msm_slim_ctrl *dev, struct sps_mem_buffer *mem)
{
	dma_free_coherent(dev->dev, mem->size, mem->base, mem->phys_base);
	if (mem->base && mem->phys_base)
		dma_free_coherent(dev->dev, mem->size, mem->base,
							mem->phys_base);
	 else
		dev_err(dev->dev, "cant dma free. they are NULL\n");
	mem->size = 0;
	mem->base = NULL;
	mem->phys_base = 0;
@@ -1039,6 +1043,22 @@ void msm_slim_disconnect_endp(struct msm_slim_ctrl *dev,
	}
}

static int msm_slim_discard_rx_data(struct msm_slim_ctrl *dev,
					struct msm_slim_endp *endpoint)
{
	struct sps_iovec sio;
	int desc_num = 0, ret = 0;

	ret = sps_get_unused_desc_num(endpoint->sps, &desc_num);
	if (ret) {
		dev_err(dev->dev, "sps_get_iovec() failed 0x%x\n", ret);
		return ret;
	}
	while (desc_num--)
		sps_get_iovec(endpoint->sps, &sio);
	return ret;
}

static void msm_slim_remove_ep(struct msm_slim_ctrl *dev,
					struct msm_slim_endp *endpoint,
					enum msm_slim_msgq *msgq_flag)
@@ -1046,15 +1066,37 @@ static void msm_slim_remove_ep(struct msm_slim_ctrl *dev,
	struct sps_connect *config = &endpoint->config;
	struct sps_mem_buffer *descr = &config->desc;
	struct sps_mem_buffer *mem = &endpoint->buf;
	struct sps_register_event sps_event;
	memset(&sps_event, 0x00, sizeof(sps_event));

	msm_slim_sps_mem_free(dev, mem);
	sps_register_event(endpoint->sps, &sps_event);
	if (*msgq_flag == MSM_MSGQ_ENABLED) {
	if (*msgq_flag == MSM_MSGQ_ENABLED)
		msm_slim_disconnect_endp(dev, endpoint, msgq_flag);
	msm_slim_sps_mem_free(dev, descr);
	msm_slim_free_endpoint(endpoint);
}
	msm_slim_sps_mem_free(dev, descr);

void msm_slim_deinit_ep(struct msm_slim_ctrl *dev,
				struct msm_slim_endp *endpoint,
				enum msm_slim_msgq *msgq_flag)
{
	int ret = 0;
	struct sps_connect *config = &endpoint->config;

	if (config->mode == SPS_MODE_SRC) {
		ret = msm_slim_discard_rx_data(dev, endpoint);
		if (ret)
			SLIM_WARN(dev, "discarding Rx data failed\n");
	}
	msm_slim_disconnect_endp(dev, endpoint, msgq_flag);
	msm_slim_remove_ep(dev, endpoint, msgq_flag);
}

static void msm_slim_sps_unreg_event(struct sps_pipe *sps)
{
	struct sps_register_event sps_event;

	memset(&sps_event, 0x00, sizeof(sps_event));
	/* Disable interrupt and signal notification for Rx/Tx pipe */
	sps_register_event(sps, &sps_event);
}

void msm_slim_sps_exit(struct msm_slim_ctrl *dev, bool dereg)
@@ -1062,9 +1104,10 @@ void msm_slim_sps_exit(struct msm_slim_ctrl *dev, bool dereg)
	int i;

	if (dev->use_rx_msgqs >= MSM_MSGQ_ENABLED)
		msm_slim_remove_ep(dev, &dev->rx_msgq, &dev->use_rx_msgqs);
		msm_slim_sps_unreg_event(dev->rx_msgq.sps);
	if (dev->use_tx_msgqs >= MSM_MSGQ_ENABLED)
		msm_slim_remove_ep(dev, &dev->tx_msgq, &dev->use_tx_msgqs);
		msm_slim_sps_unreg_event(dev->tx_msgq.sps);

	for (i = 0; i < dev->port_nums; i++) {
		if (dev->pipes[i].connected)
			msm_slim_disconn_pipe_port(dev, i);
+4 −0
Original line number Diff line number Diff line
@@ -405,6 +405,10 @@ int msm_slim_connect_endp(struct msm_slim_ctrl *dev,
void msm_slim_disconnect_endp(struct msm_slim_ctrl *dev,
					struct msm_slim_endp *endpoint,
					enum msm_slim_msgq *msgq_flag);
void msm_slim_deinit_ep(struct msm_slim_ctrl *dev,
				struct msm_slim_endp *endpoint,
				enum msm_slim_msgq *msgq_flag);

void msm_slim_qmi_exit(struct msm_slim_ctrl *dev);
int msm_slim_qmi_init(struct msm_slim_ctrl *dev, bool apps_is_master);
int msm_slim_qmi_power_request(struct msm_slim_ctrl *dev, bool active);