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); |
