summaryrefslogtreecommitdiff
path: root/drivers/staging/fsl-mc/bus
diff options
context:
space:
mode:
authorJ. German Rivera <German.Rivera@freescale.com>2015-10-17 20:33:15 (GMT)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-10-18 03:54:46 (GMT)
commit63f2be5c3b358db031f86eafa9cd450f6558a55b (patch)
tree26e710dc8423681051d12f897ebc7a1b025ca4fb /drivers/staging/fsl-mc/bus
parent3f95ad21855f750fe0428853214754f414b82daf (diff)
downloadlinux-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.c25
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);