public inbox for linux-omap@vger.kernel.org
 help / color / mirror / Atom feed
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

      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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox