/** * Waits for the completion of an MC command doing atomic polling. * udelay() is called between polling iterations. * * @mc_io: MC I/O object to be used * @cmd: command buffer to receive MC response * @mc_status: MC command completion status */ static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io, struct mc_command *cmd, enum mc_cmd_status *mc_status) { enum mc_cmd_status status; unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000; BUILD_BUG_ON((MC_CMD_COMPLETION_TIMEOUT_MS * 1000) % MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS != 0); for (;;) { status = mc_read_response(mc_io->portal_virt_addr, cmd); if (status != MC_CMD_STATUS_READY) break; udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS); timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS; if (timeout_usecs == 0) { dev_dbg(mc_io->dev, "MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n", mc_io->portal_phys_addr, (unsigned int)mc_cmd_hdr_read_token(cmd), (unsigned int)mc_cmd_hdr_read_cmdid(cmd)); return -ETIMEDOUT; } } *mc_status = status; return 0; }
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); }
/** * mc_send_command - Send MC command and wait for response * * @mc_io: Pointer to MC I/O object to be used * @cmd: MC command buffer. On input, it contains the command to send to the MC. * On output, it contains the response from the MC if any. * * Depending on the sharing option specified when creating the MC portal * wrapper, this function will use a spinlock or mutex to ensure exclusive * access to the MC portal from the point when the command is sent until a * response is received from the MC. */ int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd) { enum mc_cmd_status status; int timeout = 2000; mc_write_command(mc_io->mmio_regs, cmd); for ( ; ; ) { status = mc_read_response(mc_io->mmio_regs, cmd); if (status != MC_CMD_STATUS_READY) break; if (--timeout == 0) { printf("Error: Timeout waiting for MC response\n"); return -ETIMEDOUT; } udelay(500); } if (status != MC_CMD_STATUS_OK) { printf("Error: MC command failed (portal: %p, obj handle: %#x, command: %#x, status: %#x)\n", mc_io->mmio_regs, (unsigned int)MC_CMD_HDR_READ_AUTHID(cmd->header), (unsigned int)MC_CMD_HDR_READ_CMDID(cmd->header), (unsigned int)status); return -EIO; } return 0; }
/** * Waits for the completion of an MC command doing preemptible polling. * uslepp_range() is called between polling iterations. * * @mc_io: MC I/O object to be used * @cmd: command buffer to receive MC response * @mc_status: MC command completion status */ static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io, struct mc_command *cmd, enum mc_cmd_status *mc_status) { enum mc_cmd_status status; unsigned long jiffies_until_timeout = jiffies + msecs_to_jiffies(MC_CMD_COMPLETION_TIMEOUT_MS); /* * Wait for response from the MC hardware: */ for (;;) { status = mc_read_response(mc_io->portal_virt_addr, cmd); if (status != MC_CMD_STATUS_READY) break; /* * TODO: When MC command completion interrupts are supported * call wait function here instead of usleep_range() */ usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS, MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS); if (time_after_eq(jiffies, jiffies_until_timeout)) { dev_dbg(mc_io->dev, "MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n", mc_io->portal_phys_addr, (unsigned int)mc_cmd_hdr_read_token(cmd), (unsigned int)mc_cmd_hdr_read_cmdid(cmd)); return -ETIMEDOUT; } } *mc_status = status; return 0; }