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
This commit is contained in:
Коммит
1ff6f3dbfb
|
@ -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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
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,
|
||||||
{
|
{
|
||||||
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)
|
||||||
/*
|
/*
|
||||||
* 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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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,10 +995,20 @@ 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)
|
||||||
*/
|
*/
|
||||||
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 {
|
||||||
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 */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче