提交 1ff6f3db 编写于 作者: L Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc:
  sdhci: tell which spurious interrupt we got
  sdhci: handle data interrupts during command
  mmc: ignore bad max block size in sdhci
  sdhci: be more cautious about block count register
  drivers/mmc/core/host.c: kmalloc + memset conversion to kzalloc
  drivers/mmc/core/bus.c: kmalloc + memset conversion to kzalloc
...@@ -186,12 +186,10 @@ struct mmc_card *mmc_alloc_card(struct mmc_host *host) ...@@ -186,12 +186,10 @@ struct mmc_card *mmc_alloc_card(struct mmc_host *host)
{ {
struct mmc_card *card; struct mmc_card *card;
card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL); card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL);
if (!card) if (!card)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
memset(card, 0, sizeof(struct mmc_card));
card->host = host; card->host = host;
device_initialize(&card->dev); device_initialize(&card->dev);
......
...@@ -58,12 +58,10 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) ...@@ -58,12 +58,10 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
{ {
struct mmc_host *host; struct mmc_host *host;
host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
if (!host) if (!host)
return NULL; return NULL;
memset(host, 0, sizeof(struct mmc_host) + extra);
host->parent = dev; host->parent = dev;
host->class_dev.parent = dev; host->class_dev.parent = dev;
host->class_dev.class = &mmc_host_class; host->class_dev.class = &mmc_host_class;
......
...@@ -385,6 +385,9 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) ...@@ -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->blksz > host->mmc->max_blk_size);
BUG_ON(data->blocks > 65535); BUG_ON(data->blocks > 65535);
host->data = data;
host->data_early = 0;
/* timeout in us */ /* timeout in us */
target_timeout = data->timeout_ns / 1000 + target_timeout = data->timeout_ns / 1000 +
data->timeout_clks / host->clock; data->timeout_clks / host->clock;
...@@ -443,11 +446,11 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, ...@@ -443,11 +446,11 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,
{ {
u16 mode; u16 mode;
WARN_ON(host->data);
if (data == NULL) if (data == NULL)
return; return;
WARN_ON(!host->data);
mode = SDHCI_TRNS_BLK_CNT_EN; mode = SDHCI_TRNS_BLK_CNT_EN;
if (data->blocks > 1) if (data->blocks > 1)
mode |= SDHCI_TRNS_MULTI; mode |= SDHCI_TRNS_MULTI;
...@@ -477,8 +480,8 @@ static void sdhci_finish_data(struct sdhci_host *host) ...@@ -477,8 +480,8 @@ static void sdhci_finish_data(struct sdhci_host *host)
/* /*
* Controller doesn't count down when in single block mode. * Controller doesn't count down when in single block mode.
*/ */
if ((data->blocks == 1) && (data->error == MMC_ERR_NONE)) if (data->blocks == 1)
blocks = 0; blocks = (data->error == MMC_ERR_NONE) ? 0 : 1;
else else
blocks = readw(host->ioaddr + SDHCI_BLOCK_COUNT); blocks = readw(host->ioaddr + SDHCI_BLOCK_COUNT);
data->bytes_xfered = data->blksz * (data->blocks - blocks); data->bytes_xfered = data->blksz * (data->blocks - blocks);
...@@ -600,9 +603,10 @@ static void sdhci_finish_command(struct sdhci_host *host) ...@@ -600,9 +603,10 @@ static void sdhci_finish_command(struct sdhci_host *host)
host->cmd->error = MMC_ERR_NONE; host->cmd->error = MMC_ERR_NONE;
if (host->cmd->data) if (host->data && host->data_early)
host->data = host->cmd->data; sdhci_finish_data(host);
else
if (!host->cmd->data)
tasklet_schedule(&host->finish_tasklet); tasklet_schedule(&host->finish_tasklet);
host->cmd = NULL; host->cmd = NULL;
...@@ -929,9 +933,9 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) ...@@ -929,9 +933,9 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
BUG_ON(intmask == 0); BUG_ON(intmask == 0);
if (!host->cmd) { if (!host->cmd) {
printk(KERN_ERR "%s: Got command interrupt even though no " printk(KERN_ERR "%s: Got command interrupt 0x%08x even "
"command operation was in progress.\n", "though no command operation was in progress.\n",
mmc_hostname(host->mmc)); mmc_hostname(host->mmc), (unsigned)intmask);
sdhci_dumpregs(host); sdhci_dumpregs(host);
return; return;
} }
...@@ -961,9 +965,9 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) ...@@ -961,9 +965,9 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
if (intmask & SDHCI_INT_DATA_END) if (intmask & SDHCI_INT_DATA_END)
return; return;
printk(KERN_ERR "%s: Got data interrupt even though no " printk(KERN_ERR "%s: Got data interrupt 0x%08x even "
"data operation was in progress.\n", "though no data operation was in progress.\n",
mmc_hostname(host->mmc)); mmc_hostname(host->mmc), (unsigned)intmask);
sdhci_dumpregs(host); sdhci_dumpregs(host);
return; return;
...@@ -991,9 +995,19 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) ...@@ -991,9 +995,19 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
writel(readl(host->ioaddr + SDHCI_DMA_ADDRESS), writel(readl(host->ioaddr + SDHCI_DMA_ADDRESS),
host->ioaddr + SDHCI_DMA_ADDRESS); host->ioaddr + SDHCI_DMA_ADDRESS);
if (intmask & SDHCI_INT_DATA_END) 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); sdhci_finish_data(host);
} }
}
}
} }
static irqreturn_t sdhci_irq(int irq, void *dev_id) static irqreturn_t sdhci_irq(int irq, void *dev_id)
...@@ -1347,11 +1361,10 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) ...@@ -1347,11 +1361,10 @@ 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; mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
if (mmc->max_blk_size >= 3) { 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); host->slot_descr);
ret = -ENODEV; mmc->max_blk_size = 512;
goto unmap; } else
}
mmc->max_blk_size = 512 << mmc->max_blk_size; mmc->max_blk_size = 512 << mmc->max_blk_size;
/* /*
......
...@@ -182,6 +182,7 @@ struct sdhci_host { ...@@ -182,6 +182,7 @@ struct sdhci_host {
struct mmc_request *mrq; /* Current request */ struct mmc_request *mrq; /* Current request */
struct mmc_command *cmd; /* Current command */ struct mmc_command *cmd; /* Current command */
struct mmc_data *data; /* Current data request */ struct mmc_data *data; /* Current data request */
int data_early:1; /* Data finished before cmd */
struct scatterlist *cur_sg; /* We're working on this */ struct scatterlist *cur_sg; /* We're working on this */
int num_sg; /* Entries left */ int num_sg; /* Entries left */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册