Skip to content
This repository was archived by the owner on Oct 5, 2018. It is now read-only.

Commit a2da77c

Browse files
dianderskoenkooi
authored andcommitted
mmc: dw_mmc: Only enable CD after setup and only if needed
We really don't want to get a card detect interrupt during probe time since it can confuse things. Let's disable the card detect interrupt until we're in a really good place: the end of probe. Let's also simply avoid enabling the card detect interrupt if it's not used. It appears that (at least on rk3288) when vqmmc is turned on it can cause a bogus "card detect" interrupt. That meant that we were getting a predictable card detect interrupt while we were in mmc_add_host(). On the version of the kernel I'm working with at least (3.14), this is not a great time to get a card detect interrupt since I think that we don't grab all the needed locks in mmc_add_host() and children. I put stack dumps in dw_mci_setup_bus() and found that I could see two distinct stack crawls that looked like: Caller one: * dw_mci_setup_bus * dw_mci_set_ios * mmc_power_up * mmc_start_host * mmc_add_host Caller two: * dw_mci_setup_bus * dw_mci_set_ios * mmc_set_chip_select * mmc_go_idle * mmc_rescan * process_one_work * worker_thread * kthread Signed-off-by: Doug Anderson <[email protected]> Tested-by: Javier Martinez Canillas <[email protected]> Signed-off-by: Jaehoon Chung <[email protected]> Signed-off-by: Ulf Hansson <[email protected]>
1 parent d9d4daf commit a2da77c

File tree

1 file changed

+38
-3
lines changed

1 file changed

+38
-3
lines changed

drivers/mmc/host/dw_mmc.c

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2650,6 +2650,34 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
26502650
}
26512651
#endif /* CONFIG_OF */
26522652

2653+
static void dw_mci_enable_cd(struct dw_mci *host)
2654+
{
2655+
struct dw_mci_board *brd = host->pdata;
2656+
unsigned long irqflags;
2657+
u32 temp;
2658+
int i;
2659+
2660+
/* No need for CD if broken card detection */
2661+
if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
2662+
return;
2663+
2664+
/* No need for CD if all slots have a non-error GPIO */
2665+
for (i = 0; i < host->num_slots; i++) {
2666+
struct dw_mci_slot *slot = host->slot[i];
2667+
2668+
if (IS_ERR_VALUE(mmc_gpio_get_cd(slot->mmc)))
2669+
break;
2670+
}
2671+
if (i == host->num_slots)
2672+
return;
2673+
2674+
spin_lock_irqsave(&host->irq_lock, irqflags);
2675+
temp = mci_readl(host, INTMASK);
2676+
temp |= SDMMC_INT_CD;
2677+
mci_writel(host, INTMASK, temp);
2678+
spin_unlock_irqrestore(&host->irq_lock, irqflags);
2679+
}
2680+
26532681
int dw_mci_probe(struct dw_mci *host)
26542682
{
26552683
const struct dw_mci_drv_data *drv_data = host->drv_data;
@@ -2839,13 +2867,13 @@ int dw_mci_probe(struct dw_mci *host)
28392867
host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1;
28402868

28412869
/*
2842-
* Enable interrupts for command done, data over, data empty, card det,
2870+
* Enable interrupts for command done, data over, data empty,
28432871
* receive ready and error such as transmit, receive timeout, crc error
28442872
*/
28452873
mci_writel(host, RINTSTS, 0xFFFFFFFF);
28462874
mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
28472875
SDMMC_INT_TXDR | SDMMC_INT_RXDR |
2848-
DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
2876+
DW_MCI_ERROR_FLAGS);
28492877
mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
28502878

28512879
dev_info(host->dev, "DW MMC controller at irq %d, "
@@ -2862,6 +2890,9 @@ int dw_mci_probe(struct dw_mci *host)
28622890
init_slots++;
28632891
}
28642892

2893+
/* Now that slots are all setup, we can enable card detect */
2894+
dw_mci_enable_cd(host);
2895+
28652896
if (init_slots) {
28662897
dev_info(host->dev, "%d slots initialized\n", init_slots);
28672898
} else {
@@ -2959,7 +2990,7 @@ int dw_mci_resume(struct dw_mci *host)
29592990
mci_writel(host, RINTSTS, 0xFFFFFFFF);
29602991
mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
29612992
SDMMC_INT_TXDR | SDMMC_INT_RXDR |
2962-
DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
2993+
DW_MCI_ERROR_FLAGS);
29632994
mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE);
29642995

29652996
for (i = 0; i < host->num_slots; i++) {
@@ -2971,6 +3002,10 @@ int dw_mci_resume(struct dw_mci *host)
29713002
dw_mci_setup_bus(slot, true);
29723003
}
29733004
}
3005+
3006+
/* Now that slots are all setup, we can enable card detect */
3007+
dw_mci_enable_cd(host);
3008+
29743009
return 0;
29753010
}
29763011
EXPORT_SYMBOL(dw_mci_resume);

0 commit comments

Comments
 (0)