Re: [PATCH] mmc: dw_mmc: Don't send clock off command if power is off

2015-03-27 Thread Jaehoon Chung
Hi,

On 03/23/2015 06:59 AM, Doug Anderson wrote:
 Alim,
 
 On Sun, Mar 22, 2015 at 5:16 AM, Alim Akhtar alim.akh...@gmail.com wrote:
 case MMC_POWER_OFF:
 -   /* Turn clock off before power goes down */
 -   dw_mci_setup_bus(slot, false);
 +   /* Turn clock off before power goes down; only if powered */
 +   if (slot-host-vqmmc_enabled)
 +   dw_mci_setup_bus(slot, false);

 vqmmc_enabled is always _true_ when entering MMC_POWER_OFF case..right?
 Is this done for extra protection? Or do you have a case where vqmmc
 is OFF and driver still calls dw_mci_setup_bus from here?
 
 Hmm.  I know I got it into the debugger in at least one reboot case
 where it was failing to turn the clock off.  I thought I confirmed it
 was the core trying to call MMC_POWER_OFF when the power was already
 off, but now I'm less certain.  I looked back at my debug session and
 I don't see where I got that evidence.  :-/  Certainly if I put a
 printout here right now I can't see my code making a difference.

I'm not sure this is really needs...and i can't find any error case..

Best Regards,
Jaehoon Chung
 
 Unfortunately the crash was a very rare one, so I may have to go back
 to the drawing board here...
 
 -Doug
 

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


[PATCH] mmc: core: Enable runtime PM management of host devices

2015-03-27 Thread Ulf Hansson
Currently those host drivers which have deployed runtime PM, deals with
the runtime PM reference counting entirely by themselves.

Since host drivers don't know when the core will send the next request
through some of the host_ops callbacks, they need to handle runtime PM
get/put between each an every request.

In quite many cases this has some negative effects, since it leads to a
high frequency of scheduled runtime PM suspend operations. That due to
the runtime PM reference count will normally reach zero in-between
every request.

We can decrease that frequency, by enabling the core to deal with
runtime PM reference counting of the host device. Since the core often
knows that it will send a seqeunce of requests, it makes sense for it
to keep a runtime PM reference count during these periods.

More exactly, let's increase the runtime PM reference count by invoking
pm_runtime_get_sync() from __mmc_claim_host(). Restore that action by
invoking pm_runtime_mark_last_busy() and pm_runtime_put_autosuspend()
in mmc_release_host(). In this way a runtime PM reference count will be
kept during the complete cycle of a claim - release host.

Signed-off-by: Ulf Hansson ulf.hans...@linaro.org
---
 drivers/mmc/core/core.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 709ada9..c296bc0 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -897,6 +897,7 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
int stop;
+   bool pm = false;
 
might_sleep();
 
@@ -916,13 +917,18 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t 
*abort)
host-claimed = 1;
host-claimer = current;
host-claim_cnt += 1;
+   if (host-claim_cnt == 1)
+   pm = true;
} else
wake_up(host-wq);
spin_unlock_irqrestore(host-lock, flags);
remove_wait_queue(host-wq, wait);
+
+   if (pm)
+   pm_runtime_get_sync(mmc_dev(host));
+
return stop;
 }
