summaryrefslogtreecommitdiff
path: root/drivers/mmc/host/mmci.c
AgeCommit message (Collapse)AuthorFilesLines
2019-06-19treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500Thomas Gleixner1-4/+1
Based on 2 normalized pattern(s): this program is free software you can redistribute it and or modify it under the terms of the gnu general public license version 2 as published by the free software foundation this program is free software you can redistribute it and or modify it under the terms of the gnu general public license version 2 as published by the free software foundation # extracted by the scancode license scanner the SPDX license identifier GPL-2.0-only has been chosen to replace the boilerplate/reference in 4122 file(s). Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Enrico Weigelt <info@metux.net> Reviewed-by: Kate Stewart <kstewart@linuxfoundation.org> Reviewed-by: Allison Randal <allison@lohutok.net> Cc: linux-spdx@vger.kernel.org Link: https://lkml.kernel.org/r/20190604081206.933168790@linutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2019-05-06mmc: mmci: Prevent polling for busy detection in IRQ contextLudovic Barre1-2/+3
The IRQ handler, mmci_irq(), loops until all status bits have been cleared. However, the status bit signaling busy in variant->busy_detect_flag, may be set even if busy detection isn't monitored for the current request. This may be the case for the CMD11 when switching the I/O voltage, which leads to that mmci_irq() busy loops in IRQ context. Fix this problem, by clearing the status bit for busy, before continuing to validate the condition for the loop. This is safe, because the busy status detection has already been taken care of by mmci_cmd_irq(). Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2019-05-06mmc: mmci: Cleanup mmci_cmd_irq() for busy detectLudovic Barre1-4/+4
Let's cleanup the mmci_cmd_irq() a bit, to make the busy detect code more clear. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2019-04-15mmc: mmci: replace blksz_datactrlXX by get_datactrl_cfg callbackLudovic Barre1-24/+2
This patch allows to get datactrl configuration specific at variant. This introduce more flexibility on datactlr value. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2019-04-15mmc: mmci: define get_dctrl_cfg for legacy variantLudovic Barre1-6/+24
This patch defines get_dctrl_cfg callback for legacy variants whatever DMA_ENGINE configuration. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> [Ulf: Fixed a build error] Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2019-04-15mmc: mmci: Make mmci_variant_init() staticUlf Hansson1-1/+1
As mmci_variant_init() is a local function to mmci.c, let's convert it into static. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Acked-by: Linus Walleij <linus.walleij@linaro.org>
2019-04-15mmc: mmci: Share sdmmc_variant_init() via the common header fileUlf Hansson1-6/+0
It's good practice to share functions via header files, rather than from the c-files. Therefore, let's move sdmmc_variant_init() to mmci.h. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Acked-by: Ludovic Barre <ludovic.barre@st.com> Tested-by: Ludovic Barre <ludovic.barre@st.com> Acked-by: Linus Walleij <linus.walleij@linaro.org>
2019-04-15mmc: mmci: Drop qcom specific header fileUlf Hansson1-1/+0
It seems a bit silly to have a header file to share only the qcom_variant_init() function. So, let's just drop it and move the declaration of the function into the common mmci.h instead. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Acked-by: Linus Walleij <linus.walleij@linaro.org>
2019-04-15mmc: mmci: Re-work code starting DMA for the qcom variantUlf Hansson1-4/+0
Having mmci_dmae_start() to invoke the shared function, dml_start_xfer(), explicitly for the qcom variant isn't very nice. Let's clean up this code by moving the qcom specific parts into the qcom ->dma_start() callback and then drop dml_start_xfer() altogether. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Acked-by: Linus Walleij <linus.walleij@linaro.org>
2019-02-25mmc: mmci: Send a CMD12 to clear the DPSM at errorsUlf Hansson1-2/+23
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@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Tested-by: Ludovic Barre <ludovic.barre@st.com>
2019-02-25mmc: slot-gpio: Remove override_active_level on WPLinus Walleij1-1/+1
The argument "override_active_level" made it possible to enforce a specific polarity on the write-protect GPIO line. All callers in the kernel pass "false" to this call after I have converted all drivers to use GPIO machine descriptors, so remove the argument and clean out this. This kind of polarity inversion should be handled by the GPIO descriptor inside the GPIO library if needed. This rids us of one instance of the kludgy calls into the gpiod_get_raw_value() API. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-12-17mmc: mmci: add variant property to set command stop bitLudovic Barre1-0/+6
On cmd12 (STOP_TRANSMISSION), STM32 sdmmc variant needs to set cmdstop bit in command register. The CPSM ("Command Path State Machine") treats the command as a Stop Transmission command and signals abort to the DPSM ("Data Path State Machine"). Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-12-17mmc: mmci: send stop command if sbc error issueLudovic Barre1-3/+2
Refer to "4.15 set block count command" of sd specification: Host needs to issue CMD12 if any error is detected in the CMD18 and CMD25 operations. In sbc case, the data->stop is fill by framework. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Tested-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: add stm32 sdmmc variantLudovic Barre1-0/+36
This patch adds a stm32 sdmmc variant, rev 1.1. Introduces a new Manufacturer id "0x53, ascii 'S' to define new stm32 sdmmc family with clean range of amba revision/configurations bits (corresponding to sdmmc_ver register with major/minor fields). Add 2 variants properties: -dma_lli, to enable link list support. -stm32_idmabsize_mask, defines the range of SDMMC_IDMABSIZER register which specify the number bytes per buffer. DT properties for sdmmc: -Indicate signal directions (only one property for d0dir, d123dir, cmd_dir) -Select command and data phase relation. -Select "clock in" from an external driver. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: add clock divider for stm32 sdmmcLudovic Barre1-0/+2
The STM32 sdmmc variant has a different clock divider. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: add optional reset propertyLudovic Barre1-0/+7
This patch adds a optional reset management. STM32 sdmmc variant needs to reset hardware block during the power cycle procedure (for re-initialization). Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: add variant property to not read datacntLudovic Barre1-2/+6
This patch adds a boolean property to not read datacnt register. Needed to support the STM32 sdmmc variant. MMCIDATACNT register should be read only after the data transfer is completed. When reading after an error event the read data count value may be different from the real number of data bytes transferred. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: add variant property to write datactrl before commandLudovic Barre1-2/+4
This patch adds a boolean property to allow to write datactrl before to send command, whatever the command type (read or write). Needed to support the STM32 sdmmc variant. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: add variant property to define irq pio maskLudovic Barre1-2/+11
This patch allows to define specific pio mask for variants. Needed to support the STM32 sdmmc variant which has some bits with different meaning (bits: 21,20,13,12,9) Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: add variant property to define dpsm bitLudovic Barre1-3/+12
This patch adds datactrl variant property to define dpsm enable bit. Needed to support the STM32 variant (STM32 has no dpsm enable bit). Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: add variant properties to define cpsm & cmdresp bitsLudovic Barre1-4/+43
This patch adds command variant properties to define cpsm enable bit and responses. Needed to support the STM32 variant (shift of cpsm bit, specific definition of commands response). Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: expand startbiterr to irqmask and error checkLudovic Barre1-11/+16
All variants don't pretend to have a startbiterr. -While data error check, if status register return an error (like MCI_DATACRCFAIL) we must avoid to check MCI_STARTBITERR (if not desired). -expand start_err to MCI_IRQENABLE to avoid to set this bit by default. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: add datactrl block size variant propertyLudovic Barre1-2/+11
This patch allows to define a datactrl block size by variant, requested by STM32 sdmmc variant. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: add set_clk/pwrreg callbacksLudovic Barre1-4/+12
This patch adds set_clkreg and set_pwrreg callbacks at mmci_host_ops to allow to call specific variant. extends visibility of mmci_write_clk/pwrreg functions to be used into specific file variant. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: add validate_data callbackLudovic Barre1-18/+21
This patch adds validate_data callback at mmci_host_ops to check specific constraints of variant. Move mmci_validate_data function to regroup mmci_host_ops interfaces. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: add dma_error callbackLudovic Barre1-11/+15
This patch adds dma_error callback at mmci_host_ops to allow to call specific variant. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: add dma_finalize callbackLudovic Barre1-7/+12
This patch adds dma_finalize callback at mmci_host_ops to allow to call specific variant. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: add dma_start callbackLudovic Barre1-30/+39
This patch adds dma_start callback to mmci_host_ops. Create a generic mmci_dma_start function which regroup common action between variant. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: add get_next_data callbackLudovic Barre1-6/+10
This patch adds get_next_data callback to mmci_host_ops. Generic mmci_get_next_data factorizes next_cookie check and the host ops call. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: add prepare/unprepare_data callbacksLudovic Barre1-33/+68
This patch adds prepare/unprepare callbacks to mmci_host_ops. Like this mmci_pre/post_request can be generic, mmci_prepare_data and mmci_unprepare_data provide common next_cookie management. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: merge prepare data functionsLudovic Barre1-12/+7
This patch merges the prepare data functions. This allows to define a single access to prepare data service. This prepares integration for mmci host ops. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: introduce dma_priv pointer to mmci_hostLudovic Barre1-54/+90
-Introduces dma_priv pointer to define specific needs for each dma engine. This patch is needed to prepare sdmmc variant with internal dma which not use dmaengine API. -Moves next cookie to mmci host structure to share same cookie management between all variants. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-09mmc: mmci: create common mmci_dma_setup/releaseLudovic Barre1-15/+60
This patch creates a common mmci_dma_setup/release which calls dma_setup/release callbacks of mmci_host_ops and manages common features like use_dma... If there is a fallbacks to pio mode, dma functions must check use_dma. error management: -mmci_dmae_setup fail if Tx and Rx dma channels are not defined -qcom_dma_setup fail if one of both dma channels is not defined, Qcom has no specific resource to release, just mmci dmae resource. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-08mmc: mmci: internalize dma_inprogress into mmci dma functionsLudovic Barre1-6/+10
This patch internalizes the dma_inprogress into mmci dma interfaces. This allows to simplify and prepare the next dma callbacks for mmci host ops. dma_inprogress is called in mmci_dma_data_error and mmci_dma_finalize. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-08mmc: mmci: internalize dma map/unmap into mmci dma functionsLudovic Barre1-23/+17
This patch internalizes the management of dma map/unmap into mmci dma interfaces. This allows to simplify and prepare the next dma callbacks for mmci host ops. mmci_dma_unmap was called in mmci_data_irq & mmci_cmd_irq functions and can be integrated in mmci_dma_data_error. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-10-08mmc: mmci: Drop support for pdata GPIO numbersLinus Walleij1-28/+6
All the machines using the MMCI are passing GPIOs for the card detect and write protect using the device tree or descriptor table (one single case, Integrator/AP IM-PD1). Drop support for passing global GPIO numbers through platform data, noone is using it. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-08-01mmc: mmci: Add and implement a ->dma_setup() callback for qcom dmlUlf Hansson1-4/+3
As a first step to improve the variant specific code for mmci, add a ->dma_setup() callback to the struct mmci_host_ops. To show its use, let's deploy the callback for the qcom dml, which involves also to the assign the mmci_host_ops pointer from the variant ->init() callback. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Reviewed-by: Ludovic Barre <ludovic.barre@st.com>
2018-07-30mmc: mmci: Initial support to manage variant specific callbacksUlf Hansson1-72/+3
To be able to better support different mmci variants, we need to be able to use variant specific callbacks, rather than continue to sprinkle the code with additional variant data. To move in this direction, let's add an optional ->init() callback to the variant data struct, which variants shall use to assign the mmci_host_ops pointer. Using an ->init() callback enables us to partition the code between different files. To allow separate mmci variant files to implement the variant specifics, let's also move the definition of the struct variant_data to the common mmci header file. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Reviewed-by: Ludovic Barre <ludovic.barre@st.com> Acked-by: Linus Walleij <linus.walleij@linaro.org>
2018-05-02mmc: mmci: Remove bogus local_irq_save()Thomas Gleixner1-5/+0
On !RT interrupt runs with interrupts disabled. On RT it's in a thread, so no need to disable interrupts at all. Remove the local_irq_save() invocation. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-01-24mmc: mmci: fix error return code in mmci_probe()Wei Yongjun1-0/+3
Fix to return a negative error code from the error handling case instead of 0, as done elsewhere in this function. Fixes: f9bb304ce855 ("mmc: mmci: Add support for setting pad type via pinctrl") Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com> Reviewed-by: Patrice Chotard <patrice.chotard@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-01-18mmc: mmci: Add STM32 variantPatrice Chotard1-0/+22
STM32F4 and STM32F7 MCUs has a SDIO controller that looks like an ARM PL810. This patch adds the STM32 variant so that mmci driver supports it. Signed-off-by: Andrea Merello <andrea.merello@gmail.com> Signed-off-by: Patrice Chotard <patrice.chotard@st.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-01-18mmc: mmci: Add support for setting pad type via pinctrlPatrice Chotard1-2/+39
If variant hasn't the control bit to switch pads in opendrain mode, we can achieve the same result by asking to the pinmux driver to configure pins for us. This patch make the mmci driver able to do this whenever needed. Signed-off-by: Andrea Merello <andrea.merello@gmail.com> Signed-off-by: Patrice Chotard <patrice.chotard@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-01-18mmc: mmci: Don't pretend all variants to have OPENDRAIN bitPatrice Chotard1-11/+12
This patch prepares for supporting STM32 variant which doesn't have opendrain bit in MMCIPOWER register. ST others variant (u300, nomadik and ux500) uses MCI_OD bit whereas others variants uses MCI_ROD bit. Signed-off-by: Patrice Chotard <patrice.chotard@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-01-18mmc: mmci: Don't pretend all variants to have MCI_STARBITERR flagPatrice Chotard1-2/+14
This patch prepares for supporting the STM32 variant that has no such bit in the status register. Signed-off-by: Andrea Merello <andrea.merello@gmail.com> Signed-off-by: Patrice Chotard <patrice.chotard@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-01-18mmc: mmci: Don't pretend all variants to have MMCIMASK1 registerPatrice Chotard1-4/+24
Two mask registers are used in order to select which events have to actually generate an interrupt on each IRQ line. It seems that in the single-IRQ case it's assumed that the IRQs lines are simply OR-ed, while the two mask registers are still present. The driver still programs the two mask registers separately. However the STM32 variant has only one IRQ, and also has only one mask register. This patch prepares for STM32 variant support by making the driver using only one mask register. This patch also optimize the MMCIMASK1 mask usage by caching it into host->mask1_reg which avoid to read it into mmci_irq(). Tested only on STM32 variant. RFT for variants other than STM32 Signed-off-by: Andrea Merello <andrea.merello@gmail.com> Signed-off-by: Patrice Chotard <patrice.chotard@st.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-10-30mmc: mmci: catch all errors when getting regulatorsWolfram Sang1-1/+1
Bail out everytime when mmc_regulator_get_supply() returns an errno, not only when probing gets deferred. This is currently a no-op, because this function only returns -EPROBE_DEFER or 0 right now. But if it will throw another error somewhen, it will be for a reason. (This still doesn't change that getting regulators is optional, so 0 can still mean no regulators found). So, let us a) be future proof and b) have driver code which is easier to understand. Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-08-30mmc: mmci: constify amba_idArvind Yadav1-1/+1
amba_id are not supposed to change at runtime. All functions working with const amba_id. So mark the non-const structs as const. Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-04-24mmc: use new core function mmc_get_dma_dirHeiner Kallweit1-12/+8
Use new core function mmc_get_dma_dir(). Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-02-13mmc: core/mmci: restore pre/post_req behaviourLinus Walleij1-1/+6
commit 64b12a68a9f74bb32d8efd7af1ad8a2ba02fc884 "mmc: core: fix prepared requests while doing bkops" is fixing a bug in the wrong way. A bug in the MMCI device driver is fixed by amending the MMC core. Thinking about it: what the pre- and post-callbacks are doing is to essentially map and unmap SG lists for DMA transfers. Why would we not be able to do that just because a BKOPS command is sent inbetween? Having to unprepare/prepare the next asynchronous request for DMA seems wrong. Looking the backtrace in that commit we can see what the real problem actually is: mmci_data_irq() is calling mmci_dma_unmap() twice which is goung to call arm_dma_unmap_sg() twice and v7_dma_inv_range() twice for the same sglist and that will crash. This happens because a request is prepared, then a BKOPS is sent. The IRQ completing the BKOPS command goes through mmci_data_irq() and thinks that a DMA operation has just been completed because dma_inprogress() reports true. It then proceeds to unmap the sglist. But that was wrong! dma_inprogress() should NOT be true because no DMA was actually in progress! We had just prepared the sglist, and the DMA channel dma_current has been configured, but NOT started! Because of this, the sglist is already unmapped when we get our actual data completion IRQ, and we are unmapping the sglist once more, and we get this crash. Therefore, we need to revert this solution pushing the problem to the core and causing problems, and instead augment the implementation such that dma_inprogress() only reports true if some DMA has actually been started. After this we can keep the request prepared during the BKOPS and we need not unprepare/reprepare it. Fixes: 64b12a68a9f7 ("mmc: core: fix prepared requests while doing bkops") Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-02-08mmc: mmci: avoid clearing ST Micro busy end interrupt mistakenlyJean-Nicolas Graux1-7/+25
This fixes a race condition that may occur whenever ST micro busy end interrupt is raised just after being unmasked but before leaving mmci interrupt context. A dead-lock has been found if connecting mmci ST Micro variant whose amba id is 0x10480180 to some new eMMC that supports internal caches. Whenever mmci driver enables cache control by programming eMMC's EXT_CSD register, block driver may request to flush the eMMC internal caches causing mmci driver to send a MMC_SWITCH command to the card with FLUSH_CACHE operation. And because busy end interrupt may be mistakenly cleared while not yet processed, this mmc request may never complete. As a result, mmcqd task may be stuck forever. Here is an instance caught by lockup detector which shows that mmcqd task was hung while waiting for mmc_flush_cache command to complete: .. [ 240.251595] INFO: task mmcqd/1:52 blocked for more than 120 seconds. [ 240.257973] Not tainted 4.1.13-00510-g9d91424 #2 [ 240.263109] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 240.270955] mmcqd/1 D c047504c 0 52 2 0x00000000 [ 240.277359] [<c047504c>] (__schedule) from [<c04754a0>] (schedule+0x40/0x98) [ 240.284418] [<c04754a0>] (schedule) from [<c0477d40>] (schedule_timeout+0x148/0x188) [ 240.292191] [<c0477d40>] (schedule_timeout) from [<c0476040>] (wait_for_common+0xa4/0x170) [ 240.300491] [<c0476040>] (wait_for_common) from [<c02efc1c>] (mmc_wait_for_req_done+0x4c/0x13c) [ 240.309224] [<c02efc1c>] (mmc_wait_for_req_done) from [<c02efd90>] (mmc_wait_for_cmd+0x64/0x84) [ 240.317953] [<c02efd90>] (mmc_wait_for_cmd) from [<c02f5b14>] (__mmc_switch+0xa4/0x2a8) [ 240.325964] [<c02f5b14>] (__mmc_switch) from [<c02f5d40>] (mmc_switch+0x28/0x30) [ 240.333389] [<c02f5d40>] (mmc_switch) from [<c02f0984>] (mmc_flush_cache+0x54/0x80) [ 240.341073] [<c02f0984>] (mmc_flush_cache) from [<c02ff0c4>] (mmc_blk_issue_rq+0x114/0x4e8) [ 240.349459] [<c02ff0c4>] (mmc_blk_issue_rq) from [<c03008d4>] (mmc_queue_thread+0xc0/0x180) [ 240.357844] [<c03008d4>] (mmc_queue_thread) from [<c003cf90>] (kthread+0xdc/0xf4) [ 240.365339] [<c003cf90>] (kthread) from [<c0010068>] (ret_from_fork+0x14/0x2c) .. .. [ 240.664311] INFO: task partprobe:564 blocked for more than 120 seconds. [ 240.670943] Not tainted 4.1.13-00510-g9d91424 #2 [ 240.676078] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 240.683922] partprobe D c047504c 0 564 486 0x00000000 [ 240.690318] [<c047504c>] (__schedule) from [<c04754a0>] (schedule+0x40/0x98) [ 240.697396] [<c04754a0>] (schedule) from [<c0477d40>] (schedule_timeout+0x148/0x188) [ 240.705149] [<c0477d40>] (schedule_timeout) from [<c0476040>] (wait_for_common+0xa4/0x170) [ 240.713446] [<c0476040>] (wait_for_common) from [<c01f3300>] (submit_bio_wait+0x58/0x64) [ 240.721571] [<c01f3300>] (submit_bio_wait) from [<c01fbbd8>] (blkdev_issue_flush+0x60/0x88) [ 240.729957] [<c01fbbd8>] (blkdev_issue_flush) from [<c010ff84>] (blkdev_fsync+0x34/0x44) [ 240.738083] [<c010ff84>] (blkdev_fsync) from [<c0109594>] (do_fsync+0x3c/0x64) [ 240.745319] [<c0109594>] (do_fsync) from [<c000ffc0>] (ret_fast_syscall+0x0/0x3c) .. Here is the detailed sequence showing when this issue may happen: 1) At probe time, mmci device is initialized and card busy detection based on DAT[0] monitoring is enabled. 2) Later during run time, since card reported to support internal caches, a MMCI_SWITCH command is sent to eMMC device with FLUSH_CACHE operation. On receiving this command, eMMC may enter busy state (for a relatively short time in the case of the dead-lock). 3) Then mmci interrupt is raised and mmci_irq() is called: MMCISTATUS register is read and is equal to 0x01000440. So the following status bits are set: - MCI_CMDRESPEND (= 6) - MCI_DATABLOCKEND (= 10) - MCI_ST_CARDBUSY (= 24) Since MMCIMASK0 register is 0x3FF, status variable is set to 0x00000040 and BIT MCI_CMDRESPEND is cleared by writing MMCICLEAR register. Then mmci_cmd_irq() is called. Considering the following conditions: - host->busy_status is 0, - this is a "busy response", - reading again MMCISTATUS register gives 0x1000400, MMCIMASK0 is updated to unmask MCI_ST_BUSYEND bit. Thus, MMCIMASK0 is set to 0x010003FF and host->busy_status is set to wait for busy end completion. Back again in status loop of mmci_irq(), we quickly go through mmci_data_irq() as there are no data in that case. And we finally go through following test at the end of while(status) loop: /* * Don't poll for busy completion in irq context. */ if (host->variant->busy_detect && host->busy_status) status &= ~host->variant->busy_detect_flag; Because status variable is not yet null (is equal to 0x40), we do not leave interrupt context yet but we loop again into while(status) loop. So we run across following steps: a) MMCISTATUS register is read again and this time is equal to 0x01000400. So that following bits are set: - MCI_DATABLOCKEND (= 10) - MCI_ST_CARDBUSY (= 24) Since MMCIMASK0 register is equal to 0x010003FF: b) status variable is set to 0x01000000. c) MCI_ST_CARDBUSY bit is cleared by writing MMCICLEAR register. Then, mmci_cmd_irq() is called one more time. Since host->busy_status is set and that MCI_ST_CARDBUSY is set in status variable, we just return from this function. Back again in mmci_irq(), status variable is set to 0 and we finally leave the while(status) loop. As a result we leave interrupt context, waiting for busy end interrupt event. Now, consider that busy end completion is raised IN BETWEEN steps 3.a) and 3.c). In such a case, we may mistakenly clear busy end interrupt at step 3.c) while it has not yet been processed. This will result in mmc command to wait forever for a busy end completion that will never happen. To fix the problem, this patch implements the following changes: Considering that the mmci seems to be triggering the IRQ on both edges while monitoring DAT0 for busy completion and that same status bit is used to monitor start and end of busy detection, special care must be taken to make sure that both start and end interrupts are always cleared one after the other. 1) Clearing of card busy bit is moved in mmc_cmd_irq() function where unmasking of busy end bit is effectively handled. 2) Just before unmasking busy end event, busy start event is cleared by writing card busy bit in MMCICLEAR register. 3) Finally, once we are no more busy with a command, busy end event is cleared writing again card busy bit in MMCICLEAR register. This patch has been tested with the ST Accordo5 machine, not yet supported upstream but relies on the mmci driver. Signed-off-by: Sarang Mairal <sarang.mairal@garmin.com> Signed-off-by: Jean-Nicolas Graux <jean-nicolas.graux@st.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>