int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd) { enum mc_cmd_status status; uint64_t response; if (!mc_io || !mc_io->regs) return -EACCES; /* --- Call lock function here in case portal is shared --- */ rte_spinlock_lock(&mc_portal_lock); mc_write_command(mc_io->regs, cmd); /* Spin until status changes */ do { response = ioread64(mc_io->regs); status = mc_cmd_read_status((struct mc_command *)&response); /* --- Call wait function here to prevent blocking --- * Change the loop condition accordingly to exit on timeout. */ } while (status == MC_CMD_STATUS_READY); /* Read the response back into the command buffer */ mc_read_response(mc_io->regs, cmd); /* --- Call unlock function here in case portal is shared --- */ rte_spinlock_unlock(&mc_portal_lock); return mc_status_to_error(status); }
/** * Sends a command to the MC device using the given MC I/O object * * @mc_io: MC I/O object to be used * @cmd: command to be sent * * Returns '0' on Success; Error code otherwise. */ int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd) { int error; enum mc_cmd_status status; unsigned long irq_flags = 0; if (WARN_ON(in_irq() && !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))) return -EINVAL; if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) spin_lock_irqsave(&mc_io->spinlock, irq_flags); else mutex_lock(&mc_io->mutex); /* * Send command to the MC hardware: */ mc_write_command(mc_io->portal_virt_addr, cmd); /* * Wait for response from the MC hardware: */ if (!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)) error = mc_polling_wait_preemptible(mc_io, cmd, &status); else error = mc_polling_wait_atomic(mc_io, cmd, &status); if (error < 0) goto common_exit; if (status != MC_CMD_STATUS_OK) { dev_dbg(mc_io->dev, "MC command failed: portal: %#llx, obj handle: %#x, command: %#x, status: %s (%#x)\n", mc_io->portal_phys_addr, (unsigned int)mc_cmd_hdr_read_token(cmd), (unsigned int)mc_cmd_hdr_read_cmdid(cmd), mc_status_to_string(status), (unsigned int)status); error = mc_status_to_error(status); goto common_exit; } error = 0; common_exit: if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) spin_unlock_irqrestore(&mc_io->spinlock, irq_flags); else mutex_unlock(&mc_io->mutex); return error; }