* [PATCH v4 1/3] mmc: core: Support the optional init_card() callback for MMC and SD
2014-12-02 20:49 [PATCH v4 0/3] Fixes for SDIO interrupts for dw_mmc Doug Anderson
@ 2014-12-02 20:49 ` Doug Anderson
2014-12-02 23:15 ` Jaehoon Chung
2014-12-02 20:49 ` [PATCH v4 2/3] mmc: dw_mmc: Cleanup disable of low power mode w/ SDIO interrupts Doug Anderson
2014-12-02 20:49 ` [PATCH v4 3/3] mmc: dw_mmc: Protect read-modify-write of INTMASK with a lock Doug Anderson
2 siblings, 1 reply; 6+ messages in thread
From: Doug Anderson @ 2014-12-02 20:49 UTC (permalink / raw)
To: Jaehoon Chung, Seungwon Jeon, Ulf Hansson
Cc: Alim Akhtar, Sonny Rao, Andrew Bresticker, Heiko Stuebner,
Doug Anderson, tony, linux, chris, gsoutade, axel.lin, s.hauer,
wsa, joe, linux-arm-kernel, linux-omap, linux-kernel, linux-mmc
In (3fcb027 ARM: MXC: mxcmmc: work around a bug in the SDHC busy line
handling) the optional init_card() callback was added. According to
the original change it was "for now only called from
mmc_sdio_init_card()".
This callback really ought to be called from the SD and MMC init
functions as well. One current user of this callback
(mxcmci_init_card) will not work as expected if you insert an SDIO
card, then eject it and put a normal SD card in. Specifically the
normal SD card will not get to run with 4-bit data.
I'd like to use the init_card() callback to handle a similar quirk on
dw_mmc when using SDIO Interrupts (the "low power" feature of the card
needs to be disabled), so that will add a second user of the function.
As part of this change fixup the one place that relied on the callback
only happening for SDIO cards.
Signed-off-by: Doug Anderson <dianders@chromium.org>
Reviewed-by: Grant Grundler <grundler@chromium.org>
---
Changes in v3:
- Add fixup to pandora_wl1251_init_card().
Changes in v2:
- mmc core change new for this version.
arch/arm/mach-omap2/board-omap3pandora.c | 14 ++++++++------
drivers/mmc/core/mmc.c | 6 ++++++
drivers/mmc/core/sd.c | 7 ++++++-
3 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 7f17087..969e100 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -254,12 +254,14 @@ static void pandora_wl1251_init_card(struct mmc_card *card)
* We have TI wl1251 attached to MMC3. Pass this information to
* SDIO core because it can't be probed by normal methods.
*/
- card->quirks |= MMC_QUIRK_NONSTD_SDIO;
- card->cccr.wide_bus = 1;
- card->cis.vendor = 0x104c;
- card->cis.device = 0x9066;
- card->cis.blksize = 512;
- card->cis.max_dtr = 20000000;
+ if (card->type == MMC_TYPE_SDIO || card->type == MMC_TYPE_SD_COMBO) {
+ card->quirks |= MMC_QUIRK_NONSTD_SDIO;
+ card->cccr.wide_bus = 1;
+ card->cis.vendor = 0x104c;
+ card->cis.device = 0x9066;
+ card->cis.blksize = 512;
+ card->cis.max_dtr = 20000000;
+ }
}
static struct omap2_hsmmc_info omap3pandora_mmc[] = {
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 02ad792..4a21d66 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1297,6 +1297,12 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
}
/*
+ * Call the optional HC's init_card function to handle quirks.
+ */
+ if (host->ops->init_card)
+ host->ops->init_card(host, card);
+
+ /*
* For native busses: set card RCA and quit open drain mode.
*/
if (!mmc_host_is_spi(host)) {
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index d90a6de..29fccdc 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -933,6 +933,12 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
}
/*
+ * Call the optional HC's init_card function to handle quirks.
+ */
+ if (host->ops->init_card)
+ host->ops->init_card(host, card);
+
+ /*
* For native busses: get card RCA and quit open drain mode.
*/
if (!mmc_host_is_spi(host)) {
@@ -1271,4 +1277,3 @@ err:
return err;
}
-
--
2.2.0.rc0.207.ga3a616c
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v4 1/3] mmc: core: Support the optional init_card() callback for MMC and SD
2014-12-02 20:49 ` [PATCH v4 1/3] mmc: core: Support the optional init_card() callback for MMC and SD Doug Anderson
@ 2014-12-02 23:15 ` Jaehoon Chung
2014-12-02 23:43 ` Doug Anderson
0 siblings, 1 reply; 6+ messages in thread
From: Jaehoon Chung @ 2014-12-02 23:15 UTC (permalink / raw)
To: Doug Anderson, Seungwon Jeon, Ulf Hansson
Cc: Alim Akhtar, Sonny Rao, Andrew Bresticker, Heiko Stuebner, tony,
linux, chris, gsoutade, axel.lin, s.hauer, wsa, joe,
linux-arm-kernel, linux-omap, linux-kernel, linux-mmc
Hi Doug.
I think good that this patch is separated to two patches.
(board file and codes relevant to mmc.)
Best Regards,
Jaehoon Chung
On 12/03/2014 05:49 AM, Doug Anderson wrote:
> In (3fcb027 ARM: MXC: mxcmmc: work around a bug in the SDHC busy line
> handling) the optional init_card() callback was added. According to
> the original change it was "for now only called from
> mmc_sdio_init_card()".
>
> This callback really ought to be called from the SD and MMC init
> functions as well. One current user of this callback
> (mxcmci_init_card) will not work as expected if you insert an SDIO
> card, then eject it and put a normal SD card in. Specifically the
> normal SD card will not get to run with 4-bit data.
>
> I'd like to use the init_card() callback to handle a similar quirk on
> dw_mmc when using SDIO Interrupts (the "low power" feature of the card
> needs to be disabled), so that will add a second user of the function.
>
> As part of this change fixup the one place that relied on the callback
> only happening for SDIO cards.
>
> Signed-off-by: Doug Anderson <dianders@chromium.org>
> Reviewed-by: Grant Grundler <grundler@chromium.org>
> ---
> Changes in v3:
> - Add fixup to pandora_wl1251_init_card().
>
> Changes in v2:
> - mmc core change new for this version.
>
> arch/arm/mach-omap2/board-omap3pandora.c | 14 ++++++++------
> drivers/mmc/core/mmc.c | 6 ++++++
> drivers/mmc/core/sd.c | 7 ++++++-
> 3 files changed, 20 insertions(+), 7 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
> index 7f17087..969e100 100644
> --- a/arch/arm/mach-omap2/board-omap3pandora.c
> +++ b/arch/arm/mach-omap2/board-omap3pandora.c
> @@ -254,12 +254,14 @@ static void pandora_wl1251_init_card(struct mmc_card *card)
> * We have TI wl1251 attached to MMC3. Pass this information to
> * SDIO core because it can't be probed by normal methods.
> */
> - card->quirks |= MMC_QUIRK_NONSTD_SDIO;
> - card->cccr.wide_bus = 1;
> - card->cis.vendor = 0x104c;
> - card->cis.device = 0x9066;
> - card->cis.blksize = 512;
> - card->cis.max_dtr = 20000000;
> + if (card->type == MMC_TYPE_SDIO || card->type == MMC_TYPE_SD_COMBO) {
> + card->quirks |= MMC_QUIRK_NONSTD_SDIO;
> + card->cccr.wide_bus = 1;
> + card->cis.vendor = 0x104c;
> + card->cis.device = 0x9066;
> + card->cis.blksize = 512;
> + card->cis.max_dtr = 20000000;
> + }
> }
>
> static struct omap2_hsmmc_info omap3pandora_mmc[] = {
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 02ad792..4a21d66 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -1297,6 +1297,12 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
> }
>
> /*
> + * Call the optional HC's init_card function to handle quirks.
> + */
> + if (host->ops->init_card)
> + host->ops->init_card(host, card);
> +
> + /*
> * For native busses: set card RCA and quit open drain mode.
> */
> if (!mmc_host_is_spi(host)) {
> diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
> index d90a6de..29fccdc 100644
> --- a/drivers/mmc/core/sd.c
> +++ b/drivers/mmc/core/sd.c
> @@ -933,6 +933,12 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
> }
>
> /*
> + * Call the optional HC's init_card function to handle quirks.
> + */
> + if (host->ops->init_card)
> + host->ops->init_card(host, card);
> +
> + /*
> * For native busses: get card RCA and quit open drain mode.
> */
> if (!mmc_host_is_spi(host)) {
> @@ -1271,4 +1277,3 @@ err:
>
> return err;
> }
> -
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v4 1/3] mmc: core: Support the optional init_card() callback for MMC and SD
2014-12-02 23:15 ` Jaehoon Chung
@ 2014-12-02 23:43 ` Doug Anderson
0 siblings, 0 replies; 6+ messages in thread
From: Doug Anderson @ 2014-12-02 23:43 UTC (permalink / raw)
To: Jaehoon Chung
Cc: Seungwon Jeon, Ulf Hansson, Alim Akhtar, Sonny Rao,
Andrew Bresticker, Heiko Stuebner, Tony Lindgren, Russell King,
Chris Ball, gsoutade, Axel Lin, Sascha Hauer, Wolfram Sang,
Joe Perches, linux-arm-kernel, linux-omap, linux-kernel,
linux-mmc
Jaehoon,
On Tue, Dec 2, 2014 at 3:15 PM, Jaehoon Chung <jh80.chung@samsung.com> wrote:
> Hi Doug.
>
> I think good that this patch is separated to two patches.
> (board file and codes relevant to mmc.)
Yes, good idea. I've spun v5 with this.
-Doug
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v4 2/3] mmc: dw_mmc: Cleanup disable of low power mode w/ SDIO interrupts
2014-12-02 20:49 [PATCH v4 0/3] Fixes for SDIO interrupts for dw_mmc Doug Anderson
2014-12-02 20:49 ` [PATCH v4 1/3] mmc: core: Support the optional init_card() callback for MMC and SD Doug Anderson
@ 2014-12-02 20:49 ` Doug Anderson
2014-12-02 20:49 ` [PATCH v4 3/3] mmc: dw_mmc: Protect read-modify-write of INTMASK with a lock Doug Anderson
2 siblings, 0 replies; 6+ messages in thread
From: Doug Anderson @ 2014-12-02 20:49 UTC (permalink / raw)
To: Jaehoon Chung, Seungwon Jeon, Ulf Hansson
Cc: Alim Akhtar, Sonny Rao, Andrew Bresticker, Heiko Stuebner,
Doug Anderson, chris, linux-mmc, linux-kernel
In the patch (9623b5b mmc: dw_mmc: Disable low power mode if SDIO
interrupts are used) I added code that disabled the low power mode of
dw_mmc when SDIO interrupts are used. That code worked but always
felt a little hacky because we ended up disabling low power as a side
effect of the first enable_sdio_irq() call. That wouldn't be so bad
except that disabling low power involves a complicated process of
writing to the CMD/CMDARG registers and that extra process makes it
difficult to cleanly the read-modify-write race in
dw_mci_enable_sdio_irq() (see future patch in the series).
Change the code to take advantage of the init_card() callback of the
mmc core to do this right at bootup.
Signed-off-by: Doug Anderson <dianders@chromium.org>
---
Changes in v3: None
Changes in v2:
- Fixed "|" to "&".
drivers/mmc/host/dw_mmc.c | 69 ++++++++++++++++++++++++-----------------------
drivers/mmc/host/dw_mmc.h | 1 +
2 files changed, 36 insertions(+), 34 deletions(-)
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 67c0451..ae10a02 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -27,6 +27,7 @@
#include <linux/stat.h>
#include <linux/delay.h>
#include <linux/irq.h>
+#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/sd.h>
@@ -926,7 +927,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
/* enable clock; only low power if no SDIO */
clk_en_a = SDMMC_CLKEN_ENABLE << slot->id;
- if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->sdio_id)))
+ if (!test_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags))
clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id;
mci_writel(host, CLKENA, clk_en_a);
@@ -1245,27 +1246,37 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
return present;
}
-/*
- * Disable lower power mode.
- *
- * Low power mode will stop the card clock when idle. According to the
- * description of the CLKENA register we should disable low power mode
- * for SDIO cards if we need SDIO interrupts to work.
- *
- * This function is fast if low power mode is already disabled.
- */
-static void dw_mci_disable_low_power(struct dw_mci_slot *slot)
+static void dw_mci_init_card(struct mmc_host *mmc, struct mmc_card *card)
{
+ struct dw_mci_slot *slot = mmc_priv(mmc);
struct dw_mci *host = slot->host;
- u32 clk_en_a;
- const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id;
- clk_en_a = mci_readl(host, CLKENA);
+ /*
+ * Low power mode will stop the card clock when idle. According to the
+ * description of the CLKENA register we should disable low power mode
+ * for SDIO cards if we need SDIO interrupts to work.
+ */
+ if (mmc->caps & MMC_CAP_SDIO_IRQ) {
+ const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id;
+ u32 clk_en_a_old;
+ u32 clk_en_a;
- if (clk_en_a & clken_low_pwr) {
- mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr);
- mci_send_cmd(slot, SDMMC_CMD_UPD_CLK |
- SDMMC_CMD_PRV_DAT_WAIT, 0);
+ clk_en_a_old = mci_readl(host, CLKENA);
+
+ if (card->type == MMC_TYPE_SDIO ||
+ card->type == MMC_TYPE_SD_COMBO) {
+ set_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags);
+ clk_en_a = clk_en_a_old & ~clken_low_pwr;
+ } else {
+ clear_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags);
+ clk_en_a = clk_en_a_old | clken_low_pwr;
+ }
+
+ if (clk_en_a != clk_en_a_old) {
+ mci_writel(host, CLKENA, clk_en_a);
+ mci_send_cmd(slot, SDMMC_CMD_UPD_CLK |
+ SDMMC_CMD_PRV_DAT_WAIT, 0);
+ }
}
}
@@ -1277,21 +1288,11 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
/* Enable/disable Slot Specific SDIO interrupt */
int_mask = mci_readl(host, INTMASK);
- if (enb) {
- /*
- * Turn off low power mode if it was enabled. This is a bit of
- * a heavy operation and we disable / enable IRQs a lot, so
- * we'll leave low power mode disabled and it will get
- * re-enabled again in dw_mci_setup_bus().
- */
- dw_mci_disable_low_power(slot);
-
- mci_writel(host, INTMASK,
- (int_mask | SDMMC_INT_SDIO(slot->sdio_id)));
- } else {
- mci_writel(host, INTMASK,
- (int_mask & ~SDMMC_INT_SDIO(slot->sdio_id)));
- }
+ if (enb)
+ int_mask |= SDMMC_INT_SDIO(slot->sdio_id);
+ else
+ int_mask &= ~SDMMC_INT_SDIO(slot->sdio_id);
+ mci_writel(host, INTMASK, int_mask);
}
static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode)
@@ -1337,7 +1338,7 @@ static const struct mmc_host_ops dw_mci_ops = {
.execute_tuning = dw_mci_execute_tuning,
.card_busy = dw_mci_card_busy,
.start_signal_voltage_switch = dw_mci_switch_voltage,
-
+ .init_card = dw_mci_init_card,
};
static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 0d0f7a2..d27d4c0 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -244,6 +244,7 @@ struct dw_mci_slot {
unsigned long flags;
#define DW_MMC_CARD_PRESENT 0
#define DW_MMC_CARD_NEED_INIT 1
+#define DW_MMC_CARD_NO_LOW_PWR 2
int id;
int sdio_id;
};
--
2.2.0.rc0.207.ga3a616c
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v4 3/3] mmc: dw_mmc: Protect read-modify-write of INTMASK with a lock
2014-12-02 20:49 [PATCH v4 0/3] Fixes for SDIO interrupts for dw_mmc Doug Anderson
2014-12-02 20:49 ` [PATCH v4 1/3] mmc: core: Support the optional init_card() callback for MMC and SD Doug Anderson
2014-12-02 20:49 ` [PATCH v4 2/3] mmc: dw_mmc: Cleanup disable of low power mode w/ SDIO interrupts Doug Anderson
@ 2014-12-02 20:49 ` Doug Anderson
2 siblings, 0 replies; 6+ messages in thread
From: Doug Anderson @ 2014-12-02 20:49 UTC (permalink / raw)
To: Jaehoon Chung, Seungwon Jeon, Ulf Hansson
Cc: Alim Akhtar, Sonny Rao, Andrew Bresticker, Heiko Stuebner,
Doug Anderson, chris, linux-mmc, linux-kernel
We're running into cases where our enabling of the SDIO interrupt in
dw_mmc doesn't actually take effect. Specifically, adding patch like
this:
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1076,6 +1076,9 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
mci_writel(host, INTMASK,
(int_mask | SDMMC_INT_SDIO(slot->id)));
+ int_mask = mci_readl(host, INTMASK);
+ if (!(int_mask & SDMMC_INT_SDIO(slot->id)))
+ dev_err(&mmc->class_dev, "failed to enable sdio irq\n");
} else {
...actually triggers the error message. That's because the
dw_mci_enable_sdio_irq() unsafely does a read-modify-write of the
INTMASK register.
We can't just use the standard host->lock since that lock is not irq
safe and mmc_signal_sdio_irq() (called from interrupt context) calls
dw_mci_enable_sdio_irq(). Add a new irq-safe lock to protect INTMASK.
An alternate solution to this is to punt mmc_signal_sdio_irq() to the
tasklet and then protect INTMASK modifications by the standard host
lock. This seemed like a bit more of a high-latency change.
Reported-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: Doug Anderson <dianders@chromium.org>
Reviewed-by: James Hogan <james.hogan@imgtec.com>
---
Changes in v3: None
Changes in v2:
- intmask_lock renamed to irq_lock
drivers/mmc/host/dw_mmc.c | 13 +++++++++++++
include/linux/mmc/dw_mmc.h | 6 ++++++
2 files changed, 19 insertions(+)
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index ae10a02..64ea042 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -759,6 +759,7 @@ disable:
static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
{
+ unsigned long irqflags;
int sg_len;
u32 temp;
@@ -795,9 +796,11 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
mci_writel(host, CTRL, temp);
/* Disable RX/TX IRQs, let DMA handle it */
+ spin_lock_irqsave(&host->irq_lock, irqflags);
temp = mci_readl(host, INTMASK);
temp &= ~(SDMMC_INT_RXDR | SDMMC_INT_TXDR);
mci_writel(host, INTMASK, temp);
+ spin_unlock_irqrestore(&host->irq_lock, irqflags);
host->dma_ops->start(host, sg_len);
@@ -806,6 +809,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)
{
+ unsigned long irqflags;
u32 temp;
data->error = -EINPROGRESS;
@@ -834,9 +838,12 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)
host->part_buf_count = 0;
mci_writel(host, RINTSTS, SDMMC_INT_TXDR | SDMMC_INT_RXDR);
+
+ spin_lock_irqsave(&host->irq_lock, irqflags);
temp = mci_readl(host, INTMASK);
temp |= SDMMC_INT_TXDR | SDMMC_INT_RXDR;
mci_writel(host, INTMASK, temp);
+ spin_unlock_irqrestore(&host->irq_lock, irqflags);
temp = mci_readl(host, CTRL);
temp &= ~SDMMC_CTRL_DMA_ENABLE;
@@ -1284,8 +1291,11 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
{
struct dw_mci_slot *slot = mmc_priv(mmc);
struct dw_mci *host = slot->host;
+ unsigned long irqflags;
u32 int_mask;
+ spin_lock_irqsave(&host->irq_lock, irqflags);
+
/* Enable/disable Slot Specific SDIO interrupt */
int_mask = mci_readl(host, INTMASK);
if (enb)
@@ -1293,6 +1303,8 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
else
int_mask &= ~SDMMC_INT_SDIO(slot->sdio_id);
mci_writel(host, INTMASK, int_mask);
+
+ spin_unlock_irqrestore(&host->irq_lock, irqflags);
}
static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode)
@@ -2661,6 +2673,7 @@ int dw_mci_probe(struct dw_mci *host)
host->quirks = host->pdata->quirks;
spin_lock_init(&host->lock);
+ spin_lock_init(&host->irq_lock);
INIT_LIST_HEAD(&host->queue);
/*
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index 42b724e..471fb31 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -106,6 +106,11 @@ struct mmc_data;
* @cur_slot, @mrq and @state. These must always be updated
* at the same time while holding @lock.
*
+ * @irq_lock is an irq-safe spinlock protecting the INTMASK register
+ * to allow the interrupt handler to modify it directly. Held for only long
+ * enough to read-modify-write INTMASK and no other locks are grabbed when
+ * holding this one.
+ *
* The @mrq field of struct dw_mci_slot is also protected by @lock,
* and must always be written at the same time as the slot is added to
* @queue.
@@ -125,6 +130,7 @@ struct mmc_data;
*/
struct dw_mci {
spinlock_t lock;
+ spinlock_t irq_lock;
void __iomem *regs;
struct scatterlist *sg;
--
2.2.0.rc0.207.ga3a616c
^ permalink raw reply related [flat|nested] 6+ messages in thread