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

Commit de0cb0e2 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "slim_msm: Optimize RX path for slimbus"

parents 84482e95 fc6d2018
Loading
Loading
Loading
Loading
+61 −92
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ enum ngd_status {
	NGD_LADDR		= 1 << 1,
};

static void ngd_slim_rx(struct msm_slim_ctrl *dev, u8 *buf);
static int ngd_slim_runtime_resume(struct device *device);
static int ngd_slim_power_up(struct msm_slim_ctrl *dev, bool mdm_restart);

@@ -122,7 +123,7 @@ static irqreturn_t ngd_slim_interrupt(int irq, void *d)
						(4 * i));
			SLIM_DBG(dev, "REG-RX data: %x\n", rx_buf[i]);
		}
		msm_slim_rx_enqueue(dev, rx_buf, len);
		ngd_slim_rx(dev, (u8 *)rx_buf);
		writel_relaxed(NGD_INT_RX_MSG_RCVD,
				ngd + NGD_INT_CLR);
		/*
@@ -132,8 +133,6 @@ static irqreturn_t ngd_slim_interrupt(int irq, void *d)
		mb();
		if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
			SLIM_WARN(dev, "direct msg rcvd with RX MSGQs\n");
		else
			complete(&dev->rx_msgq_notify);
	}
	if (stat & NGD_INT_RECFG_DONE) {
		writel_relaxed(NGD_INT_RECFG_DONE, ngd + NGD_INT_CLR);
@@ -588,7 +587,7 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
			if (dev->state != MSM_CTRL_DOWN) {
				msm_slim_disconnect_endp(dev, &dev->tx_msgq,
							&dev->use_tx_msgqs);
				msm_slim_connect_endp(dev, &dev->tx_msgq, NULL);
				msm_slim_connect_endp(dev, &dev->tx_msgq);
			}
		} else if (!timeout) {
			ret = -ETIMEDOUT;
@@ -907,8 +906,7 @@ static void ngd_slim_setup_msg_path(struct msm_slim_ctrl *dev)
			SLIM_WARN(dev, "pipe setup when RX msgq enabled?");
			goto setup_tx_msg_path;
		}
		msm_slim_connect_endp(dev, &dev->rx_msgq,
				&dev->rx_msgq_notify);
		msm_slim_connect_endp(dev, &dev->rx_msgq);

setup_tx_msg_path:
		if (dev->use_tx_msgqs == MSM_MSGQ_DISABLED)
@@ -917,74 +915,21 @@ setup_tx_msg_path:
			SLIM_WARN(dev, "pipe setup when TX msgq enabled?");
			return;
		}
		msm_slim_connect_endp(dev, &dev->tx_msgq,
				NULL);
		msm_slim_connect_endp(dev, &dev->tx_msgq);
	}
}

static void ngd_slim_rx(struct msm_slim_ctrl *dev, u8 *buf)
{
	u8 mc, mt, len;
	int ret;
	u32 msgq_en = 1;

	len = buf[0] & 0x1F;
	mt = (buf[0] >> 5) & 0x7;
	mc = buf[1];
	if (mc == SLIM_USR_MC_MASTER_CAPABILITY &&
		mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
		struct slim_msg_txn txn;
		int retries = 0;
		u8 wbuf[8];
		txn.dt = SLIM_MSG_DEST_LOGICALADDR;
		txn.ec = 0;
		txn.rbuf = NULL;
		txn.mc = SLIM_USR_MC_REPORT_SATELLITE;
		txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
		txn.la = SLIM_LA_MGR;
		wbuf[0] = SAT_MAGIC_LSB;
		wbuf[1] = SAT_MAGIC_MSB;
		wbuf[2] = SAT_MSG_VER;
		wbuf[3] = SAT_MSG_PROT;
		txn.wbuf = wbuf;
		txn.len = 4;
		SLIM_INFO(dev, "SLIM SAT: Rcvd master capability\n");
		if (dev->state >= MSM_CTRL_ASLEEP) {
			ngd_slim_setup_msg_path(dev);
			if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
				msgq_en |= NGD_CFG_RX_MSGQ_EN;
			if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
				msgq_en |= NGD_CFG_TX_MSGQ_EN;
			writel_relaxed(msgq_en, dev->base +
					NGD_BASE(dev->ctrl.nr, dev->ver));
			/* make sure NGD MSG-Q config goes through */
			mb();
		}
capability_retry:
		txn.rl = 8;
		ret = ngd_xfer_msg(&dev->ctrl, &txn);
		if (!ret) {
			enum msm_ctrl_state prev_state = dev->state;
			SLIM_INFO(dev,
				"SLIM SAT: capability exchange successful\n");
			if (prev_state >= MSM_CTRL_ASLEEP)
				complete(&dev->reconf);
			else
				SLIM_ERR(dev,
					"SLIM: unexpected capability, state:%d\n",
						prev_state);
			/* ADSP SSR, send device_up notifications */
			if (prev_state == MSM_CTRL_DOWN)
				complete(&dev->qmi.slave_notify);
		} else if (ret == -EIO) {
			SLIM_WARN(dev, "capability message NACKed, retrying\n");
			if (retries < INIT_MX_RETRIES) {
				msleep(DEF_RETRY_MS);
				retries++;
				goto capability_retry;
			}
		}
	}
		mt == SLIM_MSG_MT_SRC_REFERRED_USER)
		complete(&dev->rx_msgq_notify);

	if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
			mc == SLIM_MSG_MC_REPLY_VALUE) {
		u8 tid = buf[3];
@@ -1193,43 +1138,66 @@ static int ngd_slim_rx_msgq_thread(void *data)
{
	struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)data;
	struct completion *notify = &dev->rx_msgq_notify;
	int ret = 0, index = 0;
	u32 mc = 0;
	u32 mt = 0;
	u32 buffer[10];
	u8 msg_len = 0;
	int ret = 0;
	u32 msgq_en = 1;

	while (!kthread_should_stop()) {
		struct slim_msg_txn txn;
		int retries = 0;
		u8 wbuf[8];

		set_current_state(TASK_INTERRUPTIBLE);
		wait_for_completion(notify);
		/* 1 irq notification per message */
		if (dev->use_rx_msgqs != MSM_MSGQ_ENABLED) {
			msm_slim_rx_dequeue(dev, (u8 *)buffer);
			ngd_slim_rx(dev, (u8 *)buffer);
			continue;
		}
		do {
			ret = msm_slim_rx_msgq_get(dev, buffer, index);
			if (ret) {
				SLIM_ERR(dev, "rx_msgq_get() failed 0x%x\n",
									ret);
				break;

		txn.dt = SLIM_MSG_DEST_LOGICALADDR;
		txn.ec = 0;
		txn.rbuf = NULL;
		txn.mc = SLIM_USR_MC_REPORT_SATELLITE;
		txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
		txn.la = SLIM_LA_MGR;
		wbuf[0] = SAT_MAGIC_LSB;
		wbuf[1] = SAT_MAGIC_MSB;
		wbuf[2] = SAT_MSG_VER;
		wbuf[3] = SAT_MSG_PROT;
		txn.wbuf = wbuf;
		txn.len = 4;
		SLIM_INFO(dev, "SLIM SAT: Rcvd master capability\n");
		if (dev->state >= MSM_CTRL_ASLEEP) {
			ngd_slim_setup_msg_path(dev);
			if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
				msgq_en |= NGD_CFG_RX_MSGQ_EN;
			if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
				msgq_en |= NGD_CFG_TX_MSGQ_EN;
			writel_relaxed(msgq_en, dev->base +
					NGD_BASE(dev->ctrl.nr, dev->ver));
			/* make sure NGD MSG-Q config goes through */
			mb();
		}
capability_retry:
		txn.rl = 8;
		ret = ngd_xfer_msg(&dev->ctrl, &txn);
		if (!ret) {
			enum msm_ctrl_state prev_state = dev->state;

			/* Traverse first byte of message for message length */
			if (index++ == 0) {
				msg_len = *buffer & 0x1F;
				mt = (buffer[0] >> 5) & 0x7;
				mc = (buffer[0] >> 8) & 0xff;
				dev_dbg(dev->dev, "MC: %x, MT: %x\n", mc, mt);
			SLIM_INFO(dev,
				"SLIM SAT: capability exchange successful\n");
			if (prev_state >= MSM_CTRL_ASLEEP)
				complete(&dev->reconf);
			else
				SLIM_ERR(dev,
					"SLIM: unexpected capability, state:%d\n",
						prev_state);
			/* ADSP SSR, send device_up notifications */
			if (prev_state == MSM_CTRL_DOWN)
				complete(&dev->qmi.slave_notify);
		} else if (ret == -EIO) {
			SLIM_WARN(dev, "capability message NACKed, retrying\n");
			if (retries < INIT_MX_RETRIES) {
				msleep(DEF_RETRY_MS);
				retries++;
				goto capability_retry;
			}
			msg_len = (msg_len < 4) ? 0 : (msg_len - 4);
		} while (msg_len);
		if (!msg_len) {
			index = 0;
			ngd_slim_rx(dev, (u8 *)buffer);
		}
		continue;
	}
	return 0;
}
@@ -1459,6 +1427,7 @@ static int ngd_slim_probe(struct platform_device *pdev)
	dev->ctrl.port_xfer = msm_slim_port_xfer;
	dev->ctrl.port_xfer_status = msm_slim_port_xfer_status;
	dev->bam_mem = bam_mem;
	dev->rx_slim = ngd_slim_rx;

	init_completion(&dev->reconf);
	init_completion(&dev->ctrl_up);
+45 −25
Original line number Diff line number Diff line
@@ -578,33 +578,55 @@ u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len,
static void
msm_slim_rx_msgq_event(struct msm_slim_ctrl *dev, struct sps_event_notify *ev)
{
	u32 *buf = ev->data.transfer.user;
	struct sps_iovec *iovec = &ev->data.transfer.iovec;

	/*
	 * Note the virtual address needs to be offset by the same index
	 * as the physical address or just pass in the actual virtual address
	 * if the sps_mem_buffer is not needed.  Note that if completion is
	 * used, the virtual address won't be available and will need to be
	 * calculated based on the offset of the physical address
	 */
	if (ev->event_id == SPS_EVENT_DESC_DONE) {

		pr_debug("buf = 0x%p, data = 0x%x\n", buf, *buf);
	if (ev->event_id == SPS_EVENT_DESC_DONE)
		complete(&dev->rx_msgq_notify);
	else
		dev_err(dev->dev, "%s: unknown event %d\n",
					__func__, ev->event_id);
}

		pr_debug("iovec = (0x%x 0x%x 0x%x)\n",
			iovec->addr, iovec->size, iovec->flags);
static void
msm_slim_handle_rx(struct msm_slim_ctrl *dev, struct sps_event_notify *ev)
{
	int ret = 0, index = 0;
	u32 mc = 0;
	u32 mt = 0;
	u32 buffer[10];
	u8 msg_len = 0;

	} else {
	if (ev->event_id != SPS_EVENT_EOT) {
		dev_err(dev->dev, "%s: unknown event %d\n",
					__func__, ev->event_id);
		return;
	}
	do {
		ret = msm_slim_rx_msgq_get(dev, buffer, index);
		if (ret) {
			SLIM_ERR(dev, "rx_msgq_get() failed 0x%x\n",
								ret);
			return;
		}

		/* Traverse first byte of message for message length */
		if (index++ == 0) {
			msg_len = *buffer & 0x1F;
			mt = (buffer[0] >> 5) & 0x7;
			mc = (buffer[0] >> 8) & 0xff;
			dev_dbg(dev->dev, "MC: %x, MT: %x\n", mc, mt);
		}
		msg_len = (msg_len < 4) ? 0 : (msg_len - 4);
	} while (msg_len);
	dev->rx_slim(dev, (u8 *)buffer);
}

static void msm_slim_rx_msgq_cb(struct sps_event_notify *notify)
{
	struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)notify->user;
	/* is this manager controller or NGD controller? */
	if (dev->ctrl.wakeup)
		msm_slim_rx_msgq_event(dev, notify);
	else
		msm_slim_handle_rx(dev, notify);
}

/* Queue up Rx message buffer */
@@ -619,8 +641,6 @@ static int msm_slim_post_rx_msgq(struct msm_slim_ctrl *dev, int ix)
	u8 *virt_addr = mem->base + (4 * ix);
	phys_addr_t phys_addr = mem->phys_base + (4 * ix);

	pr_debug("index:%d, virt:0x%p\n", ix, virt_addr);

	ret = sps_transfer_one(pipe, phys_addr, 4, virt_addr, 0);
	if (ret)
		dev_err(dev->dev, "transfer_one() failed 0x%x, %d\n", ret, ix);
@@ -664,8 +684,7 @@ err_exit:
}

int msm_slim_connect_endp(struct msm_slim_ctrl *dev,
				struct msm_slim_endp *endpoint,
				struct completion *notify)
				struct msm_slim_endp *endpoint)
{
	int i, ret;
	struct sps_register_event sps_error_event; /* SPS_ERROR */
@@ -680,11 +699,12 @@ int msm_slim_connect_endp(struct msm_slim_ctrl *dev,

	memset(&sps_descr_event, 0x00, sizeof(sps_descr_event));

	if (notify) {
	if (endpoint == &dev->rx_msgq) {
		sps_descr_event.mode = SPS_TRIGGER_CALLBACK;
		sps_descr_event.options = SPS_O_EOT;
		sps_descr_event.user = (void *)dev;
		sps_descr_event.xfer_done = notify;
		sps_descr_event.callback = msm_slim_rx_msgq_cb;
		sps_descr_event.xfer_done = NULL;

		ret = sps_register_event(endpoint->sps, &sps_descr_event);
		if (ret) {
@@ -788,7 +808,7 @@ static int msm_slim_init_rx_msgq(struct msm_slim_ctrl *dev, u32 pipe_reg)
		goto alloc_buffer_failed;
	}

	ret = msm_slim_connect_endp(dev, endpoint, notify);
	ret = msm_slim_connect_endp(dev, endpoint);

	if (!ret)
		return 0;
@@ -851,7 +871,7 @@ static int msm_slim_init_tx_msgq(struct msm_slim_ctrl *dev, u32 pipe_reg)
		dev_err(dev->dev, "dma_alloc_coherent failed\n");
		goto alloc_buffer_failed;
	}
	ret = msm_slim_connect_endp(dev, endpoint, NULL);
	ret = msm_slim_connect_endp(dev, endpoint);

	if (!ret)
		return 0;
+3 −3
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
@@ -277,6 +277,7 @@ struct msm_slim_ctrl {
	int			ipc_log_mask;
	bool			sysfs_created;
	void			*ipc_slimbus_log;
	void (*rx_slim)(struct msm_slim_ctrl *dev, u8 *buf);
};

struct msm_sat_chan {
@@ -387,8 +388,7 @@ int msm_slim_sps_init(struct msm_slim_ctrl *dev, struct resource *bam_mem,
void msm_slim_sps_exit(struct msm_slim_ctrl *dev, bool dereg);

int msm_slim_connect_endp(struct msm_slim_ctrl *dev,
				struct msm_slim_endp *endpoint,
				struct completion *notify);
				struct msm_slim_endp *endpoint);
void msm_slim_disconnect_endp(struct msm_slim_ctrl *dev,
					struct msm_slim_endp *endpoint,
					enum msm_slim_msgq *msgq_flag);