Re: [RFC v3] xhci: fix dma mask setup in xhci.c

2013-07-10 Thread Felipe Balbi
Hi,

On Tue, Jul 09, 2013 at 02:43:45PM -0700, Sarah Sharp wrote:
 On Tue, Jul 09, 2013 at 02:59:38PM +0300, Felipe Balbi wrote:
  Hi,
  
  On Mon, Jul 08, 2013 at 09:55:15PM -0700, Sarah Sharp wrote:
   Felipe, Andy, and Seb, I have a couple questions below.
   
   On Fri, Jul 05, 2013 at 08:24:56PM +0300, Xenia Ragiadakou wrote:
   Felipe, Andy, is there any chance that a platform_device dma_mask
   pointer would already be initialized by the time the probe function is
   called?  We wouldn't want to overwrite it.  Can you please check the
   xhci_plat_probe code?
  
  yes there is. At least if you're booting with Devicetree, OF core sets
  *all* dma_masks to 32-bits (erroneously IMO):
  
  $ git grep -e dma_mask drivers/of/
  drivers/of/platform.c:  dev-dev.dma_mask = dev-archdata.dma_mask;
  drivers/of/platform.c:  dev-archdata.dma_mask = 0xUL;
  drivers/of/platform.c:  dev-dev.coherent_dma_mask = DMA_BIT_MASK(32);
  drivers/of/platform.c:  dev-dev.coherent_dma_mask = ~0;
  drivers/of/platform.c:  dev-dma_mask = ~0;
 
 Ok, so that means Xenia needs to make sure to check whether the dma_mask
 pointer is non-NULL in xhci-plat.c, so that she doesn't overwrite it with
 a pointer to the coherent dma mask, correct?
 
 Or should she just overwrite the pointer because the OF core really
 shouldn't be setting the DMA mask pointer?

I think it's safe to overwrite (and perhaps even better to do so)
provided OF core enables 32-bits blindly, without checking anything
about the device.

Eventually that dma_mask setting should, likely, come via DeviceTree to
the platform_devices. Until, we can overwrite with whatever we can
discover out of the device's registers.

-- 
balbi


signature.asc
Description: Digital signature


Re: [RFC v3] xhci: fix dma mask setup in xhci.c

2013-07-09 Thread Sebastian Andrzej Siewior
On 07/09/2013 01:59 PM, Felipe Balbi wrote:

 Xenia, I'm not sure what you mean by the xHC controller and the
 host support 64 bit DMA addresses.  The xHC controller is the
 xHCI host.  Did you maybe mean If both the xHCI host and the
 system support 64-bit DMA?
 
 For non-pci platforms, the dma_mask pointer is initialized to
 point to the coherent_dma_mask since the same value will be
 assigned to both.

The DMA mask for PCI is set to 32bit by default [0]. I don't know if
the PCI spec hides a bit or two which say that it can do more than
that. I know that the ehci limits the DMA mask to 2GiB for some
vendors. A bunch of network drivers increase the mask to 64bit
depending on the card type (that means to host does not matter).

That means if xhci unconditionally supports 64bit addressing we could
init at a central point. I don't think ARM/omap5 has a restriction to
32bit only.

[0]
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/pci/probe.c#n1348

Sebastian
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC v3] xhci: fix dma mask setup in xhci.c

2013-07-09 Thread Alan Stern
On Tue, 9 Jul 2013, Felipe Balbi wrote:

 Hi,
 
 On Mon, Jul 08, 2013 at 09:55:15PM -0700, Sarah Sharp wrote:

  Xenia, I'm not sure what you mean by the xHC controller and the host 
  support
  64 bit DMA addresses.  The xHC controller is the xHCI host.  Did you maybe
  mean If both the xHCI host and the system support 64-bit DMA?

I bet Xenia meant the xHC controller and the host system.

  I'm also a bit confused as to why the platform device code could work at
  all in the current state.  Xenia's patch sets usb_hcd-self.uses_dma.
  The xHCI platform code currently doesn't set this flag.  The xHCI driver
  also doesn't set the HCD_LOCAL_MEM flag.  So what the heck happens with
  a platform device without either of those flags set in this code:
  

...

  As far as I can tell, that means the setup packet for control transfers
  doesn't actually get mapped for DMA currently.  With Xenia's patch it
  will.
 
 That's a very good finding and I don't know how come we never triggered
 it. I am sure we have OMAP5 working with that :-s

It's because of this line in usb_create_shared_hcd():

hcd-self.uses_dma = (dev-dma_mask != NULL);

As a result, HCDs shouldn't have to set this flag themselves.

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC v3] xhci: fix dma mask setup in xhci.c

2013-07-09 Thread Sarah Sharp
On Tue, Jul 09, 2013 at 02:59:38PM +0300, Felipe Balbi wrote:
 Hi,
 
 On Mon, Jul 08, 2013 at 09:55:15PM -0700, Sarah Sharp wrote:
  Felipe, Andy, and Seb, I have a couple questions below.
  
  On Fri, Jul 05, 2013 at 08:24:56PM +0300, Xenia Ragiadakou wrote:
  Felipe, Andy, is there any chance that a platform_device dma_mask
  pointer would already be initialized by the time the probe function is
  called?  We wouldn't want to overwrite it.  Can you please check the
  xhci_plat_probe code?
 
 yes there is. At least if you're booting with Devicetree, OF core sets
 *all* dma_masks to 32-bits (erroneously IMO):
 
 $ git grep -e dma_mask drivers/of/
 drivers/of/platform.c:  dev-dev.dma_mask = dev-archdata.dma_mask;
 drivers/of/platform.c:  dev-archdata.dma_mask = 0xUL;
 drivers/of/platform.c:  dev-dev.coherent_dma_mask = DMA_BIT_MASK(32);
 drivers/of/platform.c:  dev-dev.coherent_dma_mask = ~0;
 drivers/of/platform.c:  dev-dma_mask = ~0;

Ok, so that means Xenia needs to make sure to check whether the dma_mask
pointer is non-NULL in xhci-plat.c, so that she doesn't overwrite it with
a pointer to the coherent dma mask, correct?

Or should she just overwrite the pointer because the OF core really
shouldn't be setting the DMA mask pointer?

Sarah Sharp
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC v3] xhci: fix dma mask setup in xhci.c

2013-07-08 Thread Sarah Sharp
Felipe, Andy, and Seb, I have a couple questions below.

On Fri, Jul 05, 2013 at 08:24:56PM +0300, Xenia Ragiadakou wrote:
 The function dma_set_mask() tests internally whether the dma_mask pointer
 for the device is initialized and fails if the dma_mask pointer is NULL.
 On pci platforms, the initialization of the device dma_mask pointer is
 performed when pci devices are enumerated and is set to point to the
 pci_dev-dma_mask which is 0x. However, for non-pci platforms,
 the dma_mask pointer remains uninitialized and dma_set_mask() will fail.
 
 Also, a call to dma_set_mask() does not set the device coherent_dma_mask.
 Since the xhci-hcd driver calls dma_alloc_coherent() and dma_pool_alloc()
 to allocate consistent DMA memory blocks, the coherent DMA address mask
 has to be set explicitly, otherwise the DMA mapping interface will return
 by default DMA addresses which are 32-bit addressable.
 
 This patch removes the dma_mask setup code from xhci_gen_setup() and places
 it in xhci_pci_setup() and xhci_plat_setup(). The dma_mask setup must be
 done before the call to xhci_gen_setup() which allocates and maps to dma
 addresses the xhci-hcd buffers.
 
 For pci platforms, the dma_mask and coherent_dma_mask are set by default
 to 32bit DMA addresses. If both the xHC controller and the host support
 64bit DMA addresses, the device dma_mask and coherent_dma_mask will be
 set to 64bits.

Xenia, I'm not sure what you mean by the xHC controller and the host support
64 bit DMA addresses.  The xHC controller is the xHCI host.  Did you maybe
mean If both the xHCI host and the system support 64-bit DMA?

 For non-pci platforms, the dma_mask pointer is initialized to point to
 the coherent_dma_mask since the same value will be assigned to both.

Felipe, Andy, is there any chance that a platform_device dma_mask
pointer would already be initialized by the time the probe function is
called?  We wouldn't want to overwrite it.  Can you please check the
xhci_plat_probe code?

I'm also a bit confused as to why the platform device code could work at
all in the current state.  Xenia's patch sets usb_hcd-self.uses_dma.
The xHCI platform code currently doesn't set this flag.  The xHCI driver
also doesn't set the HCD_LOCAL_MEM flag.  So what the heck happens with
a platform device without either of those flags set in this code:

int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
gfp_t mem_flags)
{
enum dma_data_direction dir;
int ret = 0;

/* Map the URB's buffers for DMA access.
 * Lower level HCD code should use *_dma exclusively,
 * unless it uses pio or talks to another transport,
 * or uses the provided scatter gather list for bulk.
 */

if (usb_endpoint_xfer_control(urb-ep-desc)) {
if (hcd-self.uses_pio_for_control)
return ret;
if (hcd-self.uses_dma) {
urb-setup_dma = dma_map_single(
hcd-self.controller,
urb-setup_packet,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
if (dma_mapping_error(hcd-self.controller,
urb-setup_dma))
return -EAGAIN;
urb-transfer_flags |= URB_SETUP_MAP_SINGLE;
} else if (hcd-driver-flags  HCD_LOCAL_MEM) {
ret = hcd_alloc_coherent(
urb-dev-bus, mem_flags,
urb-setup_dma,
(void **)urb-setup_packet,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
if (ret)
return ret;
urb-transfer_flags |= URB_SETUP_MAP_LOCAL;
}
}

As far as I can tell, that means the setup packet for control transfers
doesn't actually get mapped for DMA currently.  With Xenia's patch it
will.

Does that mean xHCI platform devices have just been broken all this
time?  Has this code been tested at all?

 If dma_set_mask() succeeds, for a given bitmask, it is guaranteed that
 the given bitmask is also supported for consistent DMA mappings.
 That is the reason why this patch does not add checks when setting the
 coherent_dma_mask.
 
 Signed-off-by: Xenia Ragiadakou burzalod...@gmail.com
 ---
 
 Differences from version 1 and 2:
 
 The dma_mask setup code was removed from the xhci_gen_setup()
 function defined in xhci.c and was placed in xhci_pci_setup(),
 defined in xhci-pci.c, and in xhci_plat_setup(), defined in
 xhci-plat.c. The dma mask setup code has to be called after
 the mapping of host controller registers and before 

[RFC v3] xhci: fix dma mask setup in xhci.c

2013-07-05 Thread Xenia Ragiadakou
The function dma_set_mask() tests internally whether the dma_mask pointer
for the device is initialized and fails if the dma_mask pointer is NULL.
On pci platforms, the initialization of the device dma_mask pointer is
performed when pci devices are enumerated and is set to point to the
pci_dev-dma_mask which is 0x. However, for non-pci platforms,
the dma_mask pointer remains uninitialized and dma_set_mask() will fail.

Also, a call to dma_set_mask() does not set the device coherent_dma_mask.
Since the xhci-hcd driver calls dma_alloc_coherent() and dma_pool_alloc()
to allocate consistent DMA memory blocks, the coherent DMA address mask
has to be set explicitly, otherwise the DMA mapping interface will return
by default DMA addresses which are 32-bit addressable.

This patch removes the dma_mask setup code from xhci_gen_setup() and places
it in xhci_pci_setup() and xhci_plat_setup(). The dma_mask setup must be
done before the call to xhci_gen_setup() which allocates and maps to dma
addresses the xhci-hcd buffers.

For pci platforms, the dma_mask and coherent_dma_mask are set by default
to 32bit DMA addresses. If both the xHC controller and the host support
64bit DMA addresses, the device dma_mask and coherent_dma_mask will be
set to 64bits.

For non-pci platforms, the dma_mask pointer is initialized to point to
the coherent_dma_mask since the same value will be assigned to both.

If dma_set_mask() succeeds, for a given bitmask, it is guaranteed that
the given bitmask is also supported for consistent DMA mappings.
That is the reason why this patch does not add checks when setting the
coherent_dma_mask.

Signed-off-by: Xenia Ragiadakou burzalod...@gmail.com
---

Differences from version 1 and 2:

The dma_mask setup code was removed from the xhci_gen_setup()
function defined in xhci.c and was placed in xhci_pci_setup(),
defined in xhci-pci.c, and in xhci_plat_setup(), defined in
xhci-plat.c. The dma mask setup code has to be called after
the mapping of host controller registers and before the
allocation of xhci memory buffers, so it was placed in the
driver's 'reset' callback function before the call to
xhci_gen_setup().

Initialization of the dma_mask pointer was added for non-pci
platforms, following a remark made by Andy Shevchenco.

 drivers/usb/host/xhci-pci.c  | 19 ++-
 drivers/usb/host/xhci-plat.c | 26 ++
 drivers/usb/host/xhci.c  | 17 -
 3 files changed, 44 insertions(+), 18 deletions(-)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index cc24e39..dff5a22 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -122,9 +122,26 @@ static void xhci_pci_quirks(struct device *dev, struct 
xhci_hcd *xhci)
 static int xhci_pci_setup(struct usb_hcd *hcd)
 {
struct xhci_hcd *xhci;
-   struct pci_dev  *pdev = to_pci_dev(hcd-self.controller);
+   struct pci_dev  *pdev;
+   struct device   *dev;
int retval;
 
+   dev = hcd-self.controller;
+   pdev = to_pci_dev(dev);
+
+   if (usb_hcd_is_primary_hcd(hcd)) {
+   struct xhci_cap_regs __iomem*cap_regs;
+   u32 hcc_params;
+
+   cap_regs = hcd-regs;
+   hcc_params = readl(cap_regs-hcc_params);
+   if (HCC_64BIT_ADDR(hcc_params) 
+   !dma_set_mask(dev, DMA_BIT_MASK(64))) {
+   dev_dbg(dev, Enabling 64-bit DMA addresses.\n);
+   dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
+   }
+   }
+
retval = xhci_gen_setup(hcd, xhci_pci_quirks);
if (retval)
return retval;
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 51e22bf..d718134 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -30,6 +30,32 @@ static void xhci_plat_quirks(struct device *dev, struct 
xhci_hcd *xhci)
 /* called during probe() after chip reset completes */
 static int xhci_plat_setup(struct usb_hcd *hcd)
 {
+   struct device   *dev;
+   int retval;
+
+   dev = hcd-self.controller;
+   dev-dma_mask = dev-dma_coherent_mask;
+
+   if (usb_hcd_is_primary_hcd(hcd)) {
+   struct xhci_cap_regs __iomem*cap_regs;
+   u32 hcc_params;
+
+   cap_regs = hcd-regs;
+   hcc_params = readl(cap_regs-hcc_params);
+   if (HCC_64BIT_ADDR(hcc_params) 
+   !dma_set_mask(dev, DMA_BIT_MASK(64))) {
+   dev_dbg(dev, Enabling 64-bit DMA addresses.\n);
+   } else {
+   retval = dma_set_mask(dev, DMA_BIT_MASK(32));
+   if (retval) {
+   dev-dma_mask = NULL;
+