Hi Guennadi, please could you review this one? On Mon, Jun 17 2013, Shimoda, Yoshihiro wrote: > This patch adds SET_BLOCK_COUNT(CMD23) support to sh_mmcif driver. > If we add MMC_CAP_CMD23 to ".caps" of sh_mmcif_plat_data, the mmc > core driver will use CMD23. Then, the sh_mmcif driver can use > Reliable Write feature. > > Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@xxxxxxxxxxx> > --- > about v2: > - remove the wait_for_completion() to process the .request() asynchronously. > > drivers/mmc/host/sh_mmcif.c | 64 +++++++++++++++++++++++++++++++++++++++--- > 1 files changed, 59 insertions(+), 5 deletions(-) > > diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c > index 8ef5efa..8f66532 100644 > --- a/drivers/mmc/host/sh_mmcif.c > +++ b/drivers/mmc/host/sh_mmcif.c > @@ -223,7 +223,8 @@ enum mmcif_wait_for { > > struct sh_mmcif_host { > struct mmc_host *mmc; > - struct mmc_request *mrq; > + struct mmc_request *mrq; /* current mmc_request pointer */ > + struct mmc_request *mrq_orig; /* original .request()'s pointer */ > struct platform_device *pd; > struct clk *hclk; > unsigned int clk; > @@ -244,6 +245,7 @@ struct sh_mmcif_host { > bool power; > bool card_present; > struct mutex thread_lock; > + struct mmc_request mrq_sbc; /* mmc_request for SBC */ > > /* DMA support */ > struct dma_chan *chan_rx; > @@ -802,7 +804,11 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, > tmp |= CMD_SET_DWEN; > /* CMLTE/CMD12EN */ > if (opc == MMC_READ_MULTIPLE_BLOCK || opc == MMC_WRITE_MULTIPLE_BLOCK) { > - tmp |= CMD_SET_CMLTE | CMD_SET_CMD12EN; > + /* If SBC, we don't use CMD12(STOP) */ > + if (mrq->sbc) > + tmp |= CMD_SET_CMLTE; > + else > + tmp |= CMD_SET_CMLTE | CMD_SET_CMD12EN; > sh_mmcif_bitset(host, MMCIF_CE_BLOCK_SET, > data->blocks << 16); > } > @@ -936,9 +942,27 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) > break; > } > > - host->mrq = mrq; > + if (mrq->sbc) { > + /* Store original mrq to mrq_orig */ > + host->mrq_orig = mrq; > + > + /* Copy original mrq data to mrq_sbc */ > + host->mrq_sbc = *mrq; > > - sh_mmcif_start_cmd(host, mrq); > + /* Switch the mrq_sbc.cmd for SBC */ > + host->mrq_sbc.cmd = mrq->sbc; > + host->mrq_sbc.sbc = NULL; > + host->mrq_sbc.data = NULL; > + host->mrq_sbc.stop = NULL; > + > + /* Set current mrq pointer to mrq_sbc */ > + host->mrq = &host->mrq_sbc; > + } else { > + /* Set current mrq pointer to original mrq */ > + host->mrq = mrq; > + } > + > + sh_mmcif_start_cmd(host, host->mrq); > } > > static int sh_mmcif_clk_update(struct sh_mmcif_host *host) > @@ -1212,13 +1236,35 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) > return IRQ_HANDLED; > } > > + if (mrq->sbc && (mrq->cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK) && > + (host->wait_for != MMCIF_WAIT_FOR_WRITE_END)) { > + /* Wait for end of data phase */ > + host->wait_for = MMCIF_WAIT_FOR_WRITE_END; > + sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE); > + schedule_delayed_work(&host->timeout_work, host->timeout); > + mutex_unlock(&host->thread_lock); > + return IRQ_HANDLED; > + } > + > + if (mrq->sbc && (mrq->cmd->opcode == MMC_READ_MULTIPLE_BLOCK) && > + (host->wait_for != MMCIF_WAIT_FOR_READ_END)) { > + /* Wait for end of data phase */ > + host->wait_for = MMCIF_WAIT_FOR_READ_END; > + sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE); > + schedule_delayed_work(&host->timeout_work, host->timeout); > + mutex_unlock(&host->thread_lock); > + return IRQ_HANDLED; > + } > + > if (host->wait_for != MMCIF_WAIT_FOR_STOP) { > struct mmc_data *data = mrq->data; > if (!mrq->cmd->error && data && !data->error) > data->bytes_xfered = > data->blocks * data->blksz; > > - if (mrq->stop && !mrq->cmd->error && (!data || !data->error)) { > + /* If SBC, we don't use CMD12(STOP) */ > + if (mrq->stop && !mrq->cmd->error && (!data || !data->error) && > + !mrq->sbc) { > sh_mmcif_stop_cmd(host, mrq); > if (!mrq->stop->error) { > schedule_delayed_work(&host->timeout_work, host->timeout); > @@ -1228,6 +1274,14 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) > } > } > > + if ((mrq->cmd->opcode == MMC_SET_BLOCK_COUNT) && !mrq->cmd->error) { > + /* Send the original .request() command */ > + host->mrq = host->mrq_orig; > + sh_mmcif_start_cmd(host, host->mrq); > + mutex_unlock(&host->thread_lock); > + return IRQ_HANDLED; > + } > + > host->wait_for = MMCIF_WAIT_FOR_REQUEST; > host->state = STATE_IDLE; > host->mrq = NULL; -- Chris Ball <cjb@xxxxxxxxxx> <http://printf.net/> One Laptop Per Child -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html