diff mbox

[7/32] mmc: add host capabilities for SD only and MMC only

Message ID 20090710124054.1262.18902.sendpatchset@ahunter-tower (mailing list archive)
State Awaiting Upstream, archived
Headers show

Commit Message

Adrian Hunter July 10, 2009, 12:40 p.m. UTC
From 27ed1443884c0e46855485cfc2190e1d80a0f568 Mon Sep 17 00:00:00 2001
From: Adrian Hunter <adrian.hunter@nokia.com>
Date: Tue, 7 Jul 2009 12:20:48 +0300
Subject: [PATCH] mmc: add host capabilities for SD only and MMC only

Some hosts can accept only certain types of cards.
For example, an eMMC is MMC only and a uSD slot may
be SD only.  However the MMC card scanning logic
checks for all card types one by one.

Add host capabilities to specify which card types
cannot be used, and amend the card scanning logic
to skip scanning for those types.

Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/core/core.c  |   16 +++++++++++++++-
 include/linux/mmc/host.h |    7 +++++++
 2 files changed, 22 insertions(+), 1 deletions(-)

Comments

Matt Fleming July 25, 2009, 3:53 p.m. UTC | #1
On Fri, Jul 10, 2009 at 03:40:54PM +0300, Adrian Hunter wrote:
> 
> Some hosts can accept only certain types of cards.
> For example, an eMMC is MMC only and a uSD slot may
> be SD only.  However the MMC card scanning logic
> checks for all card types one by one.
> 
> Add host capabilities to specify which card types
> cannot be used, and amend the card scanning logic
> to skip scanning for those types.
> 

I'm only nitpicking here, but I think that logic is a little inverted.
By saying which cards cannot be used (as opposed to which cards can be
used), we get conditionals like this,

>  
> -	mmc_send_if_cond(host, host->ocr_avail);
> +	if (!(host->caps & MMC_CAP_NOT_SDIO) || !(host->caps & MMC_CAP_NOT_SD))
> +		mmc_send_if_cond(host, host->ocr_avail);
> +

Whilst reviewing this patch it took my brain a few too many seconds to
parse that as "if the host is capable of SDIO or SD".


> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> index 0a60b02..e996967 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -150,6 +150,13 @@ struct mmc_host {
>  #define MMC_CAP_DISABLE		(1 << 7)	/* Can the host be disabled */
>  #define MMC_CAP_NONREMOVABLE	(1 << 8)	/* Nonremovable e.g. eMMC */
>  #define MMC_CAP_WAIT_WHILE_BUSY	(1 << 9)	/* Waits while card is busy */
> +#define MMC_CAP_NOT_SDIO	(1 << 10)	/* Card cannot be SDIO */
> +#define MMC_CAP_NOT_SD		(1 << 11)	/* Card cannot be SD */
> +#define MMC_CAP_NOT_MMC		(1 << 12)	/* Card cannot be MMC */
> +
> +#define MMC_CAP_SDIO_ONLY	(MMC_CAP_NOT_SD | MMC_CAP_NOT_MMC)
> +#define MMC_CAP_SD_ONLY		(MMC_CAP_NOT_SDIO | MMC_CAP_NOT_MMC)
> +#define MMC_CAP_MMC_ONLY	(MMC_CAP_NOT_SDIO | MMC_CAP_NOT_SD)
>  

And by saying what capabilities a host supports, when we add new
capabilities we don't have to modify existing code to say that it
doesn't support the new capability.
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Adrian Hunter July 25, 2009, 4:17 p.m. UTC | #2
Matt Fleming wrote:
> On Fri, Jul 10, 2009 at 03:40:54PM +0300, Adrian Hunter wrote:
>> Some hosts can accept only certain types of cards.
>> For example, an eMMC is MMC only and a uSD slot may
>> be SD only.  However the MMC card scanning logic
>> checks for all card types one by one.
>>
>> Add host capabilities to specify which card types
>> cannot be used, and amend the card scanning logic
>> to skip scanning for those types.
>>
> 
> I'm only nitpicking here, but I think that logic is a little inverted.
> By saying which cards cannot be used (as opposed to which cards can be
> used), we get conditionals like this,
> 
>>  
>> -	mmc_send_if_cond(host, host->ocr_avail);
>> +	if (!(host->caps & MMC_CAP_NOT_SDIO) || !(host->caps & MMC_CAP_NOT_SD))
>> +		mmc_send_if_cond(host, host->ocr_avail);
>> +
> 
> Whilst reviewing this patch it took my brain a few too many seconds to
> parse that as "if the host is capable of SDIO or SD".
> 
> 
>> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
>> index 0a60b02..e996967 100644
>> --- a/include/linux/mmc/host.h
>> +++ b/include/linux/mmc/host.h
>> @@ -150,6 +150,13 @@ struct mmc_host {
>>  #define MMC_CAP_DISABLE		(1 << 7)	/* Can the host be disabled */
>>  #define MMC_CAP_NONREMOVABLE	(1 << 8)	/* Nonremovable e.g. eMMC */
>>  #define MMC_CAP_WAIT_WHILE_BUSY	(1 << 9)	/* Waits while card is busy */
>> +#define MMC_CAP_NOT_SDIO	(1 << 10)	/* Card cannot be SDIO */
>> +#define MMC_CAP_NOT_SD		(1 << 11)	/* Card cannot be SD */
>> +#define MMC_CAP_NOT_MMC		(1 << 12)	/* Card cannot be MMC */
>> +
>> +#define MMC_CAP_SDIO_ONLY	(MMC_CAP_NOT_SD | MMC_CAP_NOT_MMC)
>> +#define MMC_CAP_SD_ONLY		(MMC_CAP_NOT_SDIO | MMC_CAP_NOT_MMC)
>> +#define MMC_CAP_MMC_ONLY	(MMC_CAP_NOT_SDIO | MMC_CAP_NOT_SD)
>>  
> 
> And by saying what capabilities a host supports, when we add new
> capabilities we don't have to modify existing code to say that it
> doesn't support the new capability.

If the capabilities are the other way around, then all existing drivers
must be changed.  On the other hand, the if statement can easily be
improved:

#define mmc_cap_mmc(host) (!((host)->caps & MMC_CAP_NOT_MMC))
#define mmc_cap_sd(host) (!((host)->caps & MMC_CAP_NOT_SD))
#define mmc_cap_sdio(host) (!((host)->caps & MMC_CAP_NOT_SDIO))

-	mmc_send_if_cond(host, host->ocr_avail);
+	if (mmc_cap_sdio(host) || mmc_cap_sd(host))
+		mmc_send_if_cond(host, host->ocr_avail);
+
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Matt Fleming July 25, 2009, 6:40 p.m. UTC | #3
On Sat, Jul 25, 2009 at 07:17:14PM +0300, Adrian Hunter wrote:
> Matt Fleming wrote:
>>
>> And by saying what capabilities a host supports, when we add new
>> capabilities we don't have to modify existing code to say that it
>> doesn't support the new capability.
>
> If the capabilities are the other way around, then all existing drivers
> must be changed.  On the other hand, the if statement can easily be
> improved:
>
> #define mmc_cap_mmc(host) (!((host)->caps & MMC_CAP_NOT_MMC))
> #define mmc_cap_sd(host) (!((host)->caps & MMC_CAP_NOT_SD))
> #define mmc_cap_sdio(host) (!((host)->caps & MMC_CAP_NOT_SDIO))
>
> -	mmc_send_if_cond(host, host->ocr_avail);
> +	if (mmc_cap_sdio(host) || mmc_cap_sd(host))
> +		mmc_send_if_cond(host, host->ocr_avail);
> +

OK, that's a fair point, all drivers would need to be changed. However,
I'm not adverse to making a one-time change to all drivers in the name
of sanity. Enumerating what cards a controller doesn't support just
doesn't sound correct to me.

It wouldn't be a complicated change either, I'd even be happy to write
the patch ;-)
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Adrian Hunter July 25, 2009, 7:45 p.m. UTC | #4
Matt Fleming wrote:
> On Sat, Jul 25, 2009 at 07:17:14PM +0300, Adrian Hunter wrote:
>> Matt Fleming wrote:
>>> And by saying what capabilities a host supports, when we add new
>>> capabilities we don't have to modify existing code to say that it
>>> doesn't support the new capability.
>> If the capabilities are the other way around, then all existing drivers
>> must be changed.  On the other hand, the if statement can easily be
>> improved:
>>
>> #define mmc_cap_mmc(host) (!((host)->caps & MMC_CAP_NOT_MMC))
>> #define mmc_cap_sd(host) (!((host)->caps & MMC_CAP_NOT_SD))
>> #define mmc_cap_sdio(host) (!((host)->caps & MMC_CAP_NOT_SDIO))
>>
>> -	mmc_send_if_cond(host, host->ocr_avail);
>> +	if (mmc_cap_sdio(host) || mmc_cap_sd(host))
>> +		mmc_send_if_cond(host, host->ocr_avail);
>> +
> 
> OK, that's a fair point, all drivers would need to be changed. However,
> I'm not adverse to making a one-time change to all drivers in the name
> of sanity. Enumerating what cards a controller doesn't support just
> doesn't sound correct to me.
> 
> It wouldn't be a complicated change either, I'd even be happy to write
> the patch ;-)

I have no objections if you write such a patch :-)

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index c5a7857..db43a1d 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1066,7 +1066,11 @@  void mmc_rescan(struct work_struct *work)
 	mmc_power_up(host);
 	mmc_go_idle(host);
 
-	mmc_send_if_cond(host, host->ocr_avail);
+	if (!(host->caps & MMC_CAP_NOT_SDIO) || !(host->caps & MMC_CAP_NOT_SD))
+		mmc_send_if_cond(host, host->ocr_avail);
+
+	if (host->caps & MMC_CAP_NOT_SDIO)
+		goto not_sdio;
 
 	/*
 	 * First we search for SDIO...
@@ -1078,6 +1082,10 @@  void mmc_rescan(struct work_struct *work)
 		goto out;
 	}
 
+not_sdio:
+	if (host->caps & MMC_CAP_NOT_SD)
+		goto not_sd;
+
 	/*
 	 * ...then normal SD...
 	 */
@@ -1088,6 +1096,10 @@  void mmc_rescan(struct work_struct *work)
 		goto out;
 	}
 
+not_sd:
+	if (host->caps & MMC_CAP_NOT_MMC)
+		goto not_mmc;
+
 	/*
 	 * ...and finally MMC.
 	 */
@@ -1098,6 +1110,8 @@  void mmc_rescan(struct work_struct *work)
 		goto out;
 	}
 
+not_mmc:
+
 	mmc_release_host(host);
 	mmc_power_off(host);
 
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 0a60b02..e996967 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -150,6 +150,13 @@  struct mmc_host {
 #define MMC_CAP_DISABLE		(1 << 7)	/* Can the host be disabled */
 #define MMC_CAP_NONREMOVABLE	(1 << 8)	/* Nonremovable e.g. eMMC */
 #define MMC_CAP_WAIT_WHILE_BUSY	(1 << 9)	/* Waits while card is busy */
+#define MMC_CAP_NOT_SDIO	(1 << 10)	/* Card cannot be SDIO */
+#define MMC_CAP_NOT_SD		(1 << 11)	/* Card cannot be SD */
+#define MMC_CAP_NOT_MMC		(1 << 12)	/* Card cannot be MMC */
+
+#define MMC_CAP_SDIO_ONLY	(MMC_CAP_NOT_SD | MMC_CAP_NOT_MMC)
+#define MMC_CAP_SD_ONLY		(MMC_CAP_NOT_SDIO | MMC_CAP_NOT_MMC)
+#define MMC_CAP_MMC_ONLY	(MMC_CAP_NOT_SDIO | MMC_CAP_NOT_SD)
 
 	/* host specific block data */
 	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */