aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci-pci.c
diff options
context:
space:
mode:
authorPierre Ossman <drzeus@drzeus.cx>2008-04-16 13:13:13 -0400
committerPierre Ossman <drzeus@drzeus.cx>2008-07-15 08:14:40 -0400
commit1e72859e3ae16346d4007024b20d2d4ef387dcc3 (patch)
tree5fc8319ce14b0770546bbbf9a72c90abaf019317 /drivers/mmc/host/sdhci-pci.c
parent4489428ab5a49a6f443d9aa17f1d891417787d7b (diff)
sdhci: handle hot-remove
Gracefully handle when the device is suddenly removed. Do a test read and avoid any further access if that read returns -1. Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc/host/sdhci-pci.c')
-rw-r--r--drivers/mmc/host/sdhci-pci.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 5dcb4958e47b..8554466e0f4e 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -47,7 +47,7 @@ struct sdhci_pci_fixes {
47 int (*probe)(struct sdhci_pci_chip*); 47 int (*probe)(struct sdhci_pci_chip*);
48 48
49 int (*probe_slot)(struct sdhci_pci_slot*); 49 int (*probe_slot)(struct sdhci_pci_slot*);
50 void (*remove_slot)(struct sdhci_pci_slot*); 50 void (*remove_slot)(struct sdhci_pci_slot*, int);
51 51
52 int (*suspend)(struct sdhci_pci_chip*, 52 int (*suspend)(struct sdhci_pci_chip*,
53 pm_message_t); 53 pm_message_t);
@@ -209,8 +209,11 @@ static int jmicron_probe_slot(struct sdhci_pci_slot *slot)
209 return 0; 209 return 0;
210} 210}
211 211
212static void jmicron_remove_slot(struct sdhci_pci_slot *slot) 212static void jmicron_remove_slot(struct sdhci_pci_slot *slot, int dead)
213{ 213{
214 if (dead)
215 return;
216
214 if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC) 217 if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC)
215 jmicron_enable_mmc(slot->host, 0); 218 jmicron_enable_mmc(slot->host, 0);
216} 219}
@@ -540,7 +543,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
540 543
541remove: 544remove:
542 if (chip->fixes && chip->fixes->remove_slot) 545 if (chip->fixes && chip->fixes->remove_slot)
543 chip->fixes->remove_slot(slot); 546 chip->fixes->remove_slot(slot, 0);
544 547
545unmap: 548unmap:
546 iounmap(host->ioaddr); 549 iounmap(host->ioaddr);
@@ -554,10 +557,18 @@ release:
554 557
555static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot) 558static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot)
556{ 559{
557 sdhci_remove_host(slot->host); 560 int dead;
561 u32 scratch;
562
563 dead = 0;
564 scratch = readl(slot->host->ioaddr + SDHCI_INT_STATUS);
565 if (scratch == (u32)-1)
566 dead = 1;
567
568 sdhci_remove_host(slot->host, dead);
558 569
559 if (slot->chip->fixes && slot->chip->fixes->remove_slot) 570 if (slot->chip->fixes && slot->chip->fixes->remove_slot)
560 slot->chip->fixes->remove_slot(slot); 571 slot->chip->fixes->remove_slot(slot, dead);
561 572
562 pci_release_region(slot->chip->pdev, slot->pci_bar); 573 pci_release_region(slot->chip->pdev, slot->pci_bar);
563 574