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; }
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; }