On Mon, 4 Feb 2019 at 15:18, Ludovic BARRE <ludovic.barre@xxxxxx> wrote: > > hi Ulf > > One comment below in mmci_cmd_irq function > > when I rebase my next serie about "busy detect" I've a kernel panic > null pointer, could you give me some time to investigate this issue > before apply this patch. Sure! FYI, I have tested this on a ux500 and didn't observe any regressions. > > > On 1/29/19 3:35 PM, Ulf Hansson wrote: > > The current approach with sending a CMD12 (STOP_TRANSMISSION) to complete a > > data transfer request, either because of using the open-ended transmission > > type or because of receiving an error during a pre-defined data transfer, > > isn't sufficient for the STM32 sdmmc variant. More precisely, this variant > > needs to clear the DPSM ("Data Path State Machine") by sending a CMD12, for > > all failing ADTC commands. > > > > Support this, by adding a struct mmc_command inside the struct mmci_host > > and initialize it to a CMD12 during ->probe(). Let's also add checks for > > the new conditions, to enable mmci_data_irq() and mmci_cmd_irq() to > > postpone the calls to mmci_request_end(), but instead send the CMD12. > > > > Cc: Ludovic Barre <ludovic.barre@xxxxxx> > > Signed-off-by: Ulf Hansson <ulf.hansson@xxxxxxxxxx> > > --- > > drivers/mmc/host/mmci.c | 25 +++++++++++++++++++++++-- > > drivers/mmc/host/mmci.h | 1 + > > 2 files changed, 24 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c > > index e352f5ad5801..45b97b41601c 100644 > > --- a/drivers/mmc/host/mmci.c > > +++ b/drivers/mmc/host/mmci.c > > @@ -1127,6 +1127,12 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) > > writel(c, base + MMCICOMMAND); > > } > > > > +static void mmci_stop_command(struct mmci_host *host) > > +{ > > + host->stop_abort.error = 0; > > + mmci_start_command(host, &host->stop_abort, 0); > > +} > > + > > static void > > mmci_data_irq(struct mmci_host *host, struct mmc_data *data, > > unsigned int status) > > @@ -1196,10 +1202,16 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, > > /* The error clause is handled above, success! */ > > data->bytes_xfered = data->blksz * data->blocks; > > > > - if (!data->stop || (host->mrq->sbc && !data->error)) > > + if (!data->stop) { > > + if (host->variant->cmdreg_stop && data->error) > > + mmci_stop_command(host); > > + else > > + mmci_request_end(host, data->mrq); > > + } else if (host->mrq->sbc && !data->error) { > > mmci_request_end(host, data->mrq); > > - else > > + } else { > > mmci_start_command(host, data->stop, 0); > > + } > > } > > } > > > > @@ -1298,6 +1310,10 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, > > mmci_dma_error(host); > > > > mmci_stop_data(host); > > + if (host->variant->cmdreg_stop && cmd->error) { > > + mmci_stop_command(host); > > + return; > > + } > > > } > > In fact a cmd without host->data could fail with DPSM enabled. > example: > sent a cmd12 with MMC_RSP_BUSY flag (R1B command) and so no data. > In sdmmc variant the MMCIDATATIMER is used to busy timeout. > The DPSM is used to sample D0 line and is activated. > the DTIMEOUT flag is set after when no end of busy received before the > timeout. (DPSM stays in BUSY and wait for Abort) Oh, that I didn't know about! That make it quite complicated, I am afraid. To send a new CMD12 to clear the DPSM, because the previous CDM12 failed seems just wrong. Why would the second CMD12 succeed and not timeout again, if you see what I mean. There are also other commands using R1B, that doesn't involve transferring data. The CMD5 (sleep) for example. If any of these commands would timeout, then why would a following CMD12 not do so as well? To me, it seems like a reset of the controller is the only really sane way of treating these scenarios, isn't it? Of course, it means we need to be able to restore the state of the controller after such a reset as well. Is this possible? > > So The mmci_stop_command may be sent when there are cmd->error and > status & MCI_DATATIMEOUT > > > > mmci_request_end(host, host->mrq); > > } else if (sbc) { > > @@ -1956,6 +1972,11 @@ static int mmci_probe(struct amba_device *dev, > > mmc->max_busy_timeout = 0; > > } > > > > + /* Prepare a CMD12 - needed to clear the DPSM on some variants. */ > > + host->stop_abort.opcode = MMC_STOP_TRANSMISSION; > > + host->stop_abort.arg = 0; > > + host->stop_abort.flags = MMC_RSP_R1B | MMC_CMD_AC; > > + > > mmc->ops = &mmci_ops; > > > > /* We support these PM capabilities. */ > > diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h > > index 24229097d05c..14df81054438 100644 > > --- a/drivers/mmc/host/mmci.h > > +++ b/drivers/mmc/host/mmci.h > > @@ -377,6 +377,7 @@ struct mmci_host { > > void __iomem *base; > > struct mmc_request *mrq; > > struct mmc_command *cmd; > > + struct mmc_command stop_abort; > > struct mmc_data *data; > > struct mmc_host *mmc; > > struct clk *clk; > > Kind regards Uffe