From 733cb1e44047ed88f97754fbfd5173741b6dca1a Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Fri, 10 Aug 2007 14:00:47 -0700 Subject: drivers/mmc/core/bus.c: kmalloc + memset conversion to kzalloc drivers/mmc/core/bus.c | 5663 -> 5619 (-44 bytes) drivers/mmc/core/bus.o | 70899 -> 70731 (-168 bytes) Signed-off-by: Mariusz Kozlowski Signed-off-by: Andrew Morton Signed-off-by: Pierre Ossman --- drivers/mmc/core/bus.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index fe0e785ed7d2..817a79462b3d 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -186,12 +186,10 @@ struct mmc_card *mmc_alloc_card(struct mmc_host *host) { struct mmc_card *card; - card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL); + card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL); if (!card) return ERR_PTR(-ENOMEM); - memset(card, 0, sizeof(struct mmc_card)); - card->host = host; device_initialize(&card->dev); -- cgit v1.2.3-59-g8ed1b From be760a9de881d84994403bb93177bcb95319c4cb Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Fri, 10 Aug 2007 14:00:50 -0700 Subject: drivers/mmc/core/host.c: kmalloc + memset conversion to kzalloc drivers/mmc/core/host.c | 3509 -> 3457 (-52 bytes) drivers/mmc/core/host.o | 92400 -> 92136 (-264 bytes) Signed-off-by: Mariusz Kozlowski Signed-off-by: Andrew Morton Signed-off-by: Pierre Ossman --- drivers/mmc/core/host.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 6a7e29849603..2c7ce8f43a9a 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -58,12 +58,10 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) { struct mmc_host *host; - host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); + host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); if (!host) return NULL; - memset(host, 0, sizeof(struct mmc_host) + extra); - host->parent = dev; host->class_dev.parent = dev; host->class_dev.class = &mmc_host_class; -- cgit v1.2.3-59-g8ed1b From 2b061973404802fb87db93175b856ee0dfbe38e4 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 12 Aug 2007 13:13:24 +0200 Subject: sdhci: be more cautious about block count register The block count register shouldn't be trusted for single block transfers, so avoid using it completely when calculating transferred bytes. Signed-off-by: Pierre Ossman --- drivers/mmc/host/sdhci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index f2bc87ac24f7..7181e867863e 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -477,8 +477,8 @@ static void sdhci_finish_data(struct sdhci_host *host) /* * Controller doesn't count down when in single block mode. */ - if ((data->blocks == 1) && (data->error == MMC_ERR_NONE)) - blocks = 0; + if (data->blocks == 1) + blocks = (data->error == MMC_ERR_NONE) ? 0 : 1; else blocks = readw(host->ioaddr + SDHCI_BLOCK_COUNT); data->bytes_xfered = data->blksz * (data->blocks - blocks); -- cgit v1.2.3-59-g8ed1b From 03f8590d90844f04d20488a80e75eaf4c4e0b35c Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Fri, 10 Aug 2007 13:25:03 +0100 Subject: mmc: ignore bad max block size in sdhci Some SDHC cards report an invalid maximum block size, in these cases assume they support block sizes up to 512 bytes instead of returning an error. Signed-off-by: David Vrabel Signed-off-by: Pierre Ossman --- drivers/mmc/host/sdhci.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 7181e867863e..2b327b40fa81 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1347,12 +1347,11 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) */ mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT; if (mmc->max_blk_size >= 3) { - printk(KERN_ERR "%s: Invalid maximum block size.\n", + printk(KERN_WARNING "%s: Invalid maximum block size, assuming 512\n", host->slot_descr); - ret = -ENODEV; - goto unmap; - } - mmc->max_blk_size = 512 << mmc->max_blk_size; + mmc->max_blk_size = 512; + } else + mmc->max_blk_size = 512 << mmc->max_blk_size; /* * Maximum block count. -- cgit v1.2.3-59-g8ed1b From e538fbe83e374a3521128c1f4642aca037661c9d Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 12 Aug 2007 16:46:32 +0200 Subject: sdhci: handle data interrupts during command It is fully legal for a controller to start issuing data related interrupts before it has signalled that the command has completed. Make sure the driver actually can handle this. Signed-off-by: Pierre Ossman --- drivers/mmc/host/sdhci.c | 28 +++++++++++++++++++++------- drivers/mmc/host/sdhci.h | 1 + 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 2b327b40fa81..f8fc0a98b8c4 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -385,6 +385,9 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) BUG_ON(data->blksz > host->mmc->max_blk_size); BUG_ON(data->blocks > 65535); + host->data = data; + host->data_early = 0; + /* timeout in us */ target_timeout = data->timeout_ns / 1000 + data->timeout_clks / host->clock; @@ -443,11 +446,11 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, { u16 mode; - WARN_ON(host->data); - if (data == NULL) return; + WARN_ON(!host->data); + mode = SDHCI_TRNS_BLK_CNT_EN; if (data->blocks > 1) mode |= SDHCI_TRNS_MULTI; @@ -600,9 +603,10 @@ static void sdhci_finish_command(struct sdhci_host *host) host->cmd->error = MMC_ERR_NONE; - if (host->cmd->data) - host->data = host->cmd->data; - else + if (host->data && host->data_early) + sdhci_finish_data(host); + + if (!host->cmd->data) tasklet_schedule(&host->finish_tasklet); host->cmd = NULL; @@ -991,8 +995,18 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) writel(readl(host->ioaddr + SDHCI_DMA_ADDRESS), host->ioaddr + SDHCI_DMA_ADDRESS); - if (intmask & SDHCI_INT_DATA_END) - sdhci_finish_data(host); + if (intmask & SDHCI_INT_DATA_END) { + if (host->cmd) { + /* + * Data managed to finish before the + * command completed. Make sure we do + * things in the proper order. + */ + host->data_early = 1; + } else { + sdhci_finish_data(host); + } + } } } diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index d157776c1149..e28987d6d2eb 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -182,6 +182,7 @@ struct sdhci_host { struct mmc_request *mrq; /* Current request */ struct mmc_command *cmd; /* Current command */ struct mmc_data *data; /* Current data request */ + int data_early:1; /* Data finished before cmd */ struct scatterlist *cur_sg; /* We're working on this */ int num_sg; /* Entries left */ -- cgit v1.2.3-59-g8ed1b From b67ac3f339c76dfea3cc75fc0285b6d13edc35fa Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 12 Aug 2007 17:29:47 +0200 Subject: sdhci: tell which spurious interrupt we got When we get unexpected interrupts, also print which interrupt it was. Signed-off-by: Pierre Ossman --- drivers/mmc/host/sdhci.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index f8fc0a98b8c4..20a7d89e01ba 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -933,9 +933,9 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) BUG_ON(intmask == 0); if (!host->cmd) { - printk(KERN_ERR "%s: Got command interrupt even though no " - "command operation was in progress.\n", - mmc_hostname(host->mmc)); + printk(KERN_ERR "%s: Got command interrupt 0x%08x even " + "though no command operation was in progress.\n", + mmc_hostname(host->mmc), (unsigned)intmask); sdhci_dumpregs(host); return; } @@ -965,9 +965,9 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) if (intmask & SDHCI_INT_DATA_END) return; - printk(KERN_ERR "%s: Got data interrupt even though no " - "data operation was in progress.\n", - mmc_hostname(host->mmc)); + printk(KERN_ERR "%s: Got data interrupt 0x%08x even " + "though no data operation was in progress.\n", + mmc_hostname(host->mmc), (unsigned)intmask); sdhci_dumpregs(host); return; -- cgit v1.2.3-59-g8ed1b