mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 04:34:11 +08:00
staging: fsl-mc:Added support for atomic portals
Refactored mc_send_command() to support two flavors of polling: - preemptible (for non-atomic portals), which was already supported. It calls usleep_range() between polling iterations. - non-preemptible (for atomic portals), which is needed when mc_send_command() is called with interrupts disabled. It calls udelay() between polling iterations. Signed-off-by: J. German Rivera <German.Rivera@freescale.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
140305e77a
commit
3f95ad2185
@ -338,6 +338,47 @@ static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io,
|
||||
return 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) {
|
||||
pr_debug("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->header),
|
||||
(unsigned int)
|
||||
MC_CMD_HDR_READ_CMDID(cmd->header));
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
*mc_status = status;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a command to the MC device using the given MC I/O object
|
||||
*
|
||||
@ -345,14 +386,16 @@ static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io,
|
||||
* @cmd: command to be sent
|
||||
*
|
||||
* Returns '0' on Success; Error code otherwise.
|
||||
*
|
||||
* NOTE: This function cannot be invoked from from atomic contexts.
|
||||
*/
|
||||
int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd)
|
||||
{
|
||||
int error;
|
||||
enum mc_cmd_status status;
|
||||
|
||||
if (WARN_ON(in_irq() &&
|
||||
!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Send command to the MC hardware:
|
||||
*/
|
||||
@ -361,7 +404,11 @@ int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd)
|
||||
/*
|
||||
* Wait for response from the MC hardware:
|
||||
*/
|
||||
error = mc_polling_wait_preemptible(mc_io, cmd, &status);
|
||||
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)
|
||||
return error;
|
||||
|
||||
|
@ -40,6 +40,11 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
/**
|
||||
* Bit masks for a MC I/O object (struct fsl_mc_io) flags
|
||||
*/
|
||||
#define FSL_MC_IO_ATOMIC_CONTEXT_PORTAL 0x0001
|
||||
|
||||
struct fsl_mc_resource;
|
||||
struct mc_command;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user