-
 EXPORT_SYMBOL(__mmc_claim_host);
 
 /**
@@ -947,6 +953,8 @@ void mmc_release_host(struct mmc_host *host)
host-claimer = NULL;
spin_unlock_irqrestore(host-lock, flags);
wake_up(host-wq);
+   pm_runtime_mark_last_busy(mmc_dev(host));
+   pm_runtime_put_autosuspend(mmc_dev(host));
}
 }
 EXPORT_SYMBOL(mmc_release_host);
-- 
1.9.1

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


Re: [PATCH] ARM: OMAP2: HSMMC: explicit fields to declare cover/card detect pin

2015-03-27 Thread Ulf Hansson
On 20 March 2015 at 15:53, Andreas Fenkart afenk...@gmail.com wrote:
 board-rx51 has no card detect pin in the mmc slot, but can detect that
 the (cell-phone) cover has been removed and the card is accessible.
 The semantics between cover/card detect differ, the gpio on the slot
 informs you after the card has been removed, cover removal does not
 necessarily mean that the card has been removed.
 This means different code paths are necessary. To complete this we
 also want different fields in the platform data for cover and card
 detect. This separation is not pushed all the way down into struct
 omap2_hsmmc_info which is used to initialize the platform data.
 If we did that we had to go over all board files and set the new
 gpio_cod pin to -EINVAL. If we forget one board or some out-of-tree
 archicture forgets that the default '0' is used which is a valid pin
 number.

 Signed-off-by: Andreas Fenkart afenk...@gmail.com

Thanks! Applied.

Kind regards
Uffe

 ---
  arch/arm/mach-omap2/hsmmc.c  | 33 
 
  drivers/mmc/host/omap_hsmmc.c| 11 ++-
  include/linux/platform_data/hsmmc-omap.h |  6 ++
  3 files changed, 33 insertions(+), 17 deletions(-)

 diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
 index dc6e79c..9a8611a 100644
 --- a/arch/arm/mach-omap2/hsmmc.c
 +++ b/arch/arm/mach-omap2/hsmmc.c
 @@ -150,9 +150,13 @@ static int nop_mmc_set_power(struct device *dev, int 
 power_on, int vdd)
  static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data
   *mmc_controller, int controller_nr)
  {
 -   if (gpio_is_valid(mmc_controller-switch_pin) 
 -   (mmc_controller-switch_pin  OMAP_MAX_GPIO_LINES))
 -   omap_mux_init_gpio(mmc_controller-switch_pin,
 +   if (gpio_is_valid(mmc_controller-gpio_cd) 
 +   (mmc_controller-gpio_cd  OMAP_MAX_GPIO_LINES))
 +   omap_mux_init_gpio(mmc_controller-gpio_cd,
 +  OMAP_PIN_INPUT_PULLUP);
 +   if (gpio_is_valid(mmc_controller-gpio_cod) 
 +   (mmc_controller-gpio_cod  OMAP_MAX_GPIO_LINES))
 +   omap_mux_init_gpio(mmc_controller-gpio_cod,
OMAP_PIN_INPUT_PULLUP);
 if (gpio_is_valid(mmc_controller-gpio_wp) 
 (mmc_controller-gpio_wp  OMAP_MAX_GPIO_LINES))
 @@ -250,15 +254,20 @@ static int __init omap_hsmmc_pdata_init(struct 
 omap2_hsmmc_info *c,
 mmc-internal_clock = !c-ext_clock;
 mmc-reg_offset = 0;

 -   mmc-switch_pin = c-gpio_cd;
 +   if (c-cover_only) {
 +   /* detect if mobile phone cover removed */
 +   mmc-gpio_cd = -EINVAL;
 +   mmc-gpio_cod = c-gpio_cd;
 +   } else {
 +   /* card detect pin on the mmc socket itself */
 +   mmc-gpio_cd = c-gpio_cd;
 +   mmc-gpio_cod = -EINVAL;
 +   }
 mmc-gpio_wp = c-gpio_wp;

 mmc-remux = c-remux;
 mmc-init_card = c-init_card;

 -   if (c-cover_only)
 -   mmc-cover = 1;
 -
 if (c-nonremovable)
 mmc-nonremovable = 1;

 @@ -358,7 +367,15 @@ void omap_hsmmc_late_init(struct omap2_hsmmc_info *c)
 if (!mmc_pdata)
 continue;

 -   mmc_pdata-switch_pin = c-gpio_cd;
 +   if (c-cover_only) {
 +   /* detect if mobile phone cover removed */
 +   mmc_pdata-gpio_cd = -EINVAL;
 +   mmc_pdata-gpio_cod = c-gpio_cd;
 +   } else {
 +   /* card detect pin on the mmc socket itself */
 +   mmc_pdata-gpio_cd = c-gpio_cd;
 +   mmc_pdata-gpio_cod = -EINVAL;
 +   }
 mmc_pdata-gpio_wp = c-gpio_wp;

 res = omap_device_register(pdev);
 diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
 index 053cd38..265391f 100644
 --- a/drivers/mmc/host/omap_hsmmc.c
 +++ b/drivers/mmc/host/omap_hsmmc.c
 @@ -427,15 +427,15 @@ static int omap_hsmmc_gpio_init(struct mmc_host *mmc,
  {
 int ret;

 -   if (pdata-cover  gpio_is_valid(pdata-switch_pin)) {
 -   ret = mmc_gpio_request_cd(mmc, pdata-switch_pin, 0);
 +   if (gpio_is_valid(pdata-gpio_cod)) {
 +   ret = mmc_gpio_request_cd(mmc, pdata-gpio_cod, 0);
 if (ret)
 return ret;

 host-get_cover_state = omap_hsmmc_get_cover_state;
 mmc_gpio_set_cd_isr(mmc, omap_hsmmc_cover_irq);
 -   } else if (!pdata-cover  gpio_is_valid(pdata-switch_pin)) {
 -   ret = mmc_gpio_request_cd(mmc, pdata-switch_pin, 0);
 +   } else if (gpio_is_valid(pdata-gpio_cd)) {
 +   ret = mmc_gpio_request_cd(mmc, pdata-gpio_cd, 0);
 if (ret)
 return ret;

 @@ -1932,7 +1932,8 @@ 

[RFC] i.MX25/35/SDHCI: switch off DMA usage

2015-03-27 Thread Juergen Borleis
DMA and the required overhead on very small data blocks seems an expensive
operation. Due to erratum ENGCM07207 for i.MX25 and i.MX35 SoCs the
support for multiblock transfers is disabled which results into a huge
amount of single 512 byte sector transfers and interrupts. This slows down
the transmission speed to below 500 kiB/s (even at 50 MHz SD card clock).
Using PIO instead of DMA to avoid ENGCM07207 happens and re-enabling
multiblock transfers again improve the transmission capability up to about
2.5 MiB/s.

I'm still not sure if ENGCM07207 is related to DMA only and can not happen
when PIO is used instead. Someone out there with experience regarding this
topic?
---
 drivers/mmc/host/sdhci-esdhc-imx.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c 
b/drivers/mmc/host/sdhci-esdhc-imx.c
index 10ef8244a239..f5fd569a17c3 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -976,8 +976,8 @@ static int sdhci_esdhc_imx_probe(struct platform_device 
*pdev)
 
if (imx_data-socdata-flags  ESDHC_FLAG_ENGCM07207)
/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
-   host-quirks |= SDHCI_QUIRK_NO_MULTIBLOCK
-   | SDHCI_QUIRK_BROKEN_ADMA;
+   host-quirks |=
+   SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_BROKEN_DMA;
 
/*
 * The imx6q ROM code will change the default watermark level setting
-- 
1.7.10.4

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


Re: [PATCH 0/2] Remove mmc_host enable/disable methods.

2015-03-27 Thread Ulf Hansson
On 25 March 2015 at 22:43, NeilBrown n...@brown.name wrote:
 Only omap_hsmmc uses enable and disable, and this seems
 to be largely for historical reasons and is no longer
 necessary.

 I have tested these patches with an OMAP3 with an
 uSD card on mmc0 and a wifi SDIO device on mmc1.

 NeilBrown


 ---

 NeilBrown (2):
   mmc: omap_hsmmc: stop using .enable and .disable method.
   mmc: remove enable/disable methods.


  drivers/mmc/core/core.c   |5 -
  drivers/mmc/host/omap_hsmmc.c |   24 +++-
  include/linux/mmc/host.h  |6 --
  3 files changed, 3 insertions(+), 32 deletions(-)

 --

Applied both patches (the later version of patch 1). Also I took the
liberty to update the commit messages.

If you care about my comments for patch1, let's deal with that as new
separate cleanup-patch.

Thanks!

Kind regards
Uffe
--
To unsubscribe from this list: send the line unsubscribe linux-mmc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH V2 11/15] mmc: sdhci: Change to new way of doing re-tuning

2015-03-27 Thread Adrian Hunter
On 26/03/15 18:06, Ulf Hansson wrote:
 On 25 March 2015 at 14:48, Adrian Hunter adrian.hun...@intel.com wrote:

 On 24/03/15 23:12, Ulf Hansson wrote:
 On 23 March 2015 at 22:11, Adrian Hunter adrian.hun...@intel.com wrote:
 On 23/03/2015 5:02 p.m., Ulf Hansson wrote:

 [...]


 I have no locking issues, so I am not sure what you mean here.


 Okay, I should have stated race conditions.


 Which I resolved using runtime get / put calls.

 Yes, I noticed that and it works! Though, I would rather avoid to add
 yet another pair of host ops callbacks for this.

 What do you think if these options instead?
 1) Do runtime PM get/put from the host ops -enable|disable()
 callbacks. As omap_hsmmc does.
 2) Or even better, do runtime PM get/put directly of the host device
 from mmc_claim|release_host().

 Claiming the host is not directly related to host controller runtime pm. It
 is possible to imagine cases for claiming the host for synchronization
 reasons that do not need the host controller powered up. And card drivers
 could reasonably assume that they can claim the host for long periods
 without affecting the runtime pm of the host controller.
 
 
 Yes, it _may_ power up the host controller sometimes when not needed.
 I don't think this will be an issue, mostly because it should be rare
 and not happening frequently - if ever.
 
 The only users of mmc_claim_host() for SD/MMC is the core itself, so I
 don't see any issue with misbehaving card drivers here.
 
 SDIO is again different, since it's up to the SDIO func drivers to
 behave - as you stated. But, if they don't they anyway need to be
 fixed, right!?

Be aware that that links the holding of re-tuning with claiming the host.
It will then not be allowed for re-tuning to be held when the host is
released. Will we have to add to mmc_release_host():

WARN_ON(host-hold_count);

That could be a problem. Say you wanted to start bkops and then release the
host so that a different context could issue an HPI. That wouldn't be
allowed anymore.

Generally it is impossible to see all ends, which begs the question: why
link things if you don't have to?

 

 Currently we have that the host controller driver is the exclusive owner of
 runtime pm for the host controller. So the first thing is to decide if we
 want to keep that or let the core be involved as well. I would argue for
 sticking with the status quo. Let the host controller driver know what is
 going on and leave it to do the right thing with its own power management.
 
 The problem I see with the current solution, is that we will be
 scheduling a runtime PM suspend for each an every request towards the
 host.
 
 It's ineffective, due to that we will unnecessary involve the runtime
 PM core, thus increasing CPU utilization - when we actually don't need
 to.
 
 I will send a patch for this tomorrow, let's discuss it separately.

Yes please let's keep that separate.

 
 [...]
 

 I have thought more about this since yesterday and I somewhat agree
 with your suggestion. Especially in that sense that I think we should
 consider Neil's issue as an idle operation for SDIO.

 For idle operations for MMC/SD cards, runtime PM is already
 deployed. So, I think it's just a matter of extending that support to
 cover more idle operations besides the MMC_CAP_AGGRESSIVE_PM thing.

 What we need to figure out is how to make this work for SDIO - and
 that's when it becomes more complex. I really would like us to avoid
 exporting new SDIO APIs, unless really needed.

 Today runtime PM is deployed by the following SDIO func drivers:
 drivers/net/wireless/libertas/if_sdio.c
 drivers/net/wireless/ti/wl1251/sdio.c
 drivers/net/wireless/ti/wlcore/sdio.c

 We _could_ consider to convert above drivers to use something else
 than runtime PM to control the power to the card. I think that would
 be the ideal solution, since then we can deploy runtime PM for SDIO
 fairly similar to how MMC/SDIO is done. That means doing runtime PM
 get/put of the device for the struct mmc_card, inside the mmc core
 while handling SDIO requests.

 The above requires some work, both in the mmc core and in the SDIO
 func drivers. The nice thing is that we don't need to export new APIs
 to the SDIO func drivers and we can keep the complexity of dealing
 with idle operations inside the mmc core.

 Thoughts?

 There isn't necessarily any link between idle operations and runtime pm.
 
 I think this is exactly what runtime PM is designed for so I don't
 want us to re-invent something that is specific for mmc.

Need to remember that PM can theoretically be configured out, which makes
using it for bkops seem inappropriate.

 

 For example for eMMC background operations I would expect to see:

 - queue is empty so block driver enables idle operations.
 - core waits (delayed work?) a few milliseconds and then starts bkops.
 - a new I/O request arrives, block driver wakes up and tells the core to
 stop idle operations ASAP, and waits until it does.
 - or, the 

Re: [PATCH V2 11/15] mmc: sdhci: Change to new way of doing re-tuning

2015-03-27 Thread Adrian Hunter
On 27/03/15 11:54, Adrian Hunter wrote:
 On 26/03/15 18:06, Ulf Hansson wrote:
 On 25 March 2015 at 14:48, Adrian Hunter adrian.hun...@intel.com wrote:

 On 24/03/15 23:12, Ulf Hansson wrote:
 On 23 March 2015 at 22:11, Adrian Hunter adrian.hun...@intel.com wrote:
 On 23/03/2015 5:02 p.m., Ulf Hansson wrote:

 [...]


 I have no locking issues, so I am not sure what you mean here.


 Okay, I should have stated race conditions.


 Which I resolved using runtime get / put calls.

 Yes, I noticed that and it works! Though, I would rather avoid to add
 yet another pair of host ops callbacks for this.

 What do you think if these options instead?
 1) Do runtime PM get/put from the host ops -enable|disable()
 callbacks. As omap_hsmmc does.
 2) Or even better, do runtime PM get/put directly of the host device
 from mmc_claim|release_host().

 Claiming the host is not directly related to host controller runtime pm. It
 is possible to imagine cases for claiming the host for synchronization
 reasons that do not need the host controller powered up. And card drivers
 could reasonably assume that they can claim the host for long periods
 without affecting the runtime pm of the host controller.


 Yes, it _may_ power up the host controller sometimes when not needed.
 I don't think this will be an issue, mostly because it should be rare
 and not happening frequently - if ever.

 The only users of mmc_claim_host() for SD/MMC is the core itself, so I
 don't see any issue with misbehaving card drivers here.

 SDIO is again different, since it's up to the SDIO func drivers to
 behave - as you stated. But, if they don't they anyway need to be
 fixed, right!?
 
 Be aware that that links the holding of re-tuning with claiming the host.
 It will then not be allowed for re-tuning to be held when the host is
 released. Will we have to add to mmc_release_host():
 
   WARN_ON(host-hold_count);
 
 That could be a problem. Say you wanted to start bkops and then release the
 host so that a different context could issue an HPI. That wouldn't be
 allowed anymore.

On the other hand, we would need to prevent the host controller runtime
suspending in that case anyway.

 
 Generally it is impossible to see all ends, which begs the question: why
 link things if you don't have to?

So I correct myself. Any time we would need to hold re-tuning but release
the host would anyway require preventing runtime suspend of the host
controller. So the requirement: don't allow the host controller to runtime
suspend while re-tuning is held is covered by the requirement don't allow
the host controller to runtime suspend when it is doing something.

 


 Currently we have that the host controller driver is the exclusive owner of
 runtime pm for the host controller. So the first thing is to decide if we
 want to keep that or let the core be involved as well. I would argue for
 sticking with the status quo. Let the host controller driver know what is
 going on and leave it to do the right thing with its own power management.

 The problem I see with the current solution, is that we will be
 scheduling a runtime PM suspend for each an every request towards the
 host.

 It's ineffective, due to that we will unnecessary involve the runtime
 PM core, thus increasing CPU utilization - when we actually don't need
 to.

 I will send a patch for this tomorrow, let's discuss it separately.
 
 Yes please let's keep that separate.
 

 [...]


 I have thought more about this since yesterday and I somewhat agree
 with your suggestion. Especially in that sense that I think we should
 consider Neil's issue as an idle operation for SDIO.

 For idle operations for MMC/SD cards, runtime PM is already
 deployed. So, I think it's just a matter of extending that support to
 cover more idle operations besides the MMC_CAP_AGGRESSIVE_PM thing.

 What we need to figure out is how to make this work for SDIO - and
 that's when it becomes more complex. I really would like us to avoid
 exporting new SDIO APIs, unless really needed.

 Today runtime PM is deployed by the following SDIO func drivers:
 drivers/net/wireless/libertas/if_sdio.c
 drivers/net/wireless/ti/wl1251/sdio.c
 drivers/net/wireless/ti/wlcore/sdio.c

 We _could_ consider to convert above drivers to use something else
 than runtime PM to control the power to the card. I think that would
 be the ideal solution, since then we can deploy runtime PM for SDIO
 fairly similar to how MMC/SDIO is done. That means doing runtime PM
 get/put of the device for the struct mmc_card, inside the mmc core
 while handling SDIO requests.

 The above requires some work, both in the mmc core and in the SDIO
 func drivers. The nice thing is that we don't need to export new APIs
 to the SDIO func drivers and we can keep the complexity of dealing
 with idle operations inside the mmc core.

 Thoughts?

 There isn't necessarily any link between idle operations and runtime pm.

 I think this is exactly what runtime PM is designed for so I don't
 

Re: [RFC] i.MX25/35/SDHCI: switch off DMA usage

2015-03-27 Thread Dong Aisheng
On Fri, Mar 27, 2015 at 11:52:04AM +0100, Juergen Borleis wrote:
 DMA and the required overhead on very small data blocks seems an expensive
 operation. Due to erratum ENGCM07207 for i.MX25 and i.MX35 SoCs the
 support for multiblock transfers is disabled which results into a huge
 amount of single 512 byte sector transfers and interrupts. This slows down
 the transmission speed to below 500 kiB/s (even at 50 MHz SD card clock).
 Using PIO instead of DMA to avoid ENGCM07207 happens and re-enabling
 multiblock transfers again improve the transmission capability up to about
 2.5 MiB/s.
 
 I'm still not sure if ENGCM07207 is related to DMA only and can not happen
 when PIO is used instead. Someone out there with experience regarding this
 topic?

The errata does not state it's related to DMA only.
http://cache.freescale.com/files/dsp/doc/errata/IMX35CE.pdf
I could double check with our IC guys to confirm it.

Regards
Dong Aisheng

 ---
  drivers/mmc/host/sdhci-esdhc-imx.c |4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c 
 b/drivers/mmc/host/sdhci-esdhc-imx.c
 index 10ef8244a239..f5fd569a17c3 100644
 --- a/drivers/mmc/host/sdhci-esdhc-imx.c
 +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
 @@ -976,8 +976,8 @@ static int sdhci_esdhc_imx_probe(struct platform_device 
 *pdev)
  
   if (imx_data-socdata-flags  ESDHC_FLAG_ENGCM07207)
   /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
 - host-quirks |= SDHCI_QUIRK_NO_MULTIBLOCK
 - | SDHCI_QUIRK_BROKEN_ADMA;
 + host-quirks |=
 + SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_BROKEN_DMA;
  
   /*
* The imx6q ROM code will change the default watermark level setting
 -- 
 1.7.10.4
 
 Juergen
--
To unsubscribe from this list: send the line unsubscribe linux-mmc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] mmc: sleep notification

2015-03-27 Thread Ulf Hansson
[...]

  What if Sleep_Notification will take several seconds?

 Yes, that horrible! You should tell your colleagues designing FTLs to make 
 sure
 that _never_ happens.

 Agree, but we need to consider and take care of all such cases in the driver 
 side.
 Device might be busy with its internal garbage collection, and as spec 
 allows, it
 will complete it in a great manner after host sends PON command.


Okay, so to me, I think the SLEEP notification needs to be sent as a
part of the system PM suspend phase. And more exactly from the
bus_ops-suspend() callback.

In addition to that, we should be able improve the situation by also
sending the SLEEP notification as part of an idle operation. With
idle operation I mean the mmc block layer hasn’t received any new
request for a while (the framework for this is already implemented by
using runtime PM).

So if the SLEEP notification was sent during the idle operation and
no new request was needed during the system PM suspend phase we
wouldn't have to wake up the card again using HPI, but instead just
leave it sleeping and send CMD5.

Still, there would be no guarantees that idle operations is executed
before a system PM suspend phase starts. So there are no way we can
improve the worst case scenario.

Kind regards
Uffe
--
To unsubscribe from this list: send the line unsubscribe linux-mmc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH] mmc: sleep notification

2015-03-27 Thread Alex Lemberg
Hi Ulf,

Sorry for the delay in response...

 -Original Message-
 From: Ulf Hansson [mailto:ulf.hans...@linaro.org]
 Sent: Tuesday, March 17, 2015 12:44 PM
 To: Alex Lemberg
 Cc: Avi Shchislowski; linux-mmc; Chris Ball
 Subject: Re: [PATCH] mmc: sleep notification
 
 On 16 March 2015 at 17:58, Alex Lemberg alex.lemb...@sandisk.com
 wrote:
 
 
  -Original Message-
  From: Ulf Hansson [mailto:ulf.hans...@linaro.org]
  Sent: Monday, March 16, 2015 3:35 PM
  To: Alex Lemberg
  Cc: Avi Shchislowski; linux-mmc; Chris Ball
  Subject: Re: [PATCH] mmc: sleep notification
 
  On 16 March 2015 at 12:37, Alex Lemberg alex.lemb...@sandisk.com
  wrote:
   Hi Ulf,
  
   -Original Message-
   From: Ulf Hansson [mailto:ulf.hans...@linaro.org]
   Sent: Thursday, March 12, 2015 11:10 AM
   To: Alex Lemberg
   Cc: Avi Shchislowski; linux-mmc; Chris Ball
   Subject: Re: [PATCH] mmc: sleep notification
  
   [...]
  
 Also, I think we need to clarify one more point for this patch:
 As was mentioned in commit message - Sleep_Notification can
 be interrupted
by HPI.
 This allows not blocking the host during the
 Sleep_Notification busy time and allows accepting requests coming
 during this stage.
 Thus, without having HPI supported, suspend/resume process
 might be influenced by Sleep_Notification busy time, and this
 should not happen -
suspend/resume should be done in very fast and not blocking manner.
   
I fail to understand your comment here.
   
Please tell me at what point(s) your think it make sense to
issue the SLEEP_NOTIFICATION? If that is during the suspend
phase, then a HPI request can't be triggered.
   
I think SLEEP_NOTIFICATION should be issued on mmc_pm_notify()
call, on PM_SUSPEND_PREPARE case.
  
   So, exactly why is that to prefer, comparing doing it in system PM
   -suspend() callback?
  
   Assuming that SLEEP_NOTIFICATION may take time (defined in
   SLEEP_NOTIFICATION_TIME byte in EXT_CSD [216]), I think it is
   better to send it from pm notifier - mmc_pm_notify().
 
  I assume you think that you will earn some milliseconds doing it in
  this phase, but I am not so sure.
 
  I was thinking mainly about how to prevent blocking during
 Sleep_Notification process.
 
 
  After the PM_SUSPEND_PREPARE notifier, we still have the mmc block
  queue open and are ready to serve requests. Therefore I would expect
  the SLEEP_NOTIFICATION to potentially be interrupted by using HPI.
 
  Right, and this was a reason for adding HPI support during the
 Sleep_Notification.
 
 
  Then we end up with the following sequence during the system PM sleep
 phase.
  1. Issue SLEEP_NOTIFICATION.
  2. Interrupt SLEEP_NOTIFICATION, using HPI.
  3. Serve blk request
  4. Issue SLEEP_NOTIFICATION.
  5. Issue SLEEP (CMD5).
 
  Correct, this is a sequence that we see after adding the patch.
 
  That seems like a bad idea to me.
 
  Could you please explain why?
  Would you suggest to call Sleep_Notification from Suspend only?
 
 Since otherwise we may end up issuing SLEEP_NOTIFICATION not only once, but
 twice during a system PM sleep sequence. So then we actually get an increased
 system PM suspend time.
 
  What if Sleep_Notification will take several seconds?
 
 Yes, that horrible! You should tell your colleagues designing FTLs to make 
 sure
 that _never_ happens.

Agree, but we need to consider and take care of all such cases in the driver 
side. 
Device might be busy with its internal garbage collection, and as spec allows, 
it
will complete it in a great manner after host sends PON command.
 
 
 Also, this makes me wonder how this kind of feature ever could make it into 
 the
 JEDEC specification.
 
 What we had earlier with CMD5 only should never have been changed.
 
 Kind regards
 Uffe


Re: [PATCH] mmc: core: Enable runtime PM management of host devices

2015-03-27 Thread Adrian Hunter
On 27/03/15 13:15, Ulf Hansson wrote:
 Currently those host drivers which have deployed runtime PM, deals with
 the runtime PM reference counting entirely by themselves.
 
 Since host drivers don't know when the core will send the next request
 through some of the host_ops callbacks, they need to handle runtime PM
 get/put between each an every request.
 
 In quite many cases this has some negative effects, since it leads to a
 high frequency of scheduled runtime PM suspend operations. That due to
 the runtime PM reference count will normally reach zero in-between
 every request.
 
 We can decrease that frequency, by enabling the core to deal with
 runtime PM reference counting of the host device. Since the core often
 knows that it will send a seqeunce of requests, it makes sense for it
 to keep a runtime PM reference count during these periods.
 
 More exactly, let's increase the runtime PM reference count by invoking
 pm_runtime_get_sync() from __mmc_claim_host(). Restore that action by
 invoking pm_runtime_mark_last_busy() and pm_runtime_put_autosuspend()
 in mmc_release_host(). In this way a runtime PM reference count will be
 kept during the complete cycle of a claim - release host.
 
 Signed-off-by: Ulf Hansson ulf.hans...@linaro.org

The downside is that it precludes the possibility of a host driver using
runtime pm for very aggressive pm. However there is anyway MMC_CLKGATE for
that, and otherwise all host drivers are either using autosuspend_delay or
staying active while the card has power. So:

Acked-by: Adrian Hunter adrian.hun...@intel.com

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


Re: [PATCH v4 1/4] mmc: dw_mmc: Don't try to enable the CD until we're sure we're not deferring

2015-03-27 Thread Doug Anderson
Jaehoon,

On Thu, Mar 26, 2015 at 10:55 PM, Jaehoon Chung jh80.ch...@samsung.com wrote:
 Hi, Doug.

 This patch is not related with [patch 2/4~4/4].
 [PATCH v4 2/4] mmc: core: Add mmc_regulator_set_vqmmc() is discussing..
 So i think if you're ok, i will pick this one [PATCH v4 1/4]. how about?

Please take it and send it to Ulf as soon as you can.  It is only
related in that the later patches in this series suddenly make the
rk3288-evb start deferring and that causes a crash without this patch.
--
To unsubscribe from this list: send the line unsubscribe linux-mmc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V4 02/15] mmc: core: Disable re-tuning when card is no longer initialized

2015-03-27 Thread Adrian Hunter
Re-tuning is done before a request is sent to the card.
Host controller drivers can choose to enable re-tuning
when tuning is done during card initialization. To
ensure that re-tuning gets disabled, add disabling to
mmc_set_initial_state() which is called whenever the
card is powered on, off, or reset.

Signed-off-by: Adrian Hunter adrian.hun...@intel.com
---
 drivers/mmc/core/core.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index c296bc0..2679264 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1140,6 +1140,8 @@ void mmc_set_bus_width(struct mmc_host *host, unsigned 
int width)
  */
 void mmc_set_initial_state(struct mmc_host *host)
 {
+   mmc_retune_disable(host);
+
if (mmc_host_is_spi(host))
host-ios.chip_select = MMC_CS_HIGH;
else
-- 
1.9.1

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


[PATCH V4 09/15] mmc: core: Separate out the mmc_switch status check so it can be re-used

2015-03-27 Thread Adrian Hunter
Make a separate function to do the mmc_switch status check
so it can be re-used. This is preparation for adding support
for HS400 re-tuning.

Signed-off-by: Adrian Hunter adrian.hun...@intel.com
---
 drivers/mmc/core/mmc_ops.c | 30 --
 drivers/mmc/core/mmc_ops.h |  1 +
 2 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index f67b0fd..02be77e 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -449,6 +449,21 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc)
return err;
 }
 
+int mmc_switch_status_error(struct mmc_host *host, u32 status)
+{
+   if (mmc_host_is_spi(host)) {
+   if (status  R1_SPI_ILLEGAL_COMMAND)
+   return -EBADMSG;
+   } else {
+   if (status  0xFDFFA000)
+   pr_warn(%s: unexpected status %#x after switch\n,
+   mmc_hostname(host), status);
+   if (status  R1_SWITCH_ERROR)
+   return -EBADMSG;
+   }
+   return 0;
+}
+
 /**
  * __mmc_switch - modify EXT_CSD register
  * @card: the MMC card associated with the data transfer
@@ -557,20 +572,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, 
u8 value,
}
} while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
 
-   if (mmc_host_is_spi(host)) {
-   if (status  R1_SPI_ILLEGAL_COMMAND) {
-   err = -EBADMSG;
-   goto out;
-   }
-   } else {
-   if (status  0xFDFFA000)
-   pr_warn(%s: unexpected status %#x after switch\n,
-   mmc_hostname(host), status);
-   if (status  R1_SWITCH_ERROR) {
-   err = -EBADMSG;
-   goto out;
-   }
-   }
+   err = mmc_switch_status_error(host, status);
 out:
mmc_retune_release(host);
 
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
index 6f4b00e..f498f9a 100644
--- a/drivers/mmc/core/mmc_ops.h
+++ b/drivers/mmc/core/mmc_ops.h
@@ -27,6 +27,7 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
 int mmc_bus_test(struct mmc_card *card, u8 bus_width);
 int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status);
 int mmc_can_ext_csd(struct mmc_card *card);
+int mmc_switch_status_error(struct mmc_host *host, u32 status);
 
 #endif
 
-- 
1.9.1

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


[PATCH V4 08/15] mmc: mmc: Comment that callers need to hold re-tuning if the card is put to sleep

2015-03-27 Thread Adrian Hunter
Currently mmc sleep is only used before power off and
is not paired with waking up.  If that ever changed,
re-tuning might need to be held, so add a comment for that.

Signed-off-by: Adrian Hunter adrian.hun...@intel.com
---
 drivers/mmc/core/mmc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 1d41e85..813b02a 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1496,6 +1496,7 @@ static int mmc_can_sleep(struct mmc_card *card)
return (card  card-ext_csd.rev = 3);
 }
 
+/* If necessary, callers must hold re-tuning */
 static int mmc_sleep(struct mmc_host *host)
 {
struct mmc_command cmd = {0};
-- 
1.9.1

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


[PATCH V4 07/15] mmc: core: Hold re-tuning while bkops ongoing

2015-03-27 Thread Adrian Hunter
Hold re-tuning during bkops to prevent
it from conflicting with the busy state.

Signed-off-by: Adrian Hunter adrian.hun...@intel.com
---
 drivers/mmc/core/core.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index d4e3248..f8ae793 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -316,6 +316,8 @@ void mmc_start_bkops(struct mmc_card *card, bool 
from_exception)
} else {
timeout = 0;
use_busy_signal = false;
+   /* Hold re-tuning for ongoing bkops */
+   mmc_retune_hold(card-host);
}
 
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -324,6 +326,9 @@ void mmc_start_bkops(struct mmc_card *card, bool 
from_exception)
if (err) {
pr_warn(%s: Error %d starting bkops\n,
mmc_hostname(card-host), err);
+   /* bkops not ongoing, so release re-tuning */
+   if (!use_busy_signal)
+   mmc_retune_release(card-host);
goto out;
}
 
@@ -749,6 +754,7 @@ int mmc_stop_bkops(struct mmc_card *card)
 */
if (!err || (err == -EINVAL)) {
mmc_card_clr_doing_bkops(card);
+   mmc_retune_release(card-host);
err = 0;
}
 
-- 
1.9.1

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


[PATCH V4 00/15] mmc: host: Add facility to support re-tuning

2015-03-27 Thread Adrian Hunter
Hi

Here is V4 of some patches to move re-tuning support
out of sdhci and into the core, and add support for HS400
re-tuning.

Currently sdhci does re-tuning transparently by
calling sdhci_execute_tuning() from its -request()
function.

The problem with HS400 re-tuning is that it must be
done in HS200 mode. That means using switch commands
and making ios changes. That means it potentially
conflicts with other command sequences. The new
re-tuning support accomodates that.

These patches now depend on Ulf's patch:

mmc: core: Enable runtime PM management of host devices


Changes in V4:

mmc: host: Add facility to support re-tuning

Assume mmc_claim_host() runtime resumes the host
controller so there are no races with runtime pm.
Consequently remove now un-needed re-tuning host
operations.

mmc: core: Add support for re-tuning before each request

Call mmc_retune() prior to -request()

mmc: sdhci: Change to new way of doing re-tuning

Updated to reflect the changes above.

Changes in V3:

mmc: host: Add facility to support re-tuning

Add host-retune_now flag so re-tuning can be
started in the host drivers -request()
function to avoid racing with Runtime PM.

Add host operations to let the host know when
re-tuning is held, for eaxmple, to enable
synchronization with runtime suspend / resume.

Ensure functions are exported.

mmc: core: Add support for re-tuning before each request
Updated to reflect the change above.

mmc: core: Check re-tuning before retrying
Updated to reflect the change above.

mmc: core: Hold re-tuning during switch commands
Updated to reflect the change above.

mmc: core: Hold re-tuning during erase commands
Updated to reflect the change above.

mmc: core: Hold re-tuning while bkops ongoing
Updated to reflect the change above.

mmc: core: Add support for HS400 re-tuning
Updated and as already sent separately as V3:
Remember to mmc_set_bus_speed(card) in mmc_hs400_to_hs200()

mmc: sdhci: Change to new way of doing re-tuning
Call mmc_retune() from -request() function to
avoid racing with Runtime PM. And implement
hold_tuning / release_tuning operations to prevent
runtime suspend while re-tuning is held.

mmc: block: Retry errored data requests when re-tuning is needed
Updated and as already sent separately as V3:
Only retry when there is an error

Changes in V2:

Added support to the block driver for re-tuning
and retrying after a CRC error. The host driver
is left to decide when an error indicates re-tuning
is needed. The block driver will retry a data request
once if re-tuning is flagged as needed.

SDIO drivers need not be aware of re-tuning because
retrying will anyway cause re-tuning when re-tuning
is flagged as needed. Nevertheless SDIO drivers could
use the need_retune flag to instigate a retry when
otherwise they might not have.

mmc: core: Simplify by adding mmc_execute_tuning()
Dropped because it has been applied

mmc: host: Add facility to support re-tuning
Renamed mmc_retune_retry() to mmc_retune_recheck()
to better reflect what it does.

mmc: core: Move mmc_card_removed() into mmc_start_request()
Dropped because it has been applied

mmc: core: Add support for re-tuning before each request
Fixed un-balanced re-tune hold / release

mmc: sdhci: Always init buf_ready_int
Dropped because it has been applied

mmc: core: Separate out the mmc_switch status check so it can be re-used
New patch

mmc: core: Add support for HS400 re-tuning
It was found that that the original code was not reliable
after a CRC error. The problem was that the CMD13 after a
switch was faiing. So the code was changed to check the
switch status *after* changing the I/O state to match the
switch i.e. the new I/O state is the correct one to use
after a switch.

mmc: sdhci: Flag re-tuning is needed on CRC or End-Bit errors
New patch

mmc: block: Check re-tuning in the recovery path
New patch

mmc: block: Retry data requests when re-tuning is needed
New patch

mmc: core: Don't print reset warning if reset is not supported
New patch


Adrian Hunter (15):
  mmc: host: Add facility to support re-tuning
  mmc: core: Disable re-tuning when card is no longer initialized
  mmc: core: Add support for re-tuning before each request
  mmc: core: Check re-tuning before retrying
  mmc: core: Hold re-tuning during switch commands
  mmc: core: Hold re-tuning during erase commands
  mmc: core: Hold re-tuning while bkops ongoing
  mmc: mmc: Comment that callers need to hold re-tuning if the card is put 
to sleep
  mmc: core: 

[PATCH V4 04/15] mmc: core: Check re-tuning before retrying

2015-03-27 Thread Adrian Hunter
Possibly a command is failing because re-tuning is needed.
Use mmc_retune_recheck() to check re-tuning. At that point
re-tuning is held, at least by the request, so
mmc_retune_recheck() flags host-retune_now if the hold
count is 1.

Signed-off-by: Adrian Hunter adrian.hun...@intel.com
---
 drivers/mmc/core/core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index bb50d82..16881c8 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -434,6 +434,7 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host,
host-areq);
break; /* return err */
} else {
+   mmc_retune_recheck(host);
pr_info(%s: req failed (CMD%u): %d, 
retrying...\n,
mmc_hostname(host),
cmd-opcode, cmd-error);
@@ -483,6 +484,8 @@ static void mmc_wait_for_req_done(struct mmc_host *host,
mmc_card_removed(host-card))
break;
 
+   mmc_retune_recheck(host);
+
pr_debug(%s: req failed (CMD%u): %d, retrying...\n,
 mmc_hostname(host), cmd-opcode, cmd-error);
cmd-retries--;
-- 
1.9.1

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


[PATCH V4 01/15] mmc: host: Add facility to support re-tuning

2015-03-27 Thread Adrian Hunter
Currently, there is core support for tuning during
initialization. There can also be a need to re-tune
periodically (e.g. sdhci) or to re-tune after the
host controller is powered off (e.g. after PM
runtime suspend / resume) or to re-tune in response
to CRC errors.

The main requirements for re-tuning are:
  - ability to enable / disable re-tuning
  - ability to flag that re-tuning is needed
  - ability to re-tune before any request
  - ability to hold off re-tuning if the card is busy
  - ability to hold off re-tuning if re-tuning is in
  progress
  - ability to run a re-tuning timer

To support those requirements 6 members are added to struct
mmc_host:

  unsigned int  can_retune:1;   /* re-tuning can be used */
  unsigned int  doing_retune:1; /* re-tuning in progress */
  unsigned int  retune_now:1;   /* do re-tuning at next req */
  int   need_retune;/* re-tuning is needed */
  int   hold_retune;/* hold off re-tuning */
  struct timer_list retune_timer;   /* for periodic re-tuning */

need_retune is an integer so it can be set without needing
synchronization. hold_retune is a integer to allow nesting.

Various simple functions are provided to set / clear those
variables.

Subsequent patches take those functions into use.

Signed-off-by: Adrian Hunter adrian.hun...@intel.com
---
 drivers/mmc/core/host.c  | 72 
 include/linux/mmc/host.h | 32 +
 2 files changed, 104 insertions(+)

diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 8be0df7..ce0ddf7 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -301,6 +301,77 @@ static inline void mmc_host_clk_sysfs_init(struct mmc_host 
*host)
 
 #endif
 
+void mmc_retune_enable(struct mmc_host *host, unsigned int period)
+{
+   host-can_retune = 1;
+   if (period)
+   mod_timer(host-retune_timer, jiffies + period * HZ);
+}
+EXPORT_SYMBOL(mmc_retune_enable);
+
+void mmc_retune_disable(struct mmc_host *host)
+{
+   host-can_retune = 0;
+   del_timer_sync(host-retune_timer);
+   host-retune_now = 0;
+   host-need_retune = 0;
+}
+EXPORT_SYMBOL(mmc_retune_disable);
+
+void mmc_retune_timer_stop(struct mmc_host *host)
+{
+   del_timer_sync(host-retune_timer);
+}
+EXPORT_SYMBOL(mmc_retune_timer_stop);
+
+void mmc_retune_hold(struct mmc_host *host)
+{
+   if (!host-hold_retune)
+   host-retune_now = 1;
+   host-hold_retune += 1;
+}
+EXPORT_SYMBOL(mmc_retune_hold);
+
+void mmc_retune_release(struct mmc_host *host)
+{
+   if (host-hold_retune)
+   host-hold_retune -= 1;
+   else
+   WARN_ON(1);
+}
+EXPORT_SYMBOL(mmc_retune_release);
+
+int mmc_retune(struct mmc_host *host)
+{
+   int err;
+
+   if (host-retune_now)
+   host-retune_now = 0;
+   else
+   return 0;
+
+   if (!host-need_retune || host-doing_retune || !host-card)
+   return 0;
+
+   host-need_retune = 0;
+
+   host-doing_retune = 1;
+
+   err = mmc_execute_tuning(host-card);
+
+   host-doing_retune = 0;
+
+   return err;
+}
+EXPORT_SYMBOL(mmc_retune);
+
+static void mmc_retune_timer(unsigned long data)
+{
+   struct mmc_host *host = (struct mmc_host *)data;
+
+   mmc_retune_needed(host);
+}
+
 /**
  * mmc_of_parse() - parse host's device-tree node
  * @host: host whose node should be parsed.
@@ -504,6 +575,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device 
*dev)
 #ifdef CONFIG_PM
host-pm_notify.notifier_call = mmc_pm_notify;
 #endif
+   setup_timer(host-retune_timer, mmc_retune_timer, (unsigned long)host);
 
/*
 * By default, hosts do not support SGIO or large requests.
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index b5bedae..f8957eb 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -12,6 +12,7 @@
 
 #include linux/leds.h
 #include linux/mutex.h
+#include linux/timer.h
 #include linux/sched.h
 #include linux/device.h
 #include linux/fault-inject.h
@@ -321,10 +322,17 @@ struct mmc_host {
 #ifdef CONFIG_MMC_DEBUG
unsigned intremoved:1;  /* host is being removed */
 #endif
+   unsigned intcan_retune:1;   /* re-tuning can be used */
+   unsigned intdoing_retune:1; /* re-tuning in progress */
+   unsigned intretune_now:1;   /* do re-tuning at next req */
 
int rescan_disable; /* disable card detection */
int rescan_entered; /* used with nonremovable 
devices */
 
+   int need_retune;/* re-tuning is needed */
+   int hold_retune;/* hold off re-tuning */
+   struct timer_list   retune_timer;   /* for periodic re-tuning */
+
booltrigger_card_event; /* card_event necessary */
 

[PATCH V4 12/15] mmc: sdhci: Flag re-tuning is needed on CRC or End-Bit errors

2015-03-27 Thread Adrian Hunter
CRC or End-Bit errors could possibly be alleviated by
re-tuning so flag re-tuning needed in those cases.
Note this has no effect if re-tuning has not been
enabled.

Signed-off-by: Adrian Hunter adrian.hun...@intel.com
---
 drivers/mmc/host/sdhci.c | 14 +-
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index c9a34b5..e6125e9 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2308,8 +2308,10 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 
intmask, u32 *mask)
if (intmask  SDHCI_INT_TIMEOUT)
host-cmd-error = -ETIMEDOUT;
else if (intmask  (SDHCI_INT_CRC | SDHCI_INT_END_BIT |
-   SDHCI_INT_INDEX))
+   SDHCI_INT_INDEX)) {
host-cmd-error = -EILSEQ;
+   mmc_retune_needed(host-mmc);
+   }
 
if (host-cmd-error) {
tasklet_schedule(host-finish_tasklet);
@@ -2434,13 +2436,15 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 
intmask)
 
if (intmask  SDHCI_INT_DATA_TIMEOUT)
host-data-error = -ETIMEDOUT;
-   else if (intmask  SDHCI_INT_DATA_END_BIT)
+   else if (intmask  SDHCI_INT_DATA_END_BIT) {
host-data-error = -EILSEQ;
-   else if ((intmask  SDHCI_INT_DATA_CRC) 
+   mmc_retune_needed(host-mmc);
+   } else if ((intmask  SDHCI_INT_DATA_CRC) 
SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))
-   != MMC_BUS_TEST_R)
+   != MMC_BUS_TEST_R) {
host-data-error = -EILSEQ;
-   else if (intmask  SDHCI_INT_ADMA_ERROR) {
+   mmc_retune_needed(host-mmc);
+   } else if (intmask  SDHCI_INT_ADMA_ERROR) {
pr_err(%s: ADMA error\n, mmc_hostname(host-mmc));
sdhci_adma_show_error(host);
host-data-error = -EIO;
-- 
1.9.1

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


[PATCH V4 15/15] mmc: core: Don't print reset warning if reset is not supported

2015-03-27 Thread Adrian Hunter
Check the error code for EOPNOTSUPP and do not print
reset warning in that case.

Signed-off-by: Adrian Hunter adrian.hun...@intel.com
---
 drivers/mmc/core/core.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index f8ae793..595be30 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2363,7 +2363,8 @@ int mmc_hw_reset(struct mmc_host *host)
ret = host-bus_ops-reset(host);
mmc_bus_put(host);
 
-   pr_warn(%s: tried to reset card\n, mmc_hostname(host));
+   if (ret != -EOPNOTSUPP)
+   pr_warn(%s: tried to reset card\n, mmc_hostname(host));
 
return ret;
 }
-- 
1.9.1

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


[PATCH V4 13/15] mmc: block: Check re-tuning in the recovery path

2015-03-27 Thread Adrian Hunter
If re-tuning is needed, do it in the recovery path to
give recovery commands a better chance of success.

Signed-off-by: Adrian Hunter adrian.hun...@intel.com
---
 drivers/mmc/card/block.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index c69afb5..293e938 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -913,6 +913,9 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, 
struct request *req,
if (!err)
break;
 
+   /* Re-tune if needed */
+   mmc_retune_recheck(card-host);
+
prev_cmd_status_valid = false;
pr_err(%s: error %d sending status command, %sing\n,
   req-rq_disk-disk_name, err, retry ? retry : abort);
-- 
1.9.1

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


[PATCH V4 14/15] mmc: block: Retry errored data requests when re-tuning is needed

2015-03-27 Thread Adrian Hunter
Retry errored data requests when re-tuning is needed and
add a flag to struct mmc_blk_request so that the retry
is only done once.

Signed-off-by: Adrian Hunter adrian.hun...@intel.com
---
 drivers/mmc/card/block.c | 11 ++-
 drivers/mmc/card/queue.h |  1 +
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 293e938..3baf7ea 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1195,6 +1195,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
mmc_active);
struct mmc_blk_request *brq = mq_mrq-brq;
struct request *req = mq_mrq-req;
+   int need_retune = card-host-need_retune;
int ecc_err = 0, gen_err = 0;
 
/*
@@ -1262,6 +1263,12 @@ static int mmc_blk_err_check(struct mmc_card *card,
}
 
if (brq-data.error) {
+   if (need_retune  !brq-retune_retry_done) {
+   pr_info(%s: retrying because a re-tune was needed\n,
+   req-rq_disk-disk_name);
+   brq-retune_retry_done = 1;
+   return MMC_BLK_RETRY;
+   }
pr_err(%s: error %d transferring data, sector %u, nr %u, cmd 
response %#x, card status %#x\n,
   req-rq_disk-disk_name, brq-data.error,
   (unsigned)blk_rq_pos(req),
@@ -1821,7 +1828,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, 
struct request *rqc)
struct mmc_blk_data *md = mq-data;
struct mmc_card *card = md-queue.card;
struct mmc_blk_request *brq = mq-mqrq_cur-brq;
-   int ret = 1, disable_multi = 0, retry = 0, type;
+   int ret = 1, disable_multi = 0, retry = 0, type, retune_retry_done = 0;
enum mmc_blk_status status;
struct mmc_queue_req *mq_rq;
struct request *req = rqc;
@@ -1905,6 +1912,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, 
struct request *rqc)
break;
goto cmd_abort;
case MMC_BLK_RETRY:
+   retune_retry_done = brq-retune_retry_done;
if (retry++  5)
break;
/* Fall through */
@@ -1967,6 +1975,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, 
struct request *rqc)
mmc_start_req(card-host,
mq_rq-mmc_active, NULL);
}
+   mq_rq-brq.retune_retry_done = retune_retry_done;
}
} while (ret);
 
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index 5752d50..7e27915 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -12,6 +12,7 @@ struct mmc_blk_request {
struct mmc_command  cmd;
struct mmc_command  stop;
struct mmc_data data;
+   int retune_retry_done;
 };
 
 enum mmc_packed_type {
-- 
1.9.1

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


[PATCH V4 10/15] mmc: core: Add support for HS400 re-tuning

2015-03-27 Thread Adrian Hunter
HS400 re-tuning must be done in HS200 mode. Add
the ability to switch from HS400 mode to HS200
mode before re-tuning and switch back to HS400
after re-tuning.

Signed-off-by: Adrian Hunter adrian.hun...@intel.com
---
 drivers/mmc/core/core.h |  2 ++
 drivers/mmc/core/host.c | 17 ++
 drivers/mmc/core/mmc.c  | 88 +
 3 files changed, 107 insertions(+)

diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index cfba3c0..e6f2de7 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -88,6 +88,8 @@ void mmc_remove_card_debugfs(struct mmc_card *card);
 void mmc_init_context_info(struct mmc_host *host);
 
 int mmc_execute_tuning(struct mmc_card *card);
+int mmc_hs200_to_hs400(struct mmc_card *card);
+int mmc_hs400_to_hs200(struct mmc_card *card);
 
 #endif
 
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index ce0ddf7..9361312 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -343,6 +343,7 @@ EXPORT_SYMBOL(mmc_retune_release);
 
 int mmc_retune(struct mmc_host *host)
 {
+   bool return_to_hs400 = false;
int err;
 
if (host-retune_now)
@@ -357,8 +358,24 @@ int mmc_retune(struct mmc_host *host)
 
host-doing_retune = 1;
 
+   if (host-ios.timing == MMC_TIMING_MMC_HS400) {
+   err = mmc_hs400_to_hs200(host-card);
+   if (err)
+   goto out;
+
+   return_to_hs400 = true;
+
+   if (host-ops-prepare_hs400_tuning)
+   host-ops-prepare_hs400_tuning(host, host-ios);
+   }
+
err = mmc_execute_tuning(host-card);
+   if (err)
+   goto out;
 
+   if (return_to_hs400)
+   err = mmc_hs200_to_hs400(host-card);
+out:
host-doing_retune = 0;
 
return err;
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 813b02a..03577be 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1083,6 +1083,94 @@ static int mmc_select_hs400(struct mmc_card *card)
return 0;
 }
 
+int mmc_hs200_to_hs400(struct mmc_card *card)
+{
+   return mmc_select_hs400(card);
+}
+
+/* Caller must hold re-tuning */
+static int mmc_switch_status(struct mmc_card *card)
+{
+   u32 status;
+   int err;
+
+   err = mmc_send_status(card, status);
+   if (err)
+   return err;
+
+   return mmc_switch_status_error(card-host, status);
+}
+
+int mmc_hs400_to_hs200(struct mmc_card *card)
+{
+   struct mmc_host *host = card-host;
+   bool send_status = true;
+   unsigned int max_dtr;
+   int err;
+
+   if (host-caps  MMC_CAP_WAIT_WHILE_BUSY)
+   send_status = false;
+
+   /* Reduce frequency to HS */
+   max_dtr = card-ext_csd.hs_max_dtr;
+   mmc_set_clock(host, max_dtr);
+
+   /* Switch HS400 to HS DDR */
+   err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
+  EXT_CSD_TIMING_HS, card-ext_csd.generic_cmd6_time,
+  true, send_status, true);
+   if (err)
+   goto out_err;
+
+   mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
+
+   if (!send_status) {
+   err = mmc_switch_status(card);
+   if (err)
+   goto out_err;
+   }
+
+   /* Switch HS DDR to HS */
+   err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
+  EXT_CSD_BUS_WIDTH_8, card-ext_csd.generic_cmd6_time,
+  true, send_status, true);
+   if (err)
+   goto out_err;
+
+   mmc_set_timing(host, MMC_TIMING_MMC_HS);
+
+   if (!send_status) {
+   err = mmc_switch_status(card);
+   if (err)
+   goto out_err;
+   }
+
+   /* Switch HS to HS200 */
+   err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
+  EXT_CSD_TIMING_HS200,
+  card-ext_csd.generic_cmd6_time, true, send_status,
+  true);
+   if (err)
+   goto out_err;
+
+   mmc_set_timing(host, MMC_TIMING_MMC_HS200);
+
+   if (!send_status) {
+   err = mmc_switch_status(card);
+   if (err)
+   goto out_err;
+   }
+
+   mmc_set_bus_speed(card);
+
+   return 0;
+
+out_err:
+   pr_err(%s: %s failed, error %d\n, mmc_hostname(card-host),
+  __func__, err);
+   return err;
+}
+
 /*
  * For device supporting HS200 mode, the following sequence
  * should be done before executing the tuning process.
-- 
1.9.1

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


[PATCH V4 11/15] mmc: sdhci: Change to new way of doing re-tuning

2015-03-27 Thread Adrian Hunter
Make use of mmc core support for re-tuning instead
of doing it all in the sdhci driver.

This patch also changes to flag the need for re-tuning
always after runtime suspend when tuning has been used
at initialization. Previously it was only done if
the re-tuning timer was in use.

Signed-off-by: Adrian Hunter adrian.hun...@intel.com
---
 drivers/mmc/host/sdhci.c | 113 ++-
 drivers/mmc/host/sdhci.h |   3 --
 2 files changed, 14 insertions(+), 102 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index c80287a..c9a34b5 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -52,7 +52,6 @@ static void sdhci_finish_data(struct sdhci_host *);
 
 static void sdhci_finish_command(struct sdhci_host *);
 static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
-static void sdhci_tuning_timer(unsigned long data);
 static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
 static int sdhci_pre_dma_transfer(struct sdhci_host *host,
struct mmc_data *data,
@@ -254,17 +253,6 @@ static void sdhci_init(struct sdhci_host *host, int soft)
 static void sdhci_reinit(struct sdhci_host *host)
 {
sdhci_init(host, 0);
-   /*
-* Retuning stuffs are affected by different cards inserted and only
-* applicable to UHS-I cards. So reset these fields to their initial
-* value when card is removed.
-*/
-   if (host-flags  SDHCI_USING_RETUNING_TIMER) {
-   host-flags = ~SDHCI_USING_RETUNING_TIMER;
-
-   del_timer_sync(host-tuning_timer);
-   host-flags = ~SDHCI_NEEDS_RETUNING;
-   }
sdhci_enable_card_detection(host);
 }
 
@@ -1353,7 +1341,6 @@ static void sdhci_request(struct mmc_host *mmc, struct 
mmc_request *mrq)
struct sdhci_host *host;
int present;
unsigned long flags;
-   u32 tuning_opcode;
 
host = mmc_priv(mmc);
 
@@ -1387,39 +1374,6 @@ static void sdhci_request(struct mmc_host *mmc, struct 
mmc_request *mrq)
host-mrq-cmd-error = -ENOMEDIUM;
tasklet_schedule(host-finish_tasklet);
} else {
-   u32 present_state;
-
-   present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
-   /*
-* Check if the re-tuning timer has already expired and there
-* is no on-going data transfer and DAT0 is not busy. If so,
-* we need to execute tuning procedure before sending command.
-*/
-   if ((host-flags  SDHCI_NEEDS_RETUNING) 
-   !(present_state  (SDHCI_DOING_WRITE | SDHCI_DOING_READ)) 
-   (present_state  SDHCI_DATA_0_LVL_MASK)) {
-   if (mmc-card) {
-   /* eMMC uses cmd21 but sd and sdio use cmd19 */
-   tuning_opcode =
-   mmc-card-type == MMC_TYPE_MMC ?
-   MMC_SEND_TUNING_BLOCK_HS200 :
-   MMC_SEND_TUNING_BLOCK;
-
-   /* Here we need to set the host-mrq to NULL,
-* in case the pending finish_tasklet
-* finishes it incorrectly.
-*/
-   host-mrq = NULL;
-
-   spin_unlock_irqrestore(host-lock, flags);
-   sdhci_execute_tuning(mmc, tuning_opcode);
-   spin_lock_irqsave(host-lock, flags);
-
-   /* Restore original mmc_request structure */
-   host-mrq = mrq;
-   }
-   }
-
if (mrq-sbc  !(host-flags  SDHCI_AUTO_CMD23))
sdhci_send_command(host, mrq-sbc);
else
@@ -2065,23 +2019,19 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, 
u32 opcode)
}
 
 out:
-   host-flags = ~SDHCI_NEEDS_RETUNING;
-
if (tuning_count) {
-   host-flags |= SDHCI_USING_RETUNING_TIMER;
-   mod_timer(host-tuning_timer, jiffies + tuning_count * HZ);
+   /*
+* In case tuning fails, host controllers which support
+* re-tuning can try tuning again at a later time, when the
+* re-tuning timer expires.  So for these controllers, we
+* return 0. Since there might be other controllers who do not
+* have this capability, we return error for them.
+*/
+   err = 0;
}
 
-   /*
-* In case tuning fails, host controllers which support re-tuning can
-* try tuning again at a later time, when the re-tuning timer expires.
-* So for these controllers, we return 0. Since there 

[PATCH V4 05/15] mmc: core: Hold re-tuning during switch commands

2015-03-27 Thread Adrian Hunter
Hold re-tuning during switch commands to prevent
it from conflicting with the busy state or the CMD13
verification.

Signed-off-by: Adrian Hunter adrian.hun...@intel.com
---
 drivers/mmc/core/mmc_ops.c | 29 +++--
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 0ea042d..f67b0fd 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -474,6 +474,8 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, 
u8 value,
u32 status = 0;
bool use_r1b_resp = use_busy_signal;
 
+   mmc_retune_hold(host);
+
/*
 * If the cmd timeout and the max_busy_timeout of the host are both
 * specified, let's validate them. A failure means we need to prevent
@@ -506,11 +508,11 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, 
u8 value,
 
err = mmc_wait_for_cmd(host, cmd, MMC_CMD_RETRIES);
if (err)
-   return err;
+   goto out;
 
/* No need to check card status in case of unblocking command */
if (!use_busy_signal)
-   return 0;
+   goto out;
 
/*
 * CRC errors shall only be ignored in cases were CMD13 is used to poll
@@ -529,7 +531,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, 
u8 value,
if (send_status) {
err = __mmc_send_status(card, status, ignore_crc);
if (err)
-   return err;
+   goto out;
}
if ((host-caps  MMC_CAP_WAIT_WHILE_BUSY)  use_r1b_resp)
break;
@@ -543,29 +545,36 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, 
u8 value,
 */
if (!send_status) {
mmc_delay(timeout_ms);
-   return 0;
+   goto out;
}
 
/* Timeout if the device never leaves the program state. */
if (time_after(jiffies, timeout)) {
pr_err(%s: Card stuck in programming state! %s\n,
mmc_hostname(host), __func__);
-   return -ETIMEDOUT;
+   err = -ETIMEDOUT;
+   goto out;
}
} while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
 
if (mmc_host_is_spi(host)) {
-   if (status  R1_SPI_ILLEGAL_COMMAND)
-   return -EBADMSG;
+   if (status  R1_SPI_ILLEGAL_COMMAND) {
+   err = -EBADMSG;
+   goto out;
+   }
} else {
if (status  0xFDFFA000)
pr_warn(%s: unexpected status %#x after switch\n,
mmc_hostname(host), status);
-   if (status  R1_SWITCH_ERROR)
-   return -EBADMSG;
+   if (status  R1_SWITCH_ERROR) {
+   err = -EBADMSG;
+   goto out;
+   }
}
+out:
+   mmc_retune_release(host);
 
-   return 0;
+   return err;
 }
 EXPORT_SYMBOL_GPL(__mmc_switch);
 
-- 
1.9.1

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


[PATCH V4 06/15] mmc: core: Hold re-tuning during erase commands

2015-03-27 Thread Adrian Hunter
Hold re-tuning during erase commands to prevent
it from conflicting with the sequence of commands.

Signed-off-by: Adrian Hunter adrian.hun...@intel.com
---
 drivers/mmc/core/core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 16881c8..d4e3248 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1993,6 +1993,8 @@ static int mmc_do_erase(struct mmc_card *card, unsigned 
int from,
unsigned long timeout;
int err;
 
+   mmc_retune_hold(card-host);
+
/*
 * qty is used to calculate the erase timeout which depends on how many
 * erase groups (or allocation units in SD terminology) are affected.
@@ -2096,6 +2098,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned 
int from,
} while (!(cmd.resp[0]  R1_READY_FOR_DATA) ||
 (R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG));
 out:
+   mmc_retune_release(card-host);
return err;
 }
 
-- 
1.9.1

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


Re: [PATCH] mmc: core: Enable runtime PM management of host devices

2015-03-27 Thread NeilBrown
On Fri, 27 Mar 2015 12:15:15 +0100 Ulf Hansson ulf.hans...@linaro.org wrote:

 Currently those host drivers which have deployed runtime PM, deals with
 the runtime PM reference counting entirely by themselves.
 
 Since host drivers don't know when the core will send the next request
 through some of the host_ops callbacks, they need to handle runtime PM
 get/put between each an every request.
 
 In quite many cases this has some negative effects, since it leads to a
 high frequency of scheduled runtime PM suspend operations. That due to
 the runtime PM reference count will normally reach zero in-between
 every request.

I don't understand why this is a problem.
All the drivers use put_autosuspend, so the suspend doesn't happen for
(typically) 50ms, so the actually suspend won't happen if there is a sequence
of requests.

Is it just the scheduling of a suspend - even without the suspend happening -
that is causing problems?  If so, maybe the runtime_pm code needs optimising?

Thanks,

NeilBrown


 
 We can decrease that frequency, by enabling the core to deal with
 runtime PM reference counting of the host device. Since the core often
 knows that it will send a seqeunce of requests, it makes sense for it
 to keep a runtime PM reference count during these periods.
 
 More exactly, let's increase the runtime PM reference count by invoking
 pm_runtime_get_sync() from __mmc_claim_host(). Restore that action by
 invoking pm_runtime_mark_last_busy() and pm_runtime_put_autosuspend()
 in mmc_release_host(). In this way a runtime PM reference count will be
 kept during the complete cycle of a claim - release host.
 
 Signed-off-by: Ulf Hansson ulf.hans...@linaro.org
 ---
  drivers/mmc/core/core.c | 10 +-
  1 file changed, 9 insertions(+), 1 deletion(-)
 
 diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
 index 709ada9..c296bc0 100644
 --- a/drivers/mmc/core/core.c
 +++ b/drivers/mmc/core/core.c
 @@ -897,6 +897,7 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t 
 *abort)
   DECLARE_WAITQUEUE(wait, current);
   unsigned long flags;
   int stop;
 + bool pm = false;
  
   might_sleep();
  
 @@ -916,13 +917,18 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t 
 *abort)
   host-claimed = 1;
   host-claimer = current;
   host-claim_cnt += 1;
 + if (host-claim_cnt == 1)
 + pm = true;
   } else
   wake_up(host-wq);
   spin_unlock_irqrestore(host-lock, flags);
   remove_wait_queue(host-wq, wait);
 +
 + if (pm)
 + pm_runtime_get_sync(mmc_dev(host));
 +
   return stop;
  }
 -
  EXPORT_SYMBOL(__mmc_claim_host);
  
  /**
 @@ -947,6 +953,8 @@ void mmc_release_host(struct mmc_host *host)
   host-claimer = NULL;
   spin_unlock_irqrestore(host-lock, flags);
   wake_up(host-wq);
 + pm_runtime_mark_last_busy(mmc_dev(host));
 + pm_runtime_put_autosuspend(mmc_dev(host));
   }
  }
  EXPORT_SYMBOL(mmc_release_host);



pgpbWcjhZ4W_L.pgp
Description: OpenPGP digital signature


[PATCH 1/2] mmc: esdhc: add eSDHC little-endian mode support

2015-03-27 Thread Yangbo Lu
This patch is to support little-endian mode for ARM
eSDHC that has the same IP block with PowerPC but has
different endian mode.

Signed-off-by: Yangbo Lu yangbo...@freescale.com
---
 drivers/mmc/host/sdhci-of-esdhc.c | 105 +-
 drivers/mmc/host/sdhci-of-hlwd.c  |  12 ++---
 drivers/mmc/host/sdhci-pltfm.c|  12 -
 drivers/mmc/host/sdhci-pltfm.h|  74 +++
 4 files changed, 139 insertions(+), 64 deletions(-)

diff --git a/drivers/mmc/host/sdhci-of-esdhc.c 
b/drivers/mmc/host/sdhci-of-esdhc.c
index 17fe02e..a39b789 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -28,7 +28,7 @@ static u32 esdhc_readl(struct sdhci_host *host, int reg)
 {
u32 ret;
 
-   ret = in_be32(host-ioaddr + reg);
+   ret = sdhci_32bs_readl(host, reg);
/*
 * The bit of ADMA flag in eSDHC is not compatible with standard
 * SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is
@@ -40,7 +40,7 @@ static u32 esdhc_readl(struct sdhci_host *host, int reg)
 * the verdor version number, oxFE is SDHCI_HOST_VERSION.
 */
if ((reg == SDHCI_CAPABILITIES)  (ret  SDHCI_CAN_DO_ADMA1)) {
-   u32 tmp = in_be32(host-ioaddr + SDHCI_SLOT_INT_STATUS);
+   u32 tmp = sdhci_32bs_readl(host, SDHCI_SLOT_INT_STATUS);
tmp = (tmp  SDHCI_VENDOR_VER_MASK)  SDHCI_VENDOR_VER_SHIFT;
if (tmp  VENDOR_V_22)
ret |= SDHCI_CAN_DO_ADMA2;
@@ -56,9 +56,9 @@ static u16 esdhc_readw(struct sdhci_host *host, int reg)
int shift = (reg  0x2) * 8;
 
if (unlikely(reg == SDHCI_HOST_VERSION))
-   ret = in_be32(host-ioaddr + base)  0x;
+   ret = sdhci_32bs_readl(host, base)  0x;
else
-   ret = (in_be32(host-ioaddr + base)  shift)  0x;
+   ret = (sdhci_32bs_readl(host, base)  shift)  0x;
return ret;
 }
 
@@ -66,7 +66,10 @@ static u8 esdhc_readb(struct sdhci_host *host, int reg)
 {
int base = reg  ~0x3;
int shift = (reg  0x3) * 8;
-   u8 ret = (in_be32(host-ioaddr + base)  shift)  0xff;
+   u32 ret;
+   u8 val;
+
+   ret = sdhci_32bs_readl(host, base);
 
/*
 * DMA select locates at offset 0x28 in SD specification, but on
@@ -75,16 +78,18 @@ static u8 esdhc_readb(struct sdhci_host *host, int reg)
if (reg == SDHCI_HOST_CONTROL) {
u32 dma_bits;
 
-   dma_bits = in_be32(host-ioaddr + reg);
/* DMA select is 22,23 bits in Protocol Control Register */
-   dma_bits = (dma_bits  5)  SDHCI_CTRL_DMA_MASK;
+   dma_bits = (ret  5)  SDHCI_CTRL_DMA_MASK;
 
/* fixup the result */
ret = ~SDHCI_CTRL_DMA_MASK;
ret |= dma_bits;
+   val = (ret  0xff);
}
 
-   return ret;
+   val = (ret  shift)  0xff;
+
+   return val;
 }
 
 static void esdhc_writel(struct sdhci_host *host, u32 val, int reg)
@@ -96,11 +101,28 @@ static void esdhc_writel(struct sdhci_host *host, u32 val, 
int reg)
 */
if (reg == SDHCI_INT_ENABLE)
val |= SDHCI_INT_BLK_GAP;
-   sdhci_be32bs_writel(host, val, reg);
+   sdhci_32bs_writel(host, val, reg);
 }
 
 static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
 {
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+   switch (reg) {
+   case SDHCI_TRANSFER_MODE:
+   /*
+* Postpone this write, we must do it together with a
+* command write that is down below.
+*/
+   pltfm_host-xfer_mode_shadow = val;
+   return;
+   case SDHCI_COMMAND:
+   sdhci_32bs_writel(host, val  16 |
+ pltfm_host-xfer_mode_shadow,
+ SDHCI_TRANSFER_MODE);
+   return;
+   }
+
if (reg == SDHCI_BLOCK_SIZE) {
/*
 * Two last DMA bits are reserved, and first one is used for
@@ -109,7 +131,7 @@ static void esdhc_writew(struct sdhci_host *host, u16 val, 
int reg)
 */
val = ~SDHCI_MAKE_BLKSZ(0x7, 0);
}
-   sdhci_be32bs_writew(host, val, reg);
+   sdhci_clrsetbits(host, 0x, val, reg);
 }
 
 static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
@@ -130,16 +152,16 @@ static void esdhc_writeb(struct sdhci_host *host, u8 val, 
int reg)
 
/* DMA select is 22,23 bits in Protocol Control Register */
dma_bits = (val  SDHCI_CTRL_DMA_MASK)  5;
-   clrsetbits_be32(host-ioaddr + reg , SDHCI_CTRL_DMA_MASK  5,
-   dma_bits);
+   sdhci_clrsetbits(host, SDHCI_CTRL_DMA_MASK  5, dma_bits,
+SDHCI_HOST_CONTROL);
val = 

[PATCH 2/2] mmc: esdhc: add eMMC DDR mode support

2015-03-27 Thread Yangbo Lu
Add eMMC DDR mode support for Freescale SDHC adapter card.
The u-boot should provide device tree properties 'adapter-type'
and 'periperal-frequency' for this feature, if not, the card
would choose other mode instead of DDR.

Signed-off-by: Yangbo Lu yangbo...@freescale.com
---
 drivers/mmc/host/sdhci-esdhc.h|  24 +++
 drivers/mmc/host/sdhci-of-esdhc.c | 132 --
 2 files changed, 152 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
index 3497cfa..a6f887e 100644
--- a/drivers/mmc/host/sdhci-esdhc.h
+++ b/drivers/mmc/host/sdhci-esdhc.h
@@ -27,10 +27,32 @@
 #define ESDHC_CLOCK_MASK   0xfff0
 #define ESDHC_PREDIV_SHIFT 8
 #define ESDHC_DIVIDER_SHIFT4
+#define ESDHC_CLOCK_CRDEN  0x0008
 #define ESDHC_CLOCK_PEREN  0x0004
 #define ESDHC_CLOCK_HCKEN  0x0002
 #define ESDHC_CLOCK_IPGEN  0x0001
 
+#define ESDHCI_PRESENT_STATE   0x24
+#define ESDHC_CLK_STABLE   0x0008
+
+#define ESDHC_CAPABILITIES_1   0x114
+#define ESDHC_MODE_MASK0x0007
+#define ESDHC_MODE_DDR50_SEL   0xfffc
+#define ESDHC_MODE_DDR50   0x0004
+
+#define ESDHC_CLOCK_CONTROL0x144
+#define ESDHC_CLKLPBK_EXTPIN   0x8000
+#define ESDHC_CMDCLK_SHIFTED   0x8000
+
+/* SDHC Adapter Card Type */
+#define ESDHC_ADAPTER_TYPE_EMMC45   0x1/* eMMC Card Rev4.5 */
+#define ESDHC_ADAPTER_TYPE_SDMMC_LEGACY 0x2/* SD/MMC Legacy Card */
+#define ESDHC_ADAPTER_TYPE_EMMC44   0x3/* eMMC Card Rev4.4 */
+#define ESDHC_ADAPTER_TYPE_RSV  0x4/* Reserved */
+#define ESDHC_ADAPTER_TYPE_MMC  0x5/* MMC Card */
+#define ESDHC_ADAPTER_TYPE_SD   0x6/* SD Card Rev2.0 Rev3.0 */
+#define ESDHC_NO_ADAPTER0x7/* No Card is Present*/
+
 /* pltfm-specific */
 #define ESDHC_HOST_CONTROL_LE  0x20
 
@@ -44,6 +66,8 @@
 /* OF-specific */
 #define ESDHC_DMA_SYSCTL   0x40c
 #define ESDHC_DMA_SNOOP0x0040
+#define ESDHC_FLUSH_ASYNC_FIFO  0x0004
+#define ESDHC_USE_PERIPHERAL_CLK0x0008
 
 #define ESDHC_HOST_CONTROL_RES 0x05
 
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c 
b/drivers/mmc/host/sdhci-of-esdhc.c
index a39b789..c5d0547 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -24,11 +24,30 @@
 
 #define VENDOR_V_220x12
 #define VENDOR_V_230x13
+
+static u32 adapter_type;
+static bool peripheral_clk_available;
+
 static u32 esdhc_readl(struct sdhci_host *host, int reg)
 {
u32 ret;
 
-   ret = sdhci_32bs_readl(host, reg);
+   if (reg == SDHCI_CAPABILITIES_1) {
+   ret = sdhci_32bs_readl(host, ESDHC_CAPABILITIES_1);
+   switch (adapter_type) {
+   case ESDHC_ADAPTER_TYPE_EMMC44:
+   if (ret  ESDHC_MODE_DDR50) {
+   ret = ESDHC_MODE_DDR50_SEL;
+   /* enable 1/8V DDR capable */
+   host-mmc-caps |= MMC_CAP_1_8V_DDR;
+   } else
+   ret = ~ESDHC_MODE_MASK;
+   break;
+   default:
+   ret = ~ESDHC_MODE_MASK;
+   }
+   } else
+   ret = sdhci_32bs_readl(host, reg);
/*
 * The bit of ADMA flag in eSDHC is not compatible with standard
 * SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is
@@ -159,8 +178,11 @@ static void esdhc_writeb(struct sdhci_host *host, u8 val, 
int reg)
}
 
/* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */
-   if (reg == SDHCI_HOST_CONTROL)
+   if (reg == SDHCI_HOST_CONTROL) {
val = ~ESDHC_HOST_CONTROL_RES;
+   val = ~SDHCI_CTRL_HISPD;
+   val |= (sdhci_32bs_readl(host, reg)  SDHCI_CTRL_HISPD);
+   }
sdhci_clrsetbits(host, 0xff, val, reg);
 }
 
@@ -307,6 +329,84 @@ static void esdhc_reset(struct sdhci_host *host, u8 mask)
sdhci_writel(host, host-ier, SDHCI_SIGNAL_ENABLE);
 }
 
+static void esdhc_clock_control(struct sdhci_host *host, bool enable)
+{
+   u32 value;
+   u32 time_out;
+
+   value = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
+
+   if (enable)
+   value |= ESDHC_CLOCK_CRDEN;
+   else
+   value = ~ESDHC_CLOCK_CRDEN;
+
+   sdhci_writel(host, value, ESDHC_SYSTEM_CONTROL);
+
+   time_out = 20;
+   value = ESDHC_CLK_STABLE;
+   while (!(sdhci_readl(host, ESDHCI_PRESENT_STATE)  value)) {
+   if (time_out == 0) {
+   pr_err(%s: Internal clock never stabilised.\n,
+   mmc_hostname(host-mmc));
+   break;
+   }
+   time_out--;
+   mdelay(1);
+   }
+}
+
+static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
+{
+