All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mikko Vinni <mmvinni@yahoo.com>
To: Wolfram Sang <w.sang@pengutronix.de>
Cc: linux-mmc@vger.kernel.org, mikko.vinni@gmail.com
Subject: Re: [PATCH resend] sdhci: work around broken dma boundary behaviour
Date: Mon, 14 Mar 2011 02:23:05 -0700 (PDT)	[thread overview]
Message-ID: <423716.64271.qm@web161805.mail.bf1.yahoo.com> (raw)
In-Reply-To: <20110312214348.GA312@pengutronix.de>

Hi,



Wolfram Sang wrote:
> I finally found some time.

Greatly appreciated.

> > Some SD host controllers (noticed on an  integrated JMicron SD reader
> > on an HP Pavilion dv5-1250eo laptop) don't  update the dma address
> > register before signaling a dma interrupt due to  a dma boundary.
> > Detect this and update the register to the next 512KB  boundary,
> > at which the transfer presumably stopped.
> > 
> > As  long as each transfer is at most 512KB in size (on this hardware
> > the max  seems to be 65536 bytes), this fix is needed at most once
> > per  transfer.
> 
> But we can't guarantee that. Transfer could be up to 65535 *  2K.

In sdhci.c function sdhci_prepare_data there are these checks:

    /* Sanity checks */
    BUG_ON(data->blksz * data->blocks > 524288);
    BUG_ON(data->blksz > host->mmc->max_blk_size);
    BUG_ON(data->blocks > 65535);

I thought the first BUG_ON makes sure that the transfer doesn't go too big.
Then again, I might be missing something. Is 524288 not in bytes?

> 
> > Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=28462
> > 
> >  Signed-off-by: Mikko Vinni <mmvinni <at> yahoo.com>
> 
> Proper EMail  please.

Hm, @gmail.com? (cc added for further emails)


> > diff --git a/drivers/mmc/host/sdhci.c  b/drivers/mmc/host/sdhci.c
> > index a25db42..8651731 100644
> > ---  a/drivers/mmc/host/sdhci.c
> > +++ b/drivers/mmc/host/sdhci.c
> > @@  -1537,9 +1537,27 @@ static void sdhci_data_irq(struct sdhci_host *host, 
>u32  intmask)
> >           * boundaries, but  as we can't disable the feature
> >            * we need to at least restart the transfer.
> >            */
> > -         if (intmask & SDHCI_INT_DMA_END)
> >  -            sdhci_writel(host,  sdhci_readl(host, SDHCI_DMA_ADDRESS),
> > -                  SDHCI_DMA_ADDRESS);
> > +        if (intmask  & SDHCI_INT_DMA_END) {
> > +             u32 dmastart, dmanow;
> > +             dmastart =  sg_dma_address(host->data->sg);
> 
> This will only work for the first  512K, right?

True. If a transfer can cross more than one boundary, I suppose an
additional variable is needed to keep track of the current state.

> 
> > +             dmanow = sdhci_readl(host, SDHCI_DMA_ADDRESS);
> >  +            if (dmanow ==  dmastart) {
> > +                 /*
> > +                  * HW failed to increase the  address.
> > +                  * Update to the next 512KB block boundary.
> >  +                  */
> > +                 dmanow = (dmanow & ~0x7ffff) + 0x80000;
> 
> Hmm,  hardcoding these values is probably not a good idea. They should be
> dependent  on what is written to MAKE_BLKSIZE. Maybe a common define?

Sorry, implementing that goes beyond my comfort zone. I would be happy to
test patches, though.

> 
> >  +                if  (dmanow > dmastart + host->data->blksz *
> > +                              host->data->blocks) {
> >  +                     WARN_ON(1);
> > +                     dmanow =  dmastart;
> > +                 }
> 
> Did this happen?

No, but I though it brings some protection in case somebody *does*
change the boundary value without checking the code first (and happens
to be running on flawed hardware).

> 
> > +                 DBG("%s: next DMA  address forced "
> > +                     "from 0x%08x to  0x%08x\n",
> > +                     mmc_hostname(host->mmc), dmastart,  dmanow);
> > +             }
> > +             sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS);
> > +         }
> >  
> >           if (intmask & SDHCI_INT_DATA_END) {
> >               if (host->cmd)  {
> > -- 
> > 1.7.4.1
> 
> Regards,
> 
>    Wolfram
> 

Thanks

Mikko


      

  reply	other threads:[~2011-03-14  9:29 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-03-07 20:40 [PATCH resend] sdhci: work around broken dma boundary behaviour Mikko Vinni
2011-03-08 20:12 ` Chris Ball
2011-03-08 22:12   ` Wolfram Sang
2011-03-12 21:43 ` Wolfram Sang
2011-03-14  9:23   ` Mikko Vinni [this message]
2011-03-14 10:18     ` Wolfram Sang
2011-03-14 13:00       ` Mikko Vinni
2011-03-14 15:28         ` Wolfram Sang
2011-03-14 15:58           ` Mikko Vinni
2011-03-14 17:21             ` Wolfram Sang
2011-03-29  8:53               ` [RFC] mmc: sdhci: work around broken dma boundary behavior Mikko Vinni
2011-04-11 21:05                 ` Chris Ball
2011-04-12  4:56                   ` Wolfram Sang
2011-04-12 17:29                 ` Chris Ball
2011-04-13  7:04                   ` Mikko Vinni

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=423716.64271.qm@web161805.mail.bf1.yahoo.com \
    --to=mmvinni@yahoo.com \
    --cc=linux-mmc@vger.kernel.org \
    --cc=mikko.vinni@gmail.com \
    --cc=w.sang@pengutronix.de \
    /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.