Re: [PATCH 2/2] [MMC] Secure Digital Host Controller Interface driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Patch with your suggested improvements.

Rgds
Pierre


From: Pierre Ossman <[email protected]>


---

 drivers/mmc/sdhci.c |   53 ++++++++++++++++++++++++++++++++++++---------------
 drivers/mmc/sdhci.h |   12 +++++++++---
 2 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 4e12fe0..667928d 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -204,6 +204,9 @@ static void sdhci_transfer_pio(struct sd
 				"Please report this to "
 				BUGMAIL ".\n", mmc_hostname(host->mmc));
 			sdhci_dumpregs(host);
+
+			sdhci_kunmap_sg(host);
+
 			host->data->error = MMC_ERR_FAILED;
 			sdhci_finish_data(host);
 			return;
@@ -578,8 +581,12 @@ static void sdhci_set_ios(struct mmc_hos
 	 * Reset the chip on each power off.
 	 * Should clear out any weird states.
 	 */
-	if (ios->power_mode == MMC_POWER_OFF)
+	if (ios->power_mode == MMC_POWER_OFF) {
+		writel(0, host->ioaddr + SDHCI_SIGNAL_ENABLE);
+		spin_unlock_irqrestore(&host->lock, flags);
 		sdhci_init(host);
+		spin_lock_irqsave(&host->lock, flags);
+	}
 
 	sdhci_set_clock(host, ios->clock);
 
@@ -970,6 +977,21 @@ static int __devinit sdhci_probe_slot(st
 
 	first_bar &= PCI_SLOT_INFO_FIRST_BAR_MASK;
 
+	if (first_bar > 5) {
+		printk(KERN_ERR DRIVER_NAME ": Invalid first BAR. Aborting.\n");
+		return -ENODEV;
+	}
+
+	if (!(pci_resource_flags(pdev, first_bar + slot) & IORESOURCE_MEM)) {
+		printk(KERN_ERR DRIVER_NAME ": BAR is not iomem. Aborting.\n");
+		return -ENODEV;
+	}
+
+	if (pci_resource_len(pdev, first_bar + slot) != 0x100) {
+		printk(KERN_ERR DRIVER_NAME ": Invalid iomem size. Aborting.\n");
+		return -ENODEV;
+	}
+
 	mmc = mmc_alloc_host(sizeof(struct sdhci_host), &pdev->dev);
 	if (!mmc)
 		return -ENOMEM;
@@ -984,8 +1006,6 @@ static int __devinit sdhci_probe_slot(st
 
 	DBG("slot %d at 0x%08lx, irq %d\n", slot, host->addr, host->irq);
 
-	BUG_ON(!(pci_resource_flags(pdev, first_bar + slot) & IORESOURCE_MEM));
-
 	snprintf(host->slot_descr, 20, "sdhci:slot%d", slot);
 
 	ret = pci_request_region(pdev, host->bar, host->slot_descr);
@@ -999,11 +1019,6 @@ static int __devinit sdhci_probe_slot(st
 		goto release;
 	}
 
-	ret = request_irq(host->irq, sdhci_irq, SA_SHIRQ,
-		host->slot_descr, host);
-	if (ret)
-		goto unmap;
-
 	caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
 
 	if ((caps & SDHCI_CAN_DO_DMA) && ((pdev->class & 0x0000FF) == 0x01))
@@ -1065,9 +1080,12 @@ static int __devinit sdhci_probe_slot(st
 	tasklet_init(&host->finish_tasklet,
 		sdhci_tasklet_finish, (unsigned long)host);
 
-	init_timer(&host->timer);
-	host->timer.data = (unsigned long)host;
-	host->timer.function = sdhci_timeout_timer;
+	setup_timer(&host->timer, sdhci_timeout_timer, (int)host);
+
+	ret = request_irq(host->irq, sdhci_irq, SA_SHIRQ,
+		host->slot_descr, host);
+	if (ret)
+		goto unmap;
 
 	sdhci_init(host);
 
@@ -1087,6 +1105,9 @@ static int __devinit sdhci_probe_slot(st
 	return 0;
 
 unmap:
+	tasklet_kill(&host->card_tasklet);
+	tasklet_kill(&host->finish_tasklet);
+
 	iounmap(host->ioaddr);
 release:
 	pci_release_region(pdev, host->bar);
@@ -1110,10 +1131,12 @@ static void sdhci_remove_slot(struct pci
 
 	mmc_remove_host(mmc);
 
-	del_timer_sync(&host->timer);
-
 	sdhci_reset(host, SDHCI_RESET_ALL);
 
+	free_irq(host->irq, host);
+
+	del_timer_sync(&host->timer);
+
 	tasklet_kill(&host->card_tasklet);
 	tasklet_kill(&host->finish_tasklet);
 
@@ -1121,8 +1144,6 @@ static void sdhci_remove_slot(struct pci
 
 	pci_release_region(pdev, host->bar);
 
-	free_irq(host->irq, host);
-
 	mmc_free_host(mmc);
 }
 
@@ -1152,7 +1173,7 @@ static int __devinit sdhci_probe(struct 
 		return ret;
 
 	chip = kzalloc(sizeof(struct sdhci_chip) +
-		sizeof(sdhci_host_p) * slots, GFP_KERNEL);
+		sizeof(struct sdhci_host*) * slots, GFP_KERNEL);
 	if (!chip) {
 		ret = -ENOMEM;
 		goto err;
diff --git a/drivers/mmc/sdhci.h b/drivers/mmc/sdhci.h
index 286d4d1..3b270ef 100644
--- a/drivers/mmc/sdhci.h
+++ b/drivers/mmc/sdhci.h
@@ -9,6 +9,14 @@
  */
 
 /*
+ * PCI registers
+ */
+
+#define PCI_SLOT_INFO			0x40	/* 8 bits */
+#define  PCI_SLOT_INFO_SLOTS(x)		((x >> 4) & 7)
+#define  PCI_SLOT_INFO_FIRST_BAR_MASK	0x07
+
+/*
  * Controller registers
  */
 
@@ -169,11 +177,9 @@ struct sdhci_host {
 	struct timer_list	timer;		/* Timer for timeouts */
 };
 
-typedef struct sdhci_host *sdhci_host_p;
-
 struct sdhci_chip {
 	struct pci_dev		*pdev;
 
 	int			num_slots;	/* Slots on controller */
-	sdhci_host_p		hosts[0];	/* Pointers to hosts */
+	struct sdhci_host	*hosts[0];	/* Pointers to hosts */
 };

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux