All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Morton <akpm@linux-foundation.org>
To: "Wolfgang Mües" <wolfgang.mues@auerswald.de>
Cc: dbrownell@users.sourceforge.net, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] Fixes and enhancements for the MMC SPI driver
Date: Mon, 12 Jan 2009 15:45:48 -0800	[thread overview]
Message-ID: <20090112154548.f29d57dd.akpm@linux-foundation.org> (raw)
In-Reply-To: <200901061517.01872.wolfgang.mues@auerswald.de>

On Tue, 6 Jan 2009 15:17:01 +0100
Wolfgang M__es <wolfgang.mues@auerswald.de> wrote:

> David,
> 
> I have done some fixes and enhancements to the MMC SPI host controller driver.
> Practical results with SD/SDHC cards from different vendors are much better now. 
> The patch is for kernel 2.6.28.
> 
> (I do not read the linux kernel mailing list)

Please reissue this patch with a *full* changelog.  One which actually
describes these fixes and enhancements.  For fixes, fully decribe the
problem which was fixed.  For each enhancement, describe why that
enhancement is desirable/useful, if that is not obvious.

Before sending, please pass the patch through scripts/checkpatch.pl. 
This one adds various whitespace gremlins which you probably wouldn't
have sent, had you known they were there.

> 
> ============= snip ====================
> --- 2.6.28/drivers/mmc/host/mmc_spi.c	2008-11-24 10:26:06.000000000 +0100
> +++ new/drivers/mmc/host/mmc_spi.c	2009-01-06 14:52:59.000000000 +0100
> @@ -25,6 +25,7 @@
>   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
>   */
>  #include <linux/hrtimer.h>
> +#include <linux/sched.h>
>  #include <linux/delay.h>
>  #include <linux/bio.h>
>  #include <linux/dma-mapping.h>
> @@ -186,10 +187,10 @@
>  static int
>  mmc_spi_skip(struct mmc_spi_host *host, ktime_t timeout, unsigned n, u8 byte)
>  {
> -	u8		*cp = host->data->status;
> -
> -	timeout = ktime_add(timeout, ktime_get());
> -
> +	u8 *cp = host->data->status;
> +	unsigned long timeout_jiffies = (unsigned long) ((ktime_to_us(timeout) * HZ) / 1000000);

ktime_to_us() returns s64.  Dividing that by 1000000 introduces the
risk that the compiler will try to generate a 64-bit divide, which will
fail to link on x86_32.  Fixable by converting to unsigned long before
dividing, or via do_div().

layout: we don't *have* to do complex 100-column initialisations at the
definition site.  it's perfectly OK and often better to do:

	unsigned long timeout_jiffies;
	...
	timeout_jiffies = ...;

Please use USECS_PER_SEC for clarity, if appropriate.

> +	unsigned long starttime = jiffies;
> + 
>  	while (1) {
>  		int		status;
>  		unsigned	i;
> @@ -203,11 +204,13 @@
>  				return cp[i];
>  		}
>  
> -		/* REVISIT investigate msleep() to avoid busy-wait I/O
> -		 * in at least some cases.
> -		 */
> -		if (ktime_to_ns(ktime_sub(ktime_get(), timeout)) > 0)
> +		if ((jiffies - starttime) > timeout_jiffies)

time_after/time_before/etc would be preferred.

>  			break;
> +		/* If we need long timeouts, we may release the CPU. */
> +		/* We use jiffies here because we want to have a relation between
> +                   elapsed time and the blocking of the scheduler. */
> +		if ((jiffies - starttime) > 1)

time_after()...

> +			schedule();

does this actually do anything useful?  Presumably the
mmc_spi_readbytes() will block (unless SPI can to 10GB/sec), so I
wouldn't expect this schedule() to help anything.

If it _does_ help then we have bigger problems - if nothing esle is
runnable, we'll burn power like mad and a cpu_relax() might be needed.

>  	}
>  	return -ETIMEDOUT;
>  }
> @@ -280,7 +283,9 @@
>  		 * It'd probably be better to memcpy() the first chunk and
>  		 * avoid extra i/o calls...
>  		 */
> -		for (i = 2; i < 9; i++) {
> +		/* Note we check for more than 8 bytes, because in practice,
> +		   some SD cards are slow... */
> +		for (i = 2; i < 16; i++) {
>  			value = mmc_spi_readbytes(host, 1);
>  			if (value < 0)
>  				goto done;
> @@ -609,6 +614,15 @@
>  	struct spi_device	*spi = host->spi;
>  	int			status, i;
>  	struct scratch		*scratch = host->data;
> +	u32			pattern;
> +
> +	/* The MMC framework does a good job of computing timeouts
> +           according to the mmc/sd standard. However, we found that in
> +           SPI mode, there are many cards which need a longer timeout
> +           of 1s after receiving a long stream of write data. */
> +	struct timeval tv = ktime_to_timeval(timeout);

layout: Putting a big hole in the local definitions like this is
inviting someone else to later put some code statments *before* this
definition.  Then some other people will get compilation warnings. 
This would be better:

	u32			pattern;
	struct timeval tv;

	/* The MMC framework does a good job of computing timeouts
           according to the mmc/sd standard. However, we found that in
           SPI mode, there are many cards which need a longer timeout
           of 1s after receiving a long stream of write data. */
	tv = ktime_to_timeval(timeout);

Please format comments in the standard way:

	/*
	 * The MMC framework does a good job of computing timeouts
	 * according to the mmc/sd standard. However, we found that in
	 * SPI mode, there are many cards which need a longer timeout
	 * of 1s after receiving a long stream of write data.
	 */

and indent them with tabs, not spacespacespacespacespace.

> +	if (tv.tv_sec == 0)
> +		timeout = ktime_set(1,0);	
>  
>  	if (host->mmc->use_spi_crc)
>  		scratch->crc_val = cpu_to_be16(
> @@ -636,8 +650,23 @@
>  	 * doesn't necessarily tell whether the write operation succeeded;
>  	 * it just says if the transmission was ok and whether *earlier*
>  	 * writes succeeded; see the standard.
> -	 */
> -	switch (SPI_MMC_RESPONSE_CODE(scratch->status[0])) {
> +	 *
> +	 * In practice, there are (even modern SDHC-)Cards which need
> +	 * some bits to send the response, so we have to cope with this
> +	 * situation and check the response bit-by-bit. Arggh!!!
> +	 */
> +	pattern  = scratch->status[0] << 24;
> +	pattern |= scratch->status[1] << 16;
> +	pattern |= scratch->status[2] << 8;
> +	pattern |= scratch->status[3];
> +
> +	/* left-adjust to leading 0 bit */
> +	while (pattern & 0x80000000)
> +		pattern <<= 1;
> +	/* right-adjust for pattern matching. Code is in bit 4..0 now. */
> +	pattern >>= 27;

hm, wow, that looks like sad hardware.

> +	switch (pattern) {
>  	case SPI_RESPONSE_ACCEPTED:
>  		status = 0;
>  		break;
> @@ -668,9 +697,9 @@
>  	/* Return when not busy.  If we didn't collect that status yet,
>  	 * we'll need some more I/O.
>  	 */
> -	for (i = 1; i < sizeof(scratch->status); i++) {
> -		if (scratch->status[i] != 0)
> -			return 0;
> +	for (i = 4; i < sizeof(scratch->status); i++) {
> +		if (scratch->status[i] & 0x01)
> + 			return 0;
>  	}
>  	return mmc_spi_wait_unbusy(host, timeout);
>  }
> @@ -743,7 +772,11 @@
>  		return -EIO;
>  	}
>  
> -	if (host->mmc->use_spi_crc) {
> +	/* Omitt the CRC check for CID and CSD reads. There are some SDHC
> +	   cards which don't supply a valid CRC after CID reads.
> +	   Note that the CID has it's own CRC7 value inside the data block.
> +	*/

spelling: "Omit".

layout.

> +	if (host->mmc->use_spi_crc && (t->len == MMC_SPI_BLOCKSIZE)) {
>  		u16 crc = crc_itu_t(0, t->rx_buf, t->len);
>  
>  		be16_to_cpus(&scratch->crc_val);
> @@ -1206,8 +1239,15 @@
>  	 * rising edge ... meaning SPI modes 0 or 3.  So either SPI mode
>  	 * should be legit.  We'll use mode 0 since it seems to be a
>  	 * bit less troublesome on some hardware ... unclear why.
> -	 */
> -	spi->mode = SPI_MODE_0;
> +	 *
> +	 * If the platform_data specifies mode 3, trust the platform_data
> +	 * and use this one. This allows for platforms which do not support
> +	 * mode 0.
> +	 */
> +	if (spi->mode != SPI_MODE_3)
> +		/* set our default */
> +		spi->mode = SPI_MODE_0;
> +
>  	spi->bits_per_word = 8;
>  
>  	status = spi_setup(spi);


      parent reply	other threads:[~2009-01-12 23:46 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-01-06 14:17 [PATCH] Fixes and enhancements for the MMC SPI driver Wolfgang Mües
2009-01-06 16:10 ` Matt Fleming
2009-01-08  8:22   ` Wolfgang Mües
2009-01-08  9:24     ` Matt Fleming
2009-01-08 10:19       ` Wolfgang Mües
2009-01-12 10:50       ` Wolfgang Mües
2009-01-24 12:23         ` Pierre Ossman
2009-01-12 23:45 ` Andrew Morton [this message]

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=20090112154548.f29d57dd.akpm@linux-foundation.org \
    --to=akpm@linux-foundation.org \
    --cc=dbrownell@users.sourceforge.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=wolfgang.mues@auerswald.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.