diff options
author | Pierre Ossman <drzeus@drzeus.cx> | 2008-04-16 13:13:13 -0400 |
---|---|---|
committer | Pierre Ossman <drzeus@drzeus.cx> | 2008-07-15 08:14:40 -0400 |
commit | 1e72859e3ae16346d4007024b20d2d4ef387dcc3 (patch) | |
tree | 5fc8319ce14b0770546bbbf9a72c90abaf019317 /drivers/mmc/host/sdhci-pci.c | |
parent | 4489428ab5a49a6f443d9aa17f1d891417787d7b (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.c | 21 |
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 | ||
212 | static void jmicron_remove_slot(struct sdhci_pci_slot *slot) | 212 | static 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 | ||
541 | remove: | 544 | remove: |
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 | ||
545 | unmap: | 548 | unmap: |
546 | iounmap(host->ioaddr); | 549 | iounmap(host->ioaddr); |
@@ -554,10 +557,18 @@ release: | |||
554 | 557 | ||
555 | static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot) | 558 | static 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 | ||