Loading drivers/mmc/host/sdhci-pci.c +16 −5 Original line number Diff line number Diff line Loading @@ -47,7 +47,7 @@ struct sdhci_pci_fixes { int (*probe)(struct sdhci_pci_chip*); int (*probe_slot)(struct sdhci_pci_slot*); void (*remove_slot)(struct sdhci_pci_slot*); void (*remove_slot)(struct sdhci_pci_slot*, int); int (*suspend)(struct sdhci_pci_chip*, pm_message_t); Loading Loading @@ -209,8 +209,11 @@ static int jmicron_probe_slot(struct sdhci_pci_slot *slot) return 0; } static void jmicron_remove_slot(struct sdhci_pci_slot *slot) static void jmicron_remove_slot(struct sdhci_pci_slot *slot, int dead) { if (dead) return; if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC) jmicron_enable_mmc(slot->host, 0); } Loading Loading @@ -540,7 +543,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( remove: if (chip->fixes && chip->fixes->remove_slot) chip->fixes->remove_slot(slot); chip->fixes->remove_slot(slot, 0); unmap: iounmap(host->ioaddr); Loading @@ -554,10 +557,18 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot) { sdhci_remove_host(slot->host); int dead; u32 scratch; dead = 0; scratch = readl(slot->host->ioaddr + SDHCI_INT_STATUS); if (scratch == (u32)-1) dead = 1; sdhci_remove_host(slot->host, dead); if (slot->chip->fixes && slot->chip->fixes->remove_slot) slot->chip->fixes->remove_slot(slot); slot->chip->fixes->remove_slot(slot, dead); pci_release_region(slot->chip->pdev, slot->pci_bar); Loading drivers/mmc/host/sdhci.c +40 −8 Original line number Diff line number Diff line Loading @@ -712,7 +712,8 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) host->mrq = mrq; if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) { if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT) || (host->flags & SDHCI_DEVICE_DEAD)) { host->mrq->cmd->error = -ENOMEDIUM; tasklet_schedule(&host->finish_tasklet); } else Loading @@ -732,6 +733,9 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) spin_lock_irqsave(&host->lock, flags); if (host->flags & SDHCI_DEVICE_DEAD) goto out; /* * Reset the chip on each power off. * Should clear out any weird states. Loading Loading @@ -770,6 +774,7 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); out: mmiowb(); spin_unlock_irqrestore(&host->lock, flags); } Loading @@ -784,6 +789,9 @@ static int sdhci_get_ro(struct mmc_host *mmc) spin_lock_irqsave(&host->lock, flags); if (host->flags & SDHCI_DEVICE_DEAD) present = 0; else present = readl(host->ioaddr + SDHCI_PRESENT_STATE); spin_unlock_irqrestore(&host->lock, flags); Loading @@ -801,6 +809,9 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) spin_lock_irqsave(&host->lock, flags); if (host->flags & SDHCI_DEVICE_DEAD) goto out; ier = readl(host->ioaddr + SDHCI_INT_ENABLE); ier &= ~SDHCI_INT_CARD_INT; Loading @@ -810,6 +821,7 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) writel(ier, host->ioaddr + SDHCI_INT_ENABLE); writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE); out: mmiowb(); spin_unlock_irqrestore(&host->lock, flags); Loading Loading @@ -875,10 +887,11 @@ static void sdhci_tasklet_finish(unsigned long param) * The controller needs a reset of internal state machines * upon error conditions. */ if (mrq->cmd->error || if (!(host->flags & SDHCI_DEVICE_DEAD) && (mrq->cmd->error || (mrq->data && (mrq->data->error || (mrq->data->stop && mrq->data->stop->error))) || (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)) { (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) { /* Some controllers need this kick or reset won't work here */ if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) { Loading Loading @@ -1378,14 +1391,33 @@ int sdhci_add_host(struct sdhci_host *host) EXPORT_SYMBOL_GPL(sdhci_add_host); void sdhci_remove_host(struct sdhci_host *host) void sdhci_remove_host(struct sdhci_host *host, int dead) { unsigned long flags; if (dead) { spin_lock_irqsave(&host->lock, flags); host->flags |= SDHCI_DEVICE_DEAD; if (host->mrq) { printk(KERN_ERR "%s: Controller removed during " " transfer!\n", mmc_hostname(host->mmc)); host->mrq->cmd->error = -ENOMEDIUM; tasklet_schedule(&host->finish_tasklet); } spin_unlock_irqrestore(&host->lock, flags); } mmc_remove_host(host->mmc); #ifdef CONFIG_LEDS_CLASS led_classdev_unregister(&host->led); #endif if (!dead) sdhci_reset(host, SDHCI_RESET_ALL); free_irq(host->irq, host); Loading drivers/mmc/host/sdhci.h +2 −1 Original line number Diff line number Diff line Loading @@ -198,6 +198,7 @@ struct sdhci_host { int flags; /* Host attributes */ #define SDHCI_USE_DMA (1<<0) /* Host is DMA capable */ #define SDHCI_REQ_USE_DMA (1<<1) /* Use DMA for this req. */ #define SDHCI_DEVICE_DEAD (1<<2) /* Device unresponsive */ unsigned int max_clk; /* Max possible freq (MHz) */ unsigned int timeout_clk; /* Timeout freq (KHz) */ Loading Loading @@ -239,7 +240,7 @@ static inline void *sdhci_priv(struct sdhci_host *host) } extern int sdhci_add_host(struct sdhci_host *host); extern void sdhci_remove_host(struct sdhci_host *host); extern void sdhci_remove_host(struct sdhci_host *host, int dead); #ifdef CONFIG_PM extern int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state); Loading Loading
drivers/mmc/host/sdhci-pci.c +16 −5 Original line number Diff line number Diff line Loading @@ -47,7 +47,7 @@ struct sdhci_pci_fixes { int (*probe)(struct sdhci_pci_chip*); int (*probe_slot)(struct sdhci_pci_slot*); void (*remove_slot)(struct sdhci_pci_slot*); void (*remove_slot)(struct sdhci_pci_slot*, int); int (*suspend)(struct sdhci_pci_chip*, pm_message_t); Loading Loading @@ -209,8 +209,11 @@ static int jmicron_probe_slot(struct sdhci_pci_slot *slot) return 0; } static void jmicron_remove_slot(struct sdhci_pci_slot *slot) static void jmicron_remove_slot(struct sdhci_pci_slot *slot, int dead) { if (dead) return; if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC) jmicron_enable_mmc(slot->host, 0); } Loading Loading @@ -540,7 +543,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( remove: if (chip->fixes && chip->fixes->remove_slot) chip->fixes->remove_slot(slot); chip->fixes->remove_slot(slot, 0); unmap: iounmap(host->ioaddr); Loading @@ -554,10 +557,18 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot) { sdhci_remove_host(slot->host); int dead; u32 scratch; dead = 0; scratch = readl(slot->host->ioaddr + SDHCI_INT_STATUS); if (scratch == (u32)-1) dead = 1; sdhci_remove_host(slot->host, dead); if (slot->chip->fixes && slot->chip->fixes->remove_slot) slot->chip->fixes->remove_slot(slot); slot->chip->fixes->remove_slot(slot, dead); pci_release_region(slot->chip->pdev, slot->pci_bar); Loading
drivers/mmc/host/sdhci.c +40 −8 Original line number Diff line number Diff line Loading @@ -712,7 +712,8 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) host->mrq = mrq; if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) { if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT) || (host->flags & SDHCI_DEVICE_DEAD)) { host->mrq->cmd->error = -ENOMEDIUM; tasklet_schedule(&host->finish_tasklet); } else Loading @@ -732,6 +733,9 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) spin_lock_irqsave(&host->lock, flags); if (host->flags & SDHCI_DEVICE_DEAD) goto out; /* * Reset the chip on each power off. * Should clear out any weird states. Loading Loading @@ -770,6 +774,7 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); out: mmiowb(); spin_unlock_irqrestore(&host->lock, flags); } Loading @@ -784,6 +789,9 @@ static int sdhci_get_ro(struct mmc_host *mmc) spin_lock_irqsave(&host->lock, flags); if (host->flags & SDHCI_DEVICE_DEAD) present = 0; else present = readl(host->ioaddr + SDHCI_PRESENT_STATE); spin_unlock_irqrestore(&host->lock, flags); Loading @@ -801,6 +809,9 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) spin_lock_irqsave(&host->lock, flags); if (host->flags & SDHCI_DEVICE_DEAD) goto out; ier = readl(host->ioaddr + SDHCI_INT_ENABLE); ier &= ~SDHCI_INT_CARD_INT; Loading @@ -810,6 +821,7 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) writel(ier, host->ioaddr + SDHCI_INT_ENABLE); writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE); out: mmiowb(); spin_unlock_irqrestore(&host->lock, flags); Loading Loading @@ -875,10 +887,11 @@ static void sdhci_tasklet_finish(unsigned long param) * The controller needs a reset of internal state machines * upon error conditions. */ if (mrq->cmd->error || if (!(host->flags & SDHCI_DEVICE_DEAD) && (mrq->cmd->error || (mrq->data && (mrq->data->error || (mrq->data->stop && mrq->data->stop->error))) || (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)) { (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) { /* Some controllers need this kick or reset won't work here */ if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) { Loading Loading @@ -1378,14 +1391,33 @@ int sdhci_add_host(struct sdhci_host *host) EXPORT_SYMBOL_GPL(sdhci_add_host); void sdhci_remove_host(struct sdhci_host *host) void sdhci_remove_host(struct sdhci_host *host, int dead) { unsigned long flags; if (dead) { spin_lock_irqsave(&host->lock, flags); host->flags |= SDHCI_DEVICE_DEAD; if (host->mrq) { printk(KERN_ERR "%s: Controller removed during " " transfer!\n", mmc_hostname(host->mmc)); host->mrq->cmd->error = -ENOMEDIUM; tasklet_schedule(&host->finish_tasklet); } spin_unlock_irqrestore(&host->lock, flags); } mmc_remove_host(host->mmc); #ifdef CONFIG_LEDS_CLASS led_classdev_unregister(&host->led); #endif if (!dead) sdhci_reset(host, SDHCI_RESET_ALL); free_irq(host->irq, host); Loading
drivers/mmc/host/sdhci.h +2 −1 Original line number Diff line number Diff line Loading @@ -198,6 +198,7 @@ struct sdhci_host { int flags; /* Host attributes */ #define SDHCI_USE_DMA (1<<0) /* Host is DMA capable */ #define SDHCI_REQ_USE_DMA (1<<1) /* Use DMA for this req. */ #define SDHCI_DEVICE_DEAD (1<<2) /* Device unresponsive */ unsigned int max_clk; /* Max possible freq (MHz) */ unsigned int timeout_clk; /* Timeout freq (KHz) */ Loading Loading @@ -239,7 +240,7 @@ static inline void *sdhci_priv(struct sdhci_host *host) } extern int sdhci_add_host(struct sdhci_host *host); extern void sdhci_remove_host(struct sdhci_host *host); extern void sdhci_remove_host(struct sdhci_host *host, int dead); #ifdef CONFIG_PM extern int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state); Loading