Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ff6f3db authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
parents 2b56fec6 b67ac3f3
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -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);
+1 −3
Original line number Diff line number Diff line
@@ -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;
+33 −20
Original line number Diff line number Diff line
@@ -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;
@@ -477,8 +480,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);
@@ -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;
@@ -929,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;
	}
@@ -961,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;
@@ -991,10 +995,20 @@ 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)
		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);
			}
		}
	}
}

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;
	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;
	} else
		mmc->max_blk_size = 512 << mmc->max_blk_size;

	/*
+1 −0
Original line number Diff line number Diff line
@@ -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 */