public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Jaehoon Chung <jh80.chung@samsung.com>
To: Doug Anderson <dianders@chromium.org>,
	Ulf Hansson <ulf.hansson@linaro.org>,
	Seungwon Jeon <tgih.jun@samsung.com>
Cc: Addy Ke <addy.ke@rock-chips.com>,
	Sonny Rao <sonnyrao@chromium.org>,
	Alim Akhtar <alim.akhtar@samsung.com>,
	Andrew Bresticker <abrestic@chromium.org>,
	chris@printf.net, linux-mmc@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH] mmc: dw_mmc: Remove old card detect infrastructure
Date: Thu, 16 Oct 2014 18:38:10 +0900	[thread overview]
Message-ID: <543F9202.8010806@samsung.com> (raw)
In-Reply-To: <543F7F91.1010609@samsung.com>

Hi, Doug.

Add one comment.

On 10/16/2014 05:19 PM, Jaehoon Chung wrote:
> Hi, Doug.
> 
> Looks good to me.
> 
> Tested-by: Jaehoon Chung <jh80.chung@samsung.com>
> with exynos3/4 series.
> 
> Need to check exynos5 with using other "card detect" mechanism.
> 
> Best Regards,
> Jaehoon Chung
> 
> On 10/15/2014 01:33 AM, Doug Anderson wrote:
>> The dw_mmc driver had a bunch of code that ran whenever a card was
>> ejected and inserted.  However, this code was old and crufty and
>> should be removed.  Some evidence that it's really not needed:
>>
>> 1. Is is supposed to be legal to use 'cd-gpio' on dw_mmc instead of
>>    using the built-in card detect mechanism.  The 'cd-gpio' code
>>    doesn't run any of the crufty old code but yet still works.
>>
>> 2. While looking at this, I realized that my old change (369ac86 mmc:
>>    dw_mmc: don't queue up a card detect at slot startup) actually
>>    castrated the old code a little bit already and nobody noticed.
>>    Specifically "last_detect_state" was left as 0 at bootup.  That
>>    means that on the first card removal none of the crufty code ran.
>>
>> 3. I can run "while true; do dd if=/dev/mmcblk1 of=/dev/null; done"
>>    while ejecting and inserting an SD Card and the world doesn't
>>    explode.
>>
>> If some of the crufty old code is actually needed, we should justify
>> it and also put it in some place where it will be run even with
>> "cd-gpio".
>>
>> Note that in my case I'm using the "cd-gpio" mechanism but for various
>> reasons the hardware triggers a dw_mmc "card detect" at bootup.  That
>> was actually causing a real bug.  The card detect workqueue was
>> running while the system was trying to enumerate the card.  The
>> "present != slot->last_detect_state" triggered and we were doing all
>> kinds of crazy stuff and messing up enumeration.  The new mechanism of
>> just asking the core to check the card is much safer and then the
>> bogus interrupt doesn't hurt.

Did you read the Card-detect Recommendation?
There is a Recommendation for Card-detect(CDT) at TRM.
We don't read the CDETECT register(0x50) anywhere. Could you share this register value after detecting?

And I think "last_detect_state" is used for "software should read card detect register and store in memory."

Best Regards,
Jaehoon Chung

>>
>> Signed-off-by: Doug Anderson <dianders@chromium.org>
>> ---
>>  drivers/mmc/host/dw_mmc.c  | 121 ++++++++-------------------------------------
>>  drivers/mmc/host/dw_mmc.h  |   2 -
>>  include/linux/mmc/dw_mmc.h |   2 -
>>  3 files changed, 20 insertions(+), 105 deletions(-)
>>
>> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
>> index 69f0cc6..6a86495 100644
>> --- a/drivers/mmc/host/dw_mmc.c
>> +++ b/drivers/mmc/host/dw_mmc.c
>> @@ -34,7 +34,6 @@
>>  #include <linux/mmc/dw_mmc.h>
>>  #include <linux/bitops.h>
>>  #include <linux/regulator/consumer.h>
>> -#include <linux/workqueue.h>
>>  #include <linux/of.h>
>>  #include <linux/of_gpio.h>
>>  #include <linux/mmc/slot-gpio.h>
>> @@ -1954,6 +1953,23 @@ static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status)
>>  	tasklet_schedule(&host->tasklet);
>>  }
>>  
>> +static void dw_mci_handle_cd(struct dw_mci *host)
>> +{
>> +	int i;
>> +
>> +	for (i = 0; i < host->num_slots; i++) {
>> +		struct dw_mci_slot *slot = host->slot[i];
>> +
>> +		if (!slot)
>> +			continue;
>> +
>> +		if (slot->mmc->ops->card_event)
>> +			slot->mmc->ops->card_event(slot->mmc);
>> +		mmc_detect_change(slot->mmc,
>> +			msecs_to_jiffies(host->pdata->detect_delay_ms));
>> +	}
>> +}
>> +
>>  static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
>>  {
>>  	struct dw_mci *host = dev_id;
>> @@ -2029,7 +2045,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
>>  
>>  		if (pending & SDMMC_INT_CD) {
>>  			mci_writel(host, RINTSTS, SDMMC_INT_CD);
>> -			queue_work(host->card_workqueue, &host->card_work);
>> +			dw_mci_handle_cd(host);
>>  		}
>>  
>>  		/* Handle SDIO Interrupts */
>> @@ -2056,88 +2072,6 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
>>  	return IRQ_HANDLED;
>>  }
>>  
>> -static void dw_mci_work_routine_card(struct work_struct *work)
>> -{
>> -	struct dw_mci *host = container_of(work, struct dw_mci, card_work);
>> -	int i;
>> -
>> -	for (i = 0; i < host->num_slots; i++) {
>> -		struct dw_mci_slot *slot = host->slot[i];
>> -		struct mmc_host *mmc = slot->mmc;
>> -		struct mmc_request *mrq;
>> -		int present;
>> -
>> -		present = dw_mci_get_cd(mmc);
>> -		while (present != slot->last_detect_state) {
>> -			dev_dbg(&slot->mmc->class_dev, "card %s\n",
>> -				present ? "inserted" : "removed");
>> -
>> -			spin_lock_bh(&host->lock);
>> -
>> -			/* Card change detected */
>> -			slot->last_detect_state = present;
>> -
>> -			/* Clean up queue if present */
>> -			mrq = slot->mrq;
>> -			if (mrq) {
>> -				if (mrq == host->mrq) {
>> -					host->data = NULL;
>> -					host->cmd = NULL;
>> -
>> -					switch (host->state) {
>> -					case STATE_IDLE:
>> -					case STATE_WAITING_CMD11_DONE:
>> -						break;
>> -					case STATE_SENDING_CMD11:
>> -					case STATE_SENDING_CMD:
>> -						mrq->cmd->error = -ENOMEDIUM;
>> -						if (!mrq->data)
>> -							break;
>> -						/* fall through */
>> -					case STATE_SENDING_DATA:
>> -						mrq->data->error = -ENOMEDIUM;
>> -						dw_mci_stop_dma(host);
>> -						break;
>> -					case STATE_DATA_BUSY:
>> -					case STATE_DATA_ERROR:
>> -						if (mrq->data->error == -EINPROGRESS)
>> -							mrq->data->error = -ENOMEDIUM;
>> -						/* fall through */
>> -					case STATE_SENDING_STOP:
>> -						if (mrq->stop)
>> -							mrq->stop->error = -ENOMEDIUM;
>> -						break;
>> -					}
>> -
>> -					dw_mci_request_end(host, mrq);
>> -				} else {
>> -					list_del(&slot->queue_node);
>> -					mrq->cmd->error = -ENOMEDIUM;
>> -					if (mrq->data)
>> -						mrq->data->error = -ENOMEDIUM;
>> -					if (mrq->stop)
>> -						mrq->stop->error = -ENOMEDIUM;
>> -
>> -					spin_unlock(&host->lock);
>> -					mmc_request_done(slot->mmc, mrq);
>> -					spin_lock(&host->lock);
>> -				}
>> -			}
>> -
>> -			/* Power down slot */
>> -			if (present == 0)
>> -				dw_mci_reset(host);
>> -
>> -			spin_unlock_bh(&host->lock);
>> -
>> -			present = dw_mci_get_cd(mmc);
>> -		}
>> -
>> -		mmc_detect_change(slot->mmc,
>> -			msecs_to_jiffies(host->pdata->detect_delay_ms));
>> -	}
>> -}
>> -
>>  #ifdef CONFIG_OF
>>  /* given a slot id, find out the device node representing that slot */
>>  static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot)
>> @@ -2289,9 +2223,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
>>  	dw_mci_init_debugfs(slot);
>>  #endif
>>  
>> -	/* Card initially undetected */
>> -	slot->last_detect_state = 0;
>> -
>>  	return 0;
>>  
>>  err_host_allocated:
>> @@ -2672,17 +2603,10 @@ int dw_mci_probe(struct dw_mci *host)
>>  		host->data_offset = DATA_240A_OFFSET;
>>  
>>  	tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host);
>> -	host->card_workqueue = alloc_workqueue("dw-mci-card",
>> -			WQ_MEM_RECLAIM, 1);
>> -	if (!host->card_workqueue) {
>> -		ret = -ENOMEM;
>> -		goto err_dmaunmap;
>> -	}
>> -	INIT_WORK(&host->card_work, dw_mci_work_routine_card);
>>  	ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt,
>>  			       host->irq_flags, "dw-mci", host);
>>  	if (ret)
>> -		goto err_workqueue;
>> +		goto err_dmaunmap;
>>  
>>  	if (host->pdata->num_slots)
>>  		host->num_slots = host->pdata->num_slots;
>> @@ -2718,7 +2642,7 @@ int dw_mci_probe(struct dw_mci *host)
>>  	} else {
>>  		dev_dbg(host->dev, "attempted to initialize %d slots, "
>>  					"but failed on all\n", host->num_slots);
>> -		goto err_workqueue;
>> +		goto err_dmaunmap;
>>  	}
>>  
>>  	if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
>> @@ -2726,9 +2650,6 @@ int dw_mci_probe(struct dw_mci *host)
>>  
>>  	return 0;
>>  
>> -err_workqueue:
>> -	destroy_workqueue(host->card_workqueue);
>> -
>>  err_dmaunmap:
>>  	if (host->use_dma && host->dma_ops->exit)
>>  		host->dma_ops->exit(host);
>> @@ -2762,8 +2683,6 @@ void dw_mci_remove(struct dw_mci *host)
>>  	mci_writel(host, CLKENA, 0);
>>  	mci_writel(host, CLKSRC, 0);
>>  
>> -	destroy_workqueue(host->card_workqueue);
>> -
>>  	if (host->use_dma && host->dma_ops->exit)
>>  		host->dma_ops->exit(host);
>>  
>> diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
>> index 01b99e8..71d4995 100644
>> --- a/drivers/mmc/host/dw_mmc.h
>> +++ b/drivers/mmc/host/dw_mmc.h
>> @@ -214,7 +214,6 @@ extern int dw_mci_resume(struct dw_mci *host);
>>   *	with CONFIG_MMC_CLKGATE.
>>   * @flags: Random state bits associated with the slot.
>>   * @id: Number of this slot.
>> - * @last_detect_state: Most recently observed card detect state.
>>   */
>>  struct dw_mci_slot {
>>  	struct mmc_host		*mmc;
>> @@ -234,7 +233,6 @@ struct dw_mci_slot {
>>  #define DW_MMC_CARD_PRESENT	0
>>  #define DW_MMC_CARD_NEED_INIT	1
>>  	int			id;
>> -	int			last_detect_state;
>>  };
>>  
>>  struct dw_mci_tuning_data {
>> diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
>> index 0013669..69d0814 100644
>> --- a/include/linux/mmc/dw_mmc.h
>> +++ b/include/linux/mmc/dw_mmc.h
>> @@ -135,7 +135,6 @@ struct dw_mci {
>>  	struct mmc_command	stop_abort;
>>  	unsigned int		prev_blksz;
>>  	unsigned char		timing;
>> -	struct workqueue_struct	*card_workqueue;
>>  
>>  	/* DMA interface members*/
>>  	int			use_dma;
>> @@ -154,7 +153,6 @@ struct dw_mci {
>>  	u32			stop_cmdr;
>>  	u32			dir_status;
>>  	struct tasklet_struct	tasklet;
>> -	struct work_struct	card_work;
>>  	unsigned long		pending_events;
>>  	unsigned long		completed_events;
>>  	enum dw_mci_state	state;
>>
> 


  reply	other threads:[~2014-10-16  9:38 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-14 16:33 [PATCH] mmc: dw_mmc: Remove old card detect infrastructure Doug Anderson
2014-10-16  8:19 ` Jaehoon Chung
2014-10-16  9:38   ` Jaehoon Chung [this message]
2014-10-16 16:05     ` Doug Anderson
2014-10-16 12:57 ` Alim Akhtar
2014-10-16 16:10   ` Doug Anderson
2014-10-17 12:44     ` Alim Akhtar
2014-10-20  3:23       ` Jaehoon Chung
2014-10-22 16:36         ` Doug Anderson
2014-10-23  1:13           ` Jaehoon Chung
2014-10-23 12:43           ` Alim Akhtar
2014-10-27 15:42 ` Ulf Hansson

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=543F9202.8010806@samsung.com \
    --to=jh80.chung@samsung.com \
    --cc=abrestic@chromium.org \
    --cc=addy.ke@rock-chips.com \
    --cc=alim.akhtar@samsung.com \
    --cc=chris@printf.net \
    --cc=dianders@chromium.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=sonnyrao@chromium.org \
    --cc=tgih.jun@samsung.com \
    --cc=ulf.hansson@linaro.org \
    /path/to/YOUR_REPLY

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

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