static int qcom_xfer_msg()

in qcom-ctrl.c [325:387]


static int qcom_xfer_msg(struct slim_controller *sctrl,
			 struct slim_msg_txn *txn)
{
	struct qcom_slim_ctrl *ctrl = dev_get_drvdata(sctrl->dev);
	DECLARE_COMPLETION_ONSTACK(done);
	void *pbuf = slim_alloc_txbuf(ctrl, txn, &done);
	unsigned long ms = txn->rl + HZ;
	u8 *puc;
	int ret = 0, timeout, retries = QCOM_BUF_ALLOC_RETRIES;
	u8 la = txn->la;
	u32 *head;
	/* HW expects length field to be excluded */
	txn->rl--;

	/* spin till buffer is made available */
	if (!pbuf) {
		while (retries--) {
			usleep_range(10000, 15000);
			pbuf = slim_alloc_txbuf(ctrl, txn, &done);
			if (pbuf)
				break;
		}
	}

	if (retries < 0 && !pbuf)
		return -ENOMEM;

	puc = (u8 *)pbuf;
	head = (u32 *)pbuf;

	if (txn->dt == SLIM_MSG_DEST_LOGICALADDR) {
		*head = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt,
						txn->mc, 0, la);
		puc += 3;
	} else {
		*head = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt,
						txn->mc, 1, la);
		puc += 2;
	}

	if (slim_tid_txn(txn->mt, txn->mc))
		*(puc++) = txn->tid;

	if (slim_ec_txn(txn->mt, txn->mc)) {
		*(puc++) = (txn->ec & 0xFF);
		*(puc++) = (txn->ec >> 8) & 0xFF;
	}

	if (txn->msg && txn->msg->wbuf)
		memcpy(puc, txn->msg->wbuf, txn->msg->num_bytes);

	qcom_slim_queue_tx(ctrl, head, txn->rl, MGR_TX_MSG);
	timeout = wait_for_completion_timeout(&done, msecs_to_jiffies(ms));

	if (!timeout) {
		dev_err(ctrl->dev, "TX timed out:MC:0x%x,mt:0x%x", txn->mc,
					txn->mt);
		ret = -ETIMEDOUT;
	}

	return ret;

}