Пример #1
0
static int ccp5_do_cmd(struct ccp5_desc *desc,
		       struct ccp_cmd_queue *cmd_q)
{
	u32 *mP;
	__le32 *dP;
	u32 tail;
	int	i;
	int ret = 0;

	cmd_q->total_ops++;

	if (CCP5_CMD_SOC(desc)) {
		CCP5_CMD_IOC(desc) = 1;
		CCP5_CMD_SOC(desc) = 0;
	}
	mutex_lock(&cmd_q->q_mutex);

	mP = (u32 *) &cmd_q->qbase[cmd_q->qidx];
	dP = (__le32 *) desc;
	for (i = 0; i < 8; i++)
		mP[i] = cpu_to_le32(dP[i]); /* handle endianness */

	cmd_q->qidx = (cmd_q->qidx + 1) % COMMANDS_PER_QUEUE;

	/* The data used by this command must be flushed to memory */
	wmb();

	/* Write the new tail address back to the queue register */
	tail = low_address(cmd_q->qdma_tail + cmd_q->qidx * Q_DESC_SIZE);
	iowrite32(tail, cmd_q->reg_tail_lo);

	/* Turn the queue back on using our cached control register */
	iowrite32(cmd_q->qcontrol | CMD5_Q_RUN, cmd_q->reg_control);
	mutex_unlock(&cmd_q->q_mutex);

	if (CCP5_CMD_IOC(desc)) {
		/* Wait for the job to complete */
		ret = wait_event_interruptible(cmd_q->int_queue,
					       cmd_q->int_rcvd);
		if (ret || cmd_q->cmd_error) {
			/* Log the error and flush the queue by
			 * moving the head pointer
			 */
			if (cmd_q->cmd_error)
				ccp_log_error(cmd_q->ccp,
					      cmd_q->cmd_error);
			iowrite32(tail, cmd_q->reg_head_lo);
			if (!ret)
				ret = -EIO;
		}
		cmd_q->int_rcvd = 0;
	}

	return ret;
}
Пример #2
0
static int ccp_do_cmd(struct ccp_op *op, u32 *cr, unsigned int cr_count)
{
	struct ccp_cmd_queue *cmd_q = op->cmd_q;
	struct ccp_device *ccp = cmd_q->ccp;
	void __iomem *cr_addr;
	u32 cr0, cmd;
	unsigned int i;
	int ret = 0;

	/* We could read a status register to see how many free slots
	 * are actually available, but reading that register resets it
	 * and you could lose some error information.
	 */
	cmd_q->free_slots--;

	cr0 = (cmd_q->id << REQ0_CMD_Q_SHIFT)
	      | (op->jobid << REQ0_JOBID_SHIFT)
	      | REQ0_WAIT_FOR_WRITE;

	if (op->soc)
		cr0 |= REQ0_STOP_ON_COMPLETE
		       | REQ0_INT_ON_COMPLETE;

	if (op->ioc || !cmd_q->free_slots)
		cr0 |= REQ0_INT_ON_COMPLETE;

	/* Start at CMD_REQ1 */
	cr_addr = ccp->io_regs + CMD_REQ0 + CMD_REQ_INCR;

	mutex_lock(&ccp->req_mutex);

	/* Write CMD_REQ1 through CMD_REQx first */
	for (i = 0; i < cr_count; i++, cr_addr += CMD_REQ_INCR)
		iowrite32(*(cr + i), cr_addr);

	/* Tell the CCP to start */
	wmb();
	iowrite32(cr0, ccp->io_regs + CMD_REQ0);

	mutex_unlock(&ccp->req_mutex);

	if (cr0 & REQ0_INT_ON_COMPLETE) {
		/* Wait for the job to complete */
		ret = wait_event_interruptible(cmd_q->int_queue,
					       cmd_q->int_rcvd);
		if (ret || cmd_q->cmd_error) {
			/* On error delete all related jobs from the queue */
			cmd = (cmd_q->id << DEL_Q_ID_SHIFT)
			      | op->jobid;
			if (cmd_q->cmd_error)
				ccp_log_error(cmd_q->ccp,
					      cmd_q->cmd_error);

			iowrite32(cmd, ccp->io_regs + DEL_CMD_Q_JOB);

			if (!ret)
				ret = -EIO;
		} else if (op->soc) {
			/* Delete just head job from the queue on SoC */
			cmd = DEL_Q_ACTIVE
			      | (cmd_q->id << DEL_Q_ID_SHIFT)
			      | op->jobid;

			iowrite32(cmd, ccp->io_regs + DEL_CMD_Q_JOB);
		}

		cmd_q->free_slots = CMD_Q_DEPTH(cmd_q->q_status);

		cmd_q->int_rcvd = 0;
	}

	return ret;
}