diff options
author | J. German Rivera <German.Rivera@freescale.com> | 2015-10-17 20:33:15 (GMT) |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-10-18 03:54:46 (GMT) |
commit | 63f2be5c3b358db031f86eafa9cd450f6558a55b (patch) | |
tree | 26e710dc8423681051d12f897ebc7a1b025ca4fb /drivers/staging/fsl-mc/bus | |
parent | 3f95ad21855f750fe0428853214754f414b82daf (diff) | |
download | linux-63f2be5c3b358db031f86eafa9cd450f6558a55b.tar.xz |
staging: fsl-mc: Added serialization to mc_send_command()
When the same portal is used to call mc_send_command() from two
different threads or a thread and an interrupt handler, serialization
is required, as the MC only supports one outstanding command per MC
portal. Thus, a new command should not be sent to the MC until the
last command sent has been responded by the MC.
Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/fsl-mc/bus')
-rw-r--r-- | drivers/staging/fsl-mc/bus/mc-sys.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/drivers/staging/fsl-mc/bus/mc-sys.c b/drivers/staging/fsl-mc/bus/mc-sys.c index 6eeb9fa..6e14892 100644 --- a/drivers/staging/fsl-mc/bus/mc-sys.c +++ b/drivers/staging/fsl-mc/bus/mc-sys.c @@ -88,6 +88,11 @@ int __must_check fsl_create_mc_io(struct device *dev, mc_io->flags = flags; mc_io->portal_phys_addr = mc_portal_phys_addr; mc_io->portal_size = mc_portal_size; + if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) + spin_lock_init(&mc_io->spinlock); + else + mutex_init(&mc_io->mutex); + res = devm_request_mem_region(dev, mc_portal_phys_addr, mc_portal_size, @@ -391,11 +396,17 @@ 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: */ @@ -410,7 +421,7 @@ int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd) error = mc_polling_wait_atomic(mc_io, cmd, &status); if (error < 0) - return error; + goto common_exit; if (status != MC_CMD_STATUS_OK) { pr_debug("MC command failed: portal: %#llx, obj handle: %#x, command: %#x, status: %s (%#x)\n", @@ -420,9 +431,17 @@ int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd) mc_status_to_string(status), (unsigned int)status); - return mc_status_to_error(status); + error = mc_status_to_error(status); + goto common_exit; } - return 0; + 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; } EXPORT_SYMBOL(mc_send_command); |