Commit 5df460b1 authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Chris Ball

mmc: sh_mmcif: fix missing and consolidate IO completion timeouts

Read block and write block operations are currently missing completion
timeouts. Add missing timeouts and consolidate them at one location.
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent a812ba0f
...@@ -564,7 +564,6 @@ static void sh_mmcif_single_read(struct sh_mmcif_host *host, ...@@ -564,7 +564,6 @@ static void sh_mmcif_single_read(struct sh_mmcif_host *host,
BLOCK_SIZE_MASK) + 3; BLOCK_SIZE_MASK) + 3;
host->wait_for = MMCIF_WAIT_FOR_READ; host->wait_for = MMCIF_WAIT_FOR_READ;
schedule_delayed_work(&host->timeout_work, host->timeout);
/* buf read enable */ /* buf read enable */
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
...@@ -606,7 +605,7 @@ static void sh_mmcif_multi_read(struct sh_mmcif_host *host, ...@@ -606,7 +605,7 @@ static void sh_mmcif_multi_read(struct sh_mmcif_host *host,
host->sg_idx = 0; host->sg_idx = 0;
host->sg_blkidx = 0; host->sg_blkidx = 0;
host->pio_ptr = sg_virt(data->sg); host->pio_ptr = sg_virt(data->sg);
schedule_delayed_work(&host->timeout_work, host->timeout);
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
} }
...@@ -629,7 +628,6 @@ static bool sh_mmcif_mread_block(struct sh_mmcif_host *host) ...@@ -629,7 +628,6 @@ static bool sh_mmcif_mread_block(struct sh_mmcif_host *host)
if (!sh_mmcif_next_block(host, p)) if (!sh_mmcif_next_block(host, p))
return false; return false;
schedule_delayed_work(&host->timeout_work, host->timeout);
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
return true; return true;
...@@ -642,7 +640,6 @@ static void sh_mmcif_single_write(struct sh_mmcif_host *host, ...@@ -642,7 +640,6 @@ static void sh_mmcif_single_write(struct sh_mmcif_host *host,
BLOCK_SIZE_MASK) + 3; BLOCK_SIZE_MASK) + 3;
host->wait_for = MMCIF_WAIT_FOR_WRITE; host->wait_for = MMCIF_WAIT_FOR_WRITE;
schedule_delayed_work(&host->timeout_work, host->timeout);
/* buf write enable */ /* buf write enable */
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
...@@ -684,7 +681,7 @@ static void sh_mmcif_multi_write(struct sh_mmcif_host *host, ...@@ -684,7 +681,7 @@ static void sh_mmcif_multi_write(struct sh_mmcif_host *host,
host->sg_idx = 0; host->sg_idx = 0;
host->sg_blkidx = 0; host->sg_blkidx = 0;
host->pio_ptr = sg_virt(data->sg); host->pio_ptr = sg_virt(data->sg);
schedule_delayed_work(&host->timeout_work, host->timeout);
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
} }
...@@ -707,7 +704,6 @@ static bool sh_mmcif_mwrite_block(struct sh_mmcif_host *host) ...@@ -707,7 +704,6 @@ static bool sh_mmcif_mwrite_block(struct sh_mmcif_host *host)
if (!sh_mmcif_next_block(host, p)) if (!sh_mmcif_next_block(host, p))
return false; return false;
schedule_delayed_work(&host->timeout_work, host->timeout);
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
return true; return true;
...@@ -900,7 +896,6 @@ static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host, ...@@ -900,7 +896,6 @@ static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host,
} }
host->wait_for = MMCIF_WAIT_FOR_STOP; host->wait_for = MMCIF_WAIT_FOR_STOP;
schedule_delayed_work(&host->timeout_work, host->timeout);
} }
static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
...@@ -1121,6 +1116,7 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) ...@@ -1121,6 +1116,7 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
{ {
struct sh_mmcif_host *host = dev_id; struct sh_mmcif_host *host = dev_id;
struct mmc_request *mrq = host->mrq; struct mmc_request *mrq = host->mrq;
bool wait = false;
cancel_delayed_work_sync(&host->timeout_work); cancel_delayed_work_sync(&host->timeout_work);
...@@ -1133,29 +1129,24 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) ...@@ -1133,29 +1129,24 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
/* We're too late, the timeout has already kicked in */ /* We're too late, the timeout has already kicked in */
return IRQ_HANDLED; return IRQ_HANDLED;
case MMCIF_WAIT_FOR_CMD: case MMCIF_WAIT_FOR_CMD:
if (sh_mmcif_end_cmd(host)) /* Wait for data? */
/* Wait for data */ wait = sh_mmcif_end_cmd(host);
return IRQ_HANDLED;
break; break;
case MMCIF_WAIT_FOR_MREAD: case MMCIF_WAIT_FOR_MREAD:
if (sh_mmcif_mread_block(host)) /* Wait for more data? */
/* Wait for more data */ wait = sh_mmcif_mread_block(host);
return IRQ_HANDLED;
break; break;
case MMCIF_WAIT_FOR_READ: case MMCIF_WAIT_FOR_READ:
if (sh_mmcif_read_block(host)) /* Wait for data end? */
/* Wait for data end */ wait = sh_mmcif_read_block(host);
return IRQ_HANDLED;
break; break;
case MMCIF_WAIT_FOR_MWRITE: case MMCIF_WAIT_FOR_MWRITE:
if (sh_mmcif_mwrite_block(host)) /* Wait data to write? */
/* Wait data to write */ wait = sh_mmcif_mwrite_block(host);
return IRQ_HANDLED;
break; break;
case MMCIF_WAIT_FOR_WRITE: case MMCIF_WAIT_FOR_WRITE:
if (sh_mmcif_write_block(host)) /* Wait for data end? */
/* Wait for data end */ wait = sh_mmcif_write_block(host);
return IRQ_HANDLED;
break; break;
case MMCIF_WAIT_FOR_STOP: case MMCIF_WAIT_FOR_STOP:
if (host->sd_error) { if (host->sd_error) {
...@@ -1174,6 +1165,12 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) ...@@ -1174,6 +1165,12 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
BUG(); BUG();
} }
if (wait) {
schedule_delayed_work(&host->timeout_work, host->timeout);
/* Wait for more data */
return IRQ_HANDLED;
}
if (host->wait_for != MMCIF_WAIT_FOR_STOP) { if (host->wait_for != MMCIF_WAIT_FOR_STOP) {
struct mmc_data *data = mrq->data; struct mmc_data *data = mrq->data;
if (!mrq->cmd->error && data && !data->error) if (!mrq->cmd->error && data && !data->error)
...@@ -1182,10 +1179,12 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) ...@@ -1182,10 +1179,12 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
if (mrq->stop && !mrq->cmd->error && (!data || !data->error)) { if (mrq->stop && !mrq->cmd->error && (!data || !data->error)) {
sh_mmcif_stop_cmd(host, mrq); sh_mmcif_stop_cmd(host, mrq);
if (!mrq->stop->error) if (!mrq->stop->error) {
schedule_delayed_work(&host->timeout_work, host->timeout);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
} }
}
host->wait_for = MMCIF_WAIT_FOR_REQUEST; host->wait_for = MMCIF_WAIT_FOR_REQUEST;
host->state = STATE_IDLE; host->state = STATE_IDLE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment