All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arnd Bergmann <arnd@arndb.de>
To: linux-arm-kernel@lists.infradead.org
Cc: Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <Will.Deacon@arm.com>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	Ding Tianhong <dingtianhong@huawei.com>
Subject: Re: For the problem when using swiotlb
Date: Wed, 19 Nov 2014 16:56:42 +0100	[thread overview]
Message-ID: <3918100.vD6471iH9k@wuerfel> (raw)
In-Reply-To: <20141119154634.GE7156@e104818-lin.cambridge.arm.com>

On Wednesday 19 November 2014 15:46:35 Catalin Marinas wrote:
> On Wed, Nov 19, 2014 at 12:48:58PM +0000, Arnd Bergmann wrote:
> > On Wednesday 19 November 2014 11:29:10 Catalin Marinas wrote:
> > > > The driver should call 'dma_set_mask_and_coherent()' with the appropriate
> > > > dma mask, and check whether that succeeded. However, the code implementing
> > > > dma_set_mask_and_coherent on arm64 also needs to be changed to look up
> > > > the dma-ranges property (see of_dma_configure()), and check if the mask
> > > > is possible.
> > > 
> > > dma_set_mask_and_coherent() is a generic function. I think the
> > > of_dma_configure() should start with a coherent_dma_mask based on
> > > dma-ranges if given rather than defaulting to DMA_BIT_MASK(32). The
> > > comment in of_dma_configure() says that devices should set up the
> > > supported mask but it's not always up to them but the bus they are
> > > connected to.
> > > 
> > > Something like below, untested:
> > > 
> > > diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> > > index 3b64d0bf5bba..dff34883db45 100644
> > > --- a/drivers/of/platform.c
> > > +++ b/drivers/of/platform.c
> > > @@ -200,6 +200,10 @@ static void of_dma_configure(struct device *dev)
> > >         /* DMA ranges found. Calculate and set dma_pfn_offset */
> > >         dev->dma_pfn_offset = PFN_DOWN(paddr - dma_addr);
> > >         dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", dev->dma_pfn_offset);
> > > +
> > > +       /* Set the coherent_dma_mask based on the dma-ranges property */
> > > +       if (size)
> > > +               dev->coherent_dma_mask = DMA_BIT_MASK(ilog2(size));
> > >  }
> > 
> > We have discussed this in the past, and the problem with this is
> > that the actual mask depends both on the capabilities of the
> > device and the bus. In particular, if the device can only do
> > 32-bit DMA, we must not set the mask to something higher.
> 
> So is the dma-ranges property allowed to specify a size bigger than what
> the device supports?

dma-ranges is a property that describes the bus, but you can have
devices with different capabilities on the same bus. In particular
on PCI, you will have 32-bit and 64-bit masters on the same host
controller.

> > The normal rule here is that a driver that wants to do 64-bit
> > DMA must call dma_set_mask_and_coherent() with the higher mask,
> > while a device that can not access all of the 32-bit address space
> > must call dma_set_mask_and_coherent() with the smaller mask
> > before doing calling any of the other DMA interfaces.
> 
> OK, looking at the DMA API docs, it looks like the default mask is
> 32-bit and any other value should be explicitly set by the driver.
> 
> What we don't have on arm64 yet is taking dma_pfn_offset into account
> when generating the dma address (but so far I haven't seen any request
> for this from hardware vendors; it can easily be fixed). So if that's
> not the case for Ding, I'm not sure dma-ranges property would help.

You can ignore dma_pfn_offset for now, until someone needs it. What
we definitely need is the size of the range.

> > However, if the bus is not capable of addressing the entire
> > 32-bit range (as on some modern shmobile machines, or some of the
> > really old machines), we need to limit the mask here already.
> 
> Would the limiting be based on the dma-ranges size property?

Yes.

> Such information is not easily available after of_dma_configure(),
> maybe we could store it somewhere in struct device.

I don't think it's necessary. Setting the dma mask is a rare operation,
and we only need to check again if the new mask is larger than the
old one.

> Going back to original topic, the dma_supported() function on arm64
> calls swiotlb_dma_supported() which actually checks whether the swiotlb
> bounce buffer is within the dma mask. This transparent bouncing (unlike
> arm32 where it needs to be explicit) is not always optimal, though
> required for 32-bit only devices on a 64-bit system. The problem is when
> the driver is 64-bit capable but forgets to call
> dma_set_mask_and_coherent() (that's not the only question I got about
> running out of swiotlb buffers).

I think it would be nice to warn once per device that starts using the
swiotlb. Really all 32-bit DMA masters should have a proper IOMMU
attached.

	Arnd

WARNING: multiple messages have this Message-ID (diff)
From: arnd@arndb.de (Arnd Bergmann)
To: linux-arm-kernel@lists.infradead.org
Subject: For the problem when using swiotlb
Date: Wed, 19 Nov 2014 16:56:42 +0100	[thread overview]
Message-ID: <3918100.vD6471iH9k@wuerfel> (raw)
In-Reply-To: <20141119154634.GE7156@e104818-lin.cambridge.arm.com>

On Wednesday 19 November 2014 15:46:35 Catalin Marinas wrote:
> On Wed, Nov 19, 2014 at 12:48:58PM +0000, Arnd Bergmann wrote:
> > On Wednesday 19 November 2014 11:29:10 Catalin Marinas wrote:
> > > > The driver should call 'dma_set_mask_and_coherent()' with the appropriate
> > > > dma mask, and check whether that succeeded. However, the code implementing
> > > > dma_set_mask_and_coherent on arm64 also needs to be changed to look up
> > > > the dma-ranges property (see of_dma_configure()), and check if the mask
> > > > is possible.
> > > 
> > > dma_set_mask_and_coherent() is a generic function. I think the
> > > of_dma_configure() should start with a coherent_dma_mask based on
> > > dma-ranges if given rather than defaulting to DMA_BIT_MASK(32). The
> > > comment in of_dma_configure() says that devices should set up the
> > > supported mask but it's not always up to them but the bus they are
> > > connected to.
> > > 
> > > Something like below, untested:
> > > 
> > > diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> > > index 3b64d0bf5bba..dff34883db45 100644
> > > --- a/drivers/of/platform.c
> > > +++ b/drivers/of/platform.c
> > > @@ -200,6 +200,10 @@ static void of_dma_configure(struct device *dev)
> > >         /* DMA ranges found. Calculate and set dma_pfn_offset */
> > >         dev->dma_pfn_offset = PFN_DOWN(paddr - dma_addr);
> > >         dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", dev->dma_pfn_offset);
> > > +
> > > +       /* Set the coherent_dma_mask based on the dma-ranges property */
> > > +       if (size)
> > > +               dev->coherent_dma_mask = DMA_BIT_MASK(ilog2(size));
> > >  }
> > 
> > We have discussed this in the past, and the problem with this is
> > that the actual mask depends both on the capabilities of the
> > device and the bus. In particular, if the device can only do
> > 32-bit DMA, we must not set the mask to something higher.
> 
> So is the dma-ranges property allowed to specify a size bigger than what
> the device supports?

dma-ranges is a property that describes the bus, but you can have
devices with different capabilities on the same bus. In particular
on PCI, you will have 32-bit and 64-bit masters on the same host
controller.

> > The normal rule here is that a driver that wants to do 64-bit
> > DMA must call dma_set_mask_and_coherent() with the higher mask,
> > while a device that can not access all of the 32-bit address space
> > must call dma_set_mask_and_coherent() with the smaller mask
> > before doing calling any of the other DMA interfaces.
> 
> OK, looking at the DMA API docs, it looks like the default mask is
> 32-bit and any other value should be explicitly set by the driver.
> 
> What we don't have on arm64 yet is taking dma_pfn_offset into account
> when generating the dma address (but so far I haven't seen any request
> for this from hardware vendors; it can easily be fixed). So if that's
> not the case for Ding, I'm not sure dma-ranges property would help.

You can ignore dma_pfn_offset for now, until someone needs it. What
we definitely need is the size of the range.

> > However, if the bus is not capable of addressing the entire
> > 32-bit range (as on some modern shmobile machines, or some of the
> > really old machines), we need to limit the mask here already.
> 
> Would the limiting be based on the dma-ranges size property?

Yes.

> Such information is not easily available after of_dma_configure(),
> maybe we could store it somewhere in struct device.

I don't think it's necessary. Setting the dma mask is a rare operation,
and we only need to check again if the new mask is larger than the
old one.

> Going back to original topic, the dma_supported() function on arm64
> calls swiotlb_dma_supported() which actually checks whether the swiotlb
> bounce buffer is within the dma mask. This transparent bouncing (unlike
> arm32 where it needs to be explicit) is not always optimal, though
> required for 32-bit only devices on a 64-bit system. The problem is when
> the driver is 64-bit capable but forgets to call
> dma_set_mask_and_coherent() (that's not the only question I got about
> running out of swiotlb buffers).

I think it would be nice to warn once per device that starts using the
swiotlb. Really all 32-bit DMA masters should have a proper IOMMU
attached.

	Arnd

  reply	other threads:[~2014-11-19 15:56 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-17 11:56 For the problem when using swiotlb Ding Tianhong
2014-11-17 11:56 ` Ding Tianhong
2014-11-17 12:18 ` Arnd Bergmann
2014-11-17 12:18   ` Arnd Bergmann
2014-11-17 18:09   ` Catalin Marinas
2014-11-17 18:09     ` Catalin Marinas
2014-11-19  3:17     ` Ding Tianhong
2014-11-19  3:17       ` Ding Tianhong
2014-11-19  8:45       ` Arnd Bergmann
2014-11-19  8:45         ` Arnd Bergmann
2014-11-19 11:29         ` Catalin Marinas
2014-11-19 11:29           ` Catalin Marinas
2014-11-19 12:48           ` Arnd Bergmann
2014-11-19 12:48             ` Arnd Bergmann
2014-11-19 15:46             ` Catalin Marinas
2014-11-19 15:46               ` Catalin Marinas
2014-11-19 15:56               ` Arnd Bergmann [this message]
2014-11-19 15:56                 ` Arnd Bergmann
2014-11-21 11:06                 ` Catalin Marinas
2014-11-21 11:06                   ` Catalin Marinas
2014-11-21 11:26                   ` Arnd Bergmann
2014-11-21 11:26                     ` Arnd Bergmann
2014-11-21 11:36                     ` Catalin Marinas
2014-11-21 11:36                       ` Catalin Marinas
2014-11-21 12:27                       ` Arnd Bergmann
2014-11-21 12:27                         ` Arnd Bergmann
2014-11-20  2:57         ` Ding Tianhong
2014-11-20  2:57           ` Ding Tianhong
2014-11-20  7:40           ` Arnd Bergmann
2014-11-20  7:40             ` Arnd Bergmann
2014-11-20  8:34             ` Ding Tianhong
2014-11-20  8:34               ` Ding Tianhong
2014-11-20  9:02               ` Arnd Bergmann
2014-11-20  9:02                 ` Arnd Bergmann
2014-11-20  9:21                 ` Ding Tianhong
2014-11-20  9:21                   ` Ding Tianhong
2014-11-21  9:35             ` Catalin Marinas
2014-11-21  9:35               ` Catalin Marinas
2014-11-21 10:32               ` Catalin Marinas
2014-11-21 10:32                 ` Catalin Marinas
2014-11-21 12:48               ` Arnd Bergmann
2014-11-21 12:48                 ` Arnd Bergmann
2014-11-21 16:57                 ` Catalin Marinas
2014-11-21 16:57                   ` Catalin Marinas
2014-11-21 17:04                   ` Arnd Bergmann
2014-11-21 17:04                     ` Arnd Bergmann
2014-11-21 17:51                     ` Catalin Marinas
2014-11-21 17:51                       ` Catalin Marinas
2014-11-21 18:09                       ` Catalin Marinas
2014-11-21 18:09                         ` Catalin Marinas
2014-11-24 20:12                         ` Arnd Bergmann
2014-11-24 20:12                           ` Arnd Bergmann
2014-11-25 10:58                           ` Catalin Marinas
2014-11-25 10:58                             ` Catalin Marinas
2014-11-25 11:29                             ` Russell King - ARM Linux
2014-11-25 11:29                               ` Russell King - ARM Linux
2014-11-25 12:23                               ` Catalin Marinas
2014-11-25 12:23                                 ` Catalin Marinas
2014-11-27  2:36                                 ` Ding Tianhong
2014-11-27  2:36                                   ` Ding Tianhong

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=3918100.vD6471iH9k@wuerfel \
    --to=arnd@arndb.de \
    --cc=Will.Deacon@arm.com \
    --cc=catalin.marinas@arm.com \
    --cc=dingtianhong@huawei.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.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 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.