public inbox for linux-mmc@vger.kernel.org
 help / color / mirror / Atom feed
From: Arnd Bergmann <arnd@arndb.de>
To: linux-arm-kernel@lists.infradead.org
Cc: Shawn Guo <shawn.guo@freescale.com>,
	cjb@laptop.org, s.hauer@pengutronix.de,
	u.kleine-koenig@pengutronix.de, linux-mmc@vger.kernel.org
Subject: Re: [PATCH 1/7] mmc: mxs-mmc: add mmc host driver for i.MX23/28
Date: Fri, 4 Feb 2011 21:26:52 +0100	[thread overview]
Message-ID: <201102042126.52701.arnd@arndb.de> (raw)
In-Reply-To: <1296872327-21166-2-git-send-email-shawn.guo@freescale.com>

On Saturday 05 February 2011 03:18:41 Shawn Guo wrote:
> This adds the mmc host driver for Freescale MXS-based SoC i.MX23/28.
> The driver calls into mxs-dma via generic dmaengine api for both pio
> and data transfer.

Hi Shawn,

The driver looks good coding-style wise, but it's my impression that
you do some thing less efficient or more complex than necessary. To
be more specific:

> +struct mxs_mmc_host {

It seems you have a number of members in this struct that only
add confusion but are not actually needed, so just get rid of
them:

> +	struct device			*dev;

mmc_host->parent ?

> +	struct resource			*res;
> +	struct resource			*dma_res;
> +	struct clk			*clk;

are visible in the parent.

> +	unsigned int			version;

unused

> +	struct mmc_command		*cmd;

mrq->cmd ?

> +	struct mmc_data			*data;

unused

> +	unsigned			present:1;

Your card detection by polling through this variable is
really bad for power management. Is there really no interrupt
that gets triggered when installing or removing a card?

Also, please try to avoid bit fields. 'bool' variables are
fine for flags.

> +	unsigned int			dma_dir;

not needed, a local variable would be just fine.

> +	struct mxs_dma_data		dma_data;

Why do you need host specific DMA structures? Please stick to
the generic dma-engine API if possible.

> +	struct completion 		done;

The mmc layer already comes with a generic completion that you
can and should use, mainly for performance reasons. Adding your
own completion forces every single request to go through an
additional context switch, compared to just returning from
the request function when you have scheduled the command, and
calling mmc_request_done from the interrupt handler.

> +	u32				status;

Won't be needed any more when you complete the requests at
interrupt time.

> +#define SSP_PIO_NUM	3
> +static u32 ssp_pio_words[SSP_PIO_NUM];

I don't think this is safe: This is a global variable, so if you have
multiple controllers, they would access the same data. Why not integrate
it into the host data structure?

> +
> +static void mxs_mmc_reset(struct mxs_mmc_host *host)
> +{
> +	u32 ctrl0, ctrl1;
> +
> +	mxs_reset_block(host->base);
> +
> +	ctrl0 = BM_SSP_CTRL0_IGNORE_CRC;
> +	ctrl1 = BF_SSP(0x3, SSP_CTRL1_SSP_MODE) |
> +		BF_SSP(0x7, SSP_CTRL1_WORD_LENGTH) |
> +		BM_SSP_CTRL1_DMA_ENABLE |
> +		BM_SSP_CTRL1_POLARITY |
> +		BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN |
> +		BM_SSP_CTRL1_DATA_CRC_IRQ_EN |
> +		BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN |
> +		BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN |
> +		BM_SSP_CTRL1_RESP_ERR_IRQ_EN;
> +
> +	__raw_writel(BF_SSP(0xffff, SSP_TIMING_TIMEOUT) |
> +		     BF_SSP(2, SSP_TIMING_CLOCK_DIVIDE) |
> +		     BF_SSP(0, SSP_TIMING_CLOCK_RATE),
> +		     host->base + HW_SSP_TIMING);

Please use proper MMIO accessors like writel() and readl() that
are known to be safe here. The __raw_ variants are not really
meant for device drivers, which can lead to very subtle bugs.

> +static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id)
> +{
> +	struct mxs_mmc_host *host = dev_id;
> +	u32 stat;
> +
> +	stat = __raw_readl(host->base + HW_SSP_CTRL1);
> +	__mxs_clrl(stat & MXS_MMC_IRQ_BITS, host->base + HW_SSP_CTRL1);
> +
> +	if (host->cmd && (stat & MXS_MMC_ERR_BITS))
> +		host->status = __raw_readl(host->base + HW_SSP_STATUS);
> +
> +	if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN))
> +		mmc_signal_sdio_irq(host->mmc);
> +
> +	return IRQ_HANDLED;
> +}

You use spin_lock_irqsave in mxs_mmc_enable_sdio_irq, but don't
actually use the spinlock in the interrupt handler. This means
that either your interrupt handler is broken because it doesn't
lock, or that you don't actually need the _irqsave part.

> +static void mxs_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
> +{
> +	struct mxs_mmc_host *host = mmc_priv(mmc);
> +
> +	BUG_ON(host->mrq != NULL);
> +
> +	host->mrq = mrq;
> +	mxs_mmc_start_cmd(host, mrq->cmd);
> +
> +	if (mrq->data && mrq->data->stop) {
> +		dev_dbg(host->dev, "Stop opcode is %u\n",
> +				mrq->data->stop->opcode);
> +		mxs_mmc_start_cmd(host, mrq->data->stop);
> +	}
> +
> +	host->mrq = NULL;
> +	mmc_request_done(mmc, mrq);
> +}

As mentioned above, the mmc_request_done() shouldn't really be needed here,
it's more efficient to do it in the interrupt handler.

	Arnd

  reply	other threads:[~2011-02-04 20:27 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-02-05  2:18 [PATCH 0/7] Add mmc driver for i.MX23/28 Shawn Guo
2011-02-05  2:18 ` [PATCH 1/7] mmc: mxs-mmc: add mmc host " Shawn Guo
2011-02-04 20:26   ` Arnd Bergmann [this message]
2011-02-11  0:35     ` Shawn Guo
2011-02-10 17:17       ` Arnd Bergmann
2011-02-11 23:14         ` Shawn Guo
2011-02-11 15:51           ` Arnd Bergmann
2011-02-12  0:55             ` Shawn Guo
2011-02-11 20:04               ` Arnd Bergmann
2011-02-12 14:04                 ` Shawn Guo
2011-02-12  8:59                   ` Arnd Bergmann
2011-02-12 17:23                     ` Shawn Guo
2011-02-12 10:07                       ` Arnd Bergmann
2011-02-12 18:37                         ` Shawn Guo
2011-02-12 17:30                           ` Arnd Bergmann
2011-02-13 17:53       ` Shawn Guo
2011-02-13 15:34         ` Arnd Bergmann
2011-02-13 23:52           ` Shawn Guo
2011-02-13 16:10             ` Arnd Bergmann
2011-02-08 11:41   ` Lothar Waßmann
2011-02-11 22:11     ` Shawn Guo
2011-02-11 14:40       ` Lothar Waßmann
2011-02-12  1:08         ` Shawn Guo
2011-02-09  7:46   ` Lothar Waßmann
2011-02-11 22:08     ` Shawn Guo
2011-02-11 14:52       ` Lothar Waßmann
2011-02-11 23:48         ` Shawn Guo
2011-02-05  2:18 ` [PATCH 2/7] ARM: mxs/clock: fix base address missing in name##_set_parent Shawn Guo
2011-02-05  2:18 ` [PATCH 3/7] ARM: mxs: make ssp error irq definition consistent Shawn Guo
2011-02-05  2:18 ` [PATCH 4/7] ARM: mxs: dynamically allocate mmc device Shawn Guo
2011-02-05  2:18 ` [PATCH 5/7] ARM: mxs: fix typo "GPO" in iomux-mx23.h Shawn Guo
2011-02-05  2:18 ` [PATCH 6/7] ARM: mxs/mx23evk: add mmc device Shawn Guo
2011-02-05  2:18 ` [PATCH 7/7] ARM: mxs/mx28evk: " Shawn Guo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=201102042126.52701.arnd@arndb.de \
    --to=arnd@arndb.de \
    --cc=cjb@laptop.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=s.hauer@pengutronix.de \
    --cc=shawn.guo@freescale.com \
    --cc=u.kleine-koenig@pengutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox