aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorSan Mehat <san@google.com>2009-11-21 12:22:14 -0500
committerDaniel Walker <dwalker@codeaurora.org>2010-03-18 15:58:05 -0400
commit5b00f40f90e7b17c11cf388680f43e8466b3666d (patch)
treecc762bdeaeffebae79b26af3a5379abb11049797 /arch/arm
parentb3fa579118b239e218e690f5ef76870aff6fe738 (diff)
msm: Add 'execute' datamover callback
Based on a patch from Brent DeGraaf: "The datamover supports channels which can be shared amongst devices. As a result, the actual data transfer may occur some time after the request is queued up. Some devices such as mmc host controllers will timeout if a command is issued too far in advance of the actual transfer, so if dma to other devices on the same channel is already in progress or queued up, the added delay can cause pending transfers to fail before they start. This change extends the api to allow a user callback to be invoked just before the actual transfer takes place, thus allowing actions directly associated with the dma transfer, such as device commands, to be invoked with precise timing. Without this mechanism, there is no way for a driver to realize this timing. Also adds a user pointer to the command structure for use by the caller to reference information that may be needed by the callback routine for proper identification and processing associated with that specific request. This change is necessary to fix problems associated with excessive command timeouts and race conditions in the mmc driver." This patch also fixes all the callers of msm_dmov_enqueue_cmd() to ensure their callback function is NULL. Signed-off-by: San Mehat <san@google.com> Cc: Brent DeGraaf <bdegraaf@quicinc.com> Cc: Brian Swetland <swetland@google.com> Signed-off-by: Daniel Walker <dwalker@codeaurora.org>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-msm/dma.c5
-rw-r--r--arch/arm/mach-msm/include/mach/dma.h2
2 files changed, 7 insertions, 0 deletions
diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c
index f5420f9585c5..8df798ac70c7 100644
--- a/arch/arm/mach-msm/dma.c
+++ b/arch/arm/mach-msm/dma.c
@@ -63,6 +63,8 @@ void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd)
63 writel(DMOV_CONFIG_IRQ_EN, DMOV_CONFIG(id)); 63 writel(DMOV_CONFIG_IRQ_EN, DMOV_CONFIG(id));
64 } 64 }
65#endif 65#endif
66 if (cmd->execute_func)
67 cmd->execute_func(cmd);
66 PRINT_IO("msm_dmov_enqueue_cmd(%d), start command, status %x\n", id, status); 68 PRINT_IO("msm_dmov_enqueue_cmd(%d), start command, status %x\n", id, status);
67 list_add_tail(&cmd->list, &active_commands[id]); 69 list_add_tail(&cmd->list, &active_commands[id]);
68 if (!channel_active) 70 if (!channel_active)
@@ -108,6 +110,7 @@ int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr)
108 110
109 cmd.dmov_cmd.cmdptr = cmdptr; 111 cmd.dmov_cmd.cmdptr = cmdptr;
110 cmd.dmov_cmd.complete_func = dmov_exec_cmdptr_complete_func; 112 cmd.dmov_cmd.complete_func = dmov_exec_cmdptr_complete_func;
113 cmd.dmov_cmd.execute_func = NULL;
111 cmd.id = id; 114 cmd.id = id;
112 init_completion(&cmd.complete); 115 init_completion(&cmd.complete);
113 116
@@ -210,6 +213,8 @@ static irqreturn_t msm_datamover_irq_handler(int irq, void *dev_id)
210 cmd = list_entry(ready_commands[id].next, typeof(*cmd), list); 213 cmd = list_entry(ready_commands[id].next, typeof(*cmd), list);
211 list_del(&cmd->list); 214 list_del(&cmd->list);
212 list_add_tail(&cmd->list, &active_commands[id]); 215 list_add_tail(&cmd->list, &active_commands[id]);
216 if (cmd->execute_func)
217 cmd->execute_func(cmd);
213 PRINT_FLOW("msm_datamover_irq_handler id %d, start command\n", id); 218 PRINT_FLOW("msm_datamover_irq_handler id %d, start command\n", id);
214 writel(cmd->cmdptr, DMOV_CMD_PTR(id)); 219 writel(cmd->cmdptr, DMOV_CMD_PTR(id));
215 } 220 }
diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h
index 5ab5bdffab07..78b0ffdf27e8 100644
--- a/arch/arm/mach-msm/include/mach/dma.h
+++ b/arch/arm/mach-msm/include/mach/dma.h
@@ -28,6 +28,8 @@ struct msm_dmov_cmd {
28 void (*complete_func)(struct msm_dmov_cmd *cmd, 28 void (*complete_func)(struct msm_dmov_cmd *cmd,
29 unsigned int result, 29 unsigned int result,
30 struct msm_dmov_errdata *err); 30 struct msm_dmov_errdata *err);
31 void (*execute_func)(struct msm_dmov_cmd *cmd);
32 void *data;
31}; 33};
32 34
33void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd); 35void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd);