From: Carlos Aguiar <carlos.aguiar@indt.org.br>
To: ext Trilok Soni <soni.trilok@gmail.com>
Cc: omap-linux <linux-omap-open-source@linux.omap.com>
Subject: Re: [07/17 PATCH] MMC: OMAP: Abort stuck commands.
Date: Fri, 31 Aug 2007 11:44:24 -0400 [thread overview]
Message-ID: <46D83758.6000204@indt.org.br> (raw)
In-Reply-To: <5d5443650708180147j59e5fe90v845ee10987198a13@mail.gmail.com>
ext Trilok Soni wrote:
> Hi Carlos,
>
Hi Trilok,
> On 8/18/07, Carlos Aguiar <carlos.aguiar@indt.org.br> wrote:
>
>> From: Jarkko Lavinen <jarkko.lavinen@nokia.com>
>>
>> When a card is removed while it is being accessed, a command can get
>> stuck so that no timeout or end of command interrupt ever occurs. The
>> command getting stuck is almost always CDM12, but also the other
>> commands can get stuck. Catch a stuck command with a timer and try
>> sending the initiliazation stream until the controller starts running
>> again and responds with the end of command status.
>>
>> Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
>>
>> When a card is removed while it is being accessed, a command can get stuck so
>> that no timeout or end of command interrupt ever occurs. The command getting
>> stuck is almost always CDM12, but also the other commands can get stuck. Catch
>> a stuck command with a timer and try sending the initiliazation stream until
>> the controller starts running again and responds with the end of command
>> status.
>>
>> Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
>>
>> Index: linux-omap/drivers/mmc/host/omap.c
>> ===================================================================
>> --- linux-omap.orig/drivers/mmc/host/omap.c 2007-08-16 16:02:55.000000000 -0400
>> +++ linux-omap/drivers/mmc/host/omap.c 2007-08-16 16:03:01.000000000 -0400
>> @@ -136,6 +136,9 @@ struct mmc_omap_host {
>> unsigned char bus_mode;
>> unsigned char hw_bus_mode;
>>
>> + struct work_struct cmd_abort;
>> + struct timer_list cmd_timer;
>> +
>> unsigned int sg_len;
>> int sg_idx;
>> u16 * buffer;
>> @@ -326,6 +329,8 @@ mmc_omap_start_command(struct mmc_omap_h
>> if (host->data && !(host->data->flags & MMC_DATA_WRITE))
>> cmdreg |= 1 << 15;
>>
>> + mod_timer(&host->cmd_timer, jiffies + HZ/2);
>> +
>> OMAP_MMC_WRITE(host, CTO, 200);
>> OMAP_MMC_WRITE(host, ARGL, cmd->arg & 0xffff);
>> OMAP_MMC_WRITE(host, ARGH, cmd->arg >> 16);
>> @@ -385,9 +390,37 @@ mmc_omap_xfer_done(struct mmc_omap_host
>> }
>>
>> static void
>> +mmc_omap_send_abort(struct mmc_omap_host *host)
>> +{
>> + struct mmc_omap_slot *slot = host->current_slot;
>> + unsigned int restarts, passes, timeout;
>> + u16 stat = 0;
>> +
>> + /* Sending abort takes 80 clocks. Have some extra and round up */
>> + timeout = (120*1000000 + slot->fclk_freq - 1)/slot->fclk_freq;
>> + restarts = 0;
>> + while(restarts < 10000) {
>>
>
> space before "(" please. I think this patch series is not checked
> against "checkpatch" script. Please do it and then re-post the
> patches.
>
Yeap, my bad! I'm now using checkpatch script that's very good. I found
some others corrections beyond this you mentioned. I'll report the
series with such improvements.
>
>> + OMAP_MMC_WRITE(host, STAT, 0xFFFF);
>> + OMAP_MMC_WRITE(host, CMD, (3 << 12) | (1 << 7));
>> +
>> + passes = 0;
>> + while (passes < timeout) {
>> + stat = OMAP_MMC_READ(host, STAT);
>> + if (stat & OMAP_MMC_STAT_END_OF_CMD)
>> + goto out;
>> + udelay(1);
>> + passes ++;
>> + }
>> +
>> + restarts++;
>> + }
>> +out:
>> + OMAP_MMC_WRITE(host, STAT, stat);
>> +}
>> +
>> +static void
>> mmc_omap_abort_xfer(struct mmc_omap_host *host, struct mmc_data *data)
>> {
>> - int loops;
>> u16 ie;
>>
>> if (host->dma_in_use)
>> @@ -398,16 +431,8 @@ mmc_omap_abort_xfer(struct mmc_omap_host
>>
>> ie = OMAP_MMC_READ(host, IE);
>> OMAP_MMC_WRITE(host, IE, 0);
>> - OMAP_MMC_WRITE(host, CMD, 1 << 7);
>> - loops = 0;
>> - while (!(OMAP_MMC_READ(host, STAT) & OMAP_MMC_STAT_END_OF_CMD)) {
>> - udelay(1);
>> - loops++;
>> - if (loops == 100000)
>> - break;
>> - }
>> - OMAP_MMC_WRITE(host, STAT, OMAP_MMC_STAT_END_OF_CMD);
>> OMAP_MMC_WRITE(host, IE, ie);
>> + mmc_omap_send_abort(host);
>> }
>>
>> static void
>> @@ -463,6 +488,8 @@ mmc_omap_cmd_done(struct mmc_omap_host *
>> {
>> host->cmd = NULL;
>>
>> + del_timer(&host->cmd_timer);
>> +
>> if (cmd->flags & MMC_RSP_PRESENT) {
>> if (cmd->flags & MMC_RSP_136) {
>> /* response type 2 */
>> @@ -498,6 +525,47 @@ mmc_omap_cmd_done(struct mmc_omap_host *
>> }
>> }
>>
>> +/*
>> + * Abort stuck command. Can occur when card is removed while it is being
>> + * read.
>> + */
>> +static void mmc_omap_abort_command(struct work_struct *work)
>> +{
>> + struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
>> + cmd_abort);
>> + u16 ie;
>> +
>> + ie = OMAP_MMC_READ(host, IE);
>> + OMAP_MMC_WRITE(host, IE, 0);
>> +
>> + if (!host->cmd) {
>> + OMAP_MMC_WRITE(host, IE, ie);
>> + return;
>> + }
>> +
>> + dev_dbg(mmc_dev(host->mmc), "Aborting stuck command CMD%d\n",
>> + host->cmd->opcode);
>> +
>> + if (host->data && host->dma_in_use)
>> + mmc_omap_release_dma(host, host->data, 1);
>> +
>> + host->data = NULL;
>> + host->sg_len = 0;
>> +
>> + mmc_omap_send_abort(host);
>> + host->cmd->error = MMC_ERR_TIMEOUT;
>> + mmc_omap_cmd_done(host, host->cmd);
>> + OMAP_MMC_WRITE(host, IE, ie);
>> +}
>> +
>> +static void
>> +mmc_omap_cmd_timer(unsigned long data)
>> +{
>> + struct mmc_omap_host *host = (struct mmc_omap_host *) data;
>> +
>> + schedule_work(&host->cmd_abort);
>> +}
>> +
>> /* PIO only */
>> static void
>> mmc_omap_sg_to_buf(struct mmc_omap_host *host)
>> @@ -1263,6 +1331,11 @@ static int __init mmc_omap_probe(struct
>> goto err_free_mem_region;
>> }
>>
>> + INIT_WORK(&host->cmd_abort, mmc_omap_abort_command);
>> + init_timer(&host->cmd_timer);
>> + host->cmd_timer.function = mmc_omap_cmd_timer;
>> + host->cmd_timer.data = (unsigned long) host;
>>
>
> Use setup_timer above.
>
You're completely right! Beyond this occurrence there are more two
init_timer() on omap.c file and I replace with setup_timer. I've tested
it on N800 and looks fine.
>
>> +
>> spin_lock_init(&host->dma_lock);
>> init_timer(&host->dma_timer);
>> spin_lock_init(&host->slot_lock);
>>
>> _______________________________________________
>> Linux-omap-open-source mailing list
>> Linux-omap-open-source@linux.omap.com
>> http://linux.omap.com/mailman/listinfo/linux-omap-open-source
>>
>>
>>
>
>
Thanks for the very useful hints ;)
BR,
Carlos.
--
Carlos Eduardo Aguiar
Nokia Institute of Technology - INdT
Open Source Mobile Research Center - OSMRC - Manaus
Core Team
Phone: +55 92 2126-1079
Mobile: +55 92 8127-1797
E-mail: carlos.aguiar@indt.org.br
prev parent reply other threads:[~2007-08-31 15:44 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-08-17 19:01 [07/17 PATCH] MMC: OMAP: Abort stuck commands Carlos Aguiar
2007-08-18 8:47 ` Trilok Soni
2007-08-31 15:44 ` Carlos Aguiar [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=46D83758.6000204@indt.org.br \
--to=carlos.aguiar@indt.org.br \
--cc=linux-omap-open-source@linux.omap.com \
--cc=soni.trilok@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.