Esempio n. 1
0
/**
 * 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;
}
Esempio n. 2
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);
}
Esempio n. 3
0
/**
 * 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;
}
Esempio n. 4
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;
}