diff options
author | Kouichi Tomita <kouichi.tomita.yn@renesas.com> | 2015-02-15 09:46:46 -0500 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2015-03-23 09:13:43 -0400 |
commit | dbb42d962c4149fe2e97f74bf1343b5229eefe5e (patch) | |
tree | a2a1fced0c5290bbf1c677a9fe2171654683182e | |
parent | 4cbd52246533d1dc6449ef8278e95e5e0944a1e5 (diff) |
mmc: sh_mmcif: Add exclusion between cmd and interrupt
A command end interrupt should not be processed between command issue
and setting of wait_for flag. It expects already the flag to be set.
Therefore the exclusive control was added.
Signed-off-by: Kouichi Tomita <kouichi.tomita.yn@renesas.com>
Signed-off-by: Yoshihiro Kaneko <ykaneko0929@gmail.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r-- | drivers/mmc/host/sh_mmcif.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index e0758044a263..072f67066df3 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c | |||
@@ -875,6 +875,7 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, | |||
875 | struct mmc_command *cmd = mrq->cmd; | 875 | struct mmc_command *cmd = mrq->cmd; |
876 | u32 opc = cmd->opcode; | 876 | u32 opc = cmd->opcode; |
877 | u32 mask; | 877 | u32 mask; |
878 | unsigned long flags; | ||
878 | 879 | ||
879 | switch (opc) { | 880 | switch (opc) { |
880 | /* response busy check */ | 881 | /* response busy check */ |
@@ -909,10 +910,12 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, | |||
909 | /* set arg */ | 910 | /* set arg */ |
910 | sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg); | 911 | sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg); |
911 | /* set cmd */ | 912 | /* set cmd */ |
913 | spin_lock_irqsave(&host->lock, flags); | ||
912 | sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc); | 914 | sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc); |
913 | 915 | ||
914 | host->wait_for = MMCIF_WAIT_FOR_CMD; | 916 | host->wait_for = MMCIF_WAIT_FOR_CMD; |
915 | schedule_delayed_work(&host->timeout_work, host->timeout); | 917 | schedule_delayed_work(&host->timeout_work, host->timeout); |
918 | spin_unlock_irqrestore(&host->lock, flags); | ||
916 | } | 919 | } |
917 | 920 | ||
918 | static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host, | 921 | static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host, |
@@ -1171,6 +1174,12 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) | |||
1171 | struct sh_mmcif_host *host = dev_id; | 1174 | struct sh_mmcif_host *host = dev_id; |
1172 | struct mmc_request *mrq; | 1175 | struct mmc_request *mrq; |
1173 | bool wait = false; | 1176 | bool wait = false; |
1177 | unsigned long flags; | ||
1178 | int wait_work; | ||
1179 | |||
1180 | spin_lock_irqsave(&host->lock, flags); | ||
1181 | wait_work = host->wait_for; | ||
1182 | spin_unlock_irqrestore(&host->lock, flags); | ||
1174 | 1183 | ||
1175 | cancel_delayed_work_sync(&host->timeout_work); | 1184 | cancel_delayed_work_sync(&host->timeout_work); |
1176 | 1185 | ||
@@ -1188,7 +1197,7 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) | |||
1188 | * All handlers return true, if processing continues, and false, if the | 1197 | * All handlers return true, if processing continues, and false, if the |
1189 | * request has to be completed - successfully or not | 1198 | * request has to be completed - successfully or not |
1190 | */ | 1199 | */ |
1191 | switch (host->wait_for) { | 1200 | switch (wait_work) { |
1192 | case MMCIF_WAIT_FOR_REQUEST: | 1201 | case MMCIF_WAIT_FOR_REQUEST: |
1193 | /* We're too late, the timeout has already kicked in */ | 1202 | /* We're too late, the timeout has already kicked in */ |
1194 | mutex_unlock(&host->thread_lock); | 1203 | mutex_unlock(&host->thread_lock); |