static int ti_msgmgr_send_data()

in ti-msgmgr.c [346:398]


static int ti_msgmgr_send_data(struct mbox_chan *chan, void *data)
{
	struct device *dev = chan->mbox->dev;
	struct ti_msgmgr_inst *inst = dev_get_drvdata(dev);
	const struct ti_msgmgr_desc *desc;
	struct ti_queue_inst *qinst = chan->con_priv;
	int num_words, trail_bytes;
	struct ti_msgmgr_message *message = data;
	void __iomem *data_reg;
	u32 *word_data;

	if (WARN_ON(!inst)) {
		dev_err(dev, "no platform drv data??\n");
		return -EINVAL;
	}
	desc = inst->desc;

	if (ti_msgmgr_queue_is_error(desc, qinst)) {
		dev_err(dev, "Error on channel %s\n", qinst->name);
		return false;
	}

	if (desc->max_message_size < message->len) {
		dev_err(dev, "Queue %s message length %zu > max %d\n",
			qinst->name, message->len, desc->max_message_size);
		return -EINVAL;
	}

	/* NOTE: Constraints similar to rx path exists here as well */
	for (data_reg = qinst->queue_buff_start,
	     num_words = message->len / sizeof(u32),
	     word_data = (u32 *)message->buf;
	     num_words; num_words--, data_reg += sizeof(u32), word_data++)
		writel(*word_data, data_reg);

	trail_bytes = message->len % sizeof(u32);
	if (trail_bytes) {
		u32 data_trail = *word_data;

		/* Ensure all unused data is 0 */
		data_trail &= 0xFFFFFFFF >> (8 * (sizeof(u32) - trail_bytes));
		writel(data_trail, data_reg);
		data_reg++;
	}
	/*
	 * 'data_reg' indicates next register to write. If we did not already
	 * write on tx complete reg(last reg), we must do so for transmit
	 */
	if (data_reg <= qinst->queue_buff_end)
		writel(0, qinst->queue_buff_end);

	return 0;
}