linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] powerpc/powernv/pci: Add helper to check if a PE has a single vendor
@ 2017-06-21  7:18 Russell Currey
  2017-06-21  7:18 ` [PATCH 2/2] powerpc/powernv/pci: Enable 64-bit devices to access >4GB DMA space Russell Currey
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Russell Currey @ 2017-06-21  7:18 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, benh, Russell Currey

Add a helper that determines if all the devices contained in a given PE
are all from the same vendor or not.  This can be useful in determining
if it's okay to make PE-wide changes that may be suitable for some
devices but not for others.

This is used later in the series.

Signed-off-by: Russell Currey <ruscur@russell.cc>
---
 arch/powerpc/platforms/powernv/pci-ioda.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 283caf1070c9..13835ac30795 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -1718,6 +1718,31 @@ static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev
 	 */
 }
 
+static bool pnv_pci_ioda_pe_single_vendor(struct pnv_ioda_pe *pe)
+{
+	unsigned short vendor = 0;
+	struct pci_dev *pdev;
+
+	if (pe->device_count == 1)
+		return true;
+
+	/* pe->pdev should be set if it's a single device, pe->pbus if not */
+	if (!pe->pbus)
+		return true;
+
+	list_for_each_entry(pdev, &pe->pbus->devices, bus_list) {
+		if (!vendor) {
+			vendor = pdev->vendor;
+			continue;
+		}
+
+		if (pdev->vendor != vendor)
+			return false;
+	}
+
+	return true;
+}
+
 static int pnv_pci_ioda_dma_set_mask(struct pci_dev *pdev, u64 dma_mask)
 {
 	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
-- 
2.13.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/2] powerpc/powernv/pci: Enable 64-bit devices to access >4GB DMA space
  2017-06-21  7:18 [PATCH 1/2] powerpc/powernv/pci: Add helper to check if a PE has a single vendor Russell Currey
@ 2017-06-21  7:18 ` Russell Currey
  2017-06-23 16:15 ` [PATCH 1/2] powerpc/powernv/pci: Add helper to check if a PE has a single vendor kbuild test robot
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Russell Currey @ 2017-06-21  7:18 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: alistair, benh, Russell Currey

On PHB3/POWER8 systems, devices can select between two different sections
of address space, TVE#0 and TVE#1.  TVE#0 is intended for 32bit devices
that aren't capable of addressing more than 4GB.  Selecting TVE#1 instead,
with the capability of addressing over 4GB, is performed by setting bit 59
of a PCI address.

However, some devices aren't capable of addressing at least 59 bits, but
still want more than 4GB of DMA space.  In order to enable this, reconfigure
TVE#0 to be suitable for 64-bit devices by allocating memory past the
initial 4GB that is inaccessible by 64-bit DMAs.

This bypass mode is only enabled if a device requests 4GB or more of DMA
address space, if the system has PHB3 (POWER8 systems), and if the device
does not share a PE with any devices from different vendors.

Signed-off-by: Russell Currey <ruscur@russell.cc>
---
 arch/powerpc/platforms/powernv/pci-ioda.c | 93 ++++++++++++++++++++++++++++++-
 1 file changed, 91 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 13835ac30795..6adc548748d0 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -1743,6 +1743,75 @@ static bool pnv_pci_ioda_pe_single_vendor(struct pnv_ioda_pe *pe)
 	return true;
 }
 
+/*
+ * Reconfigure TVE#0 to be usable as 64-bit DMA space.
+ *
+ * The first 4GB of virtual memory for a PE is reserved for 32-bit accesses.
+ * Devices can only access more than that if bit 59 of the PCI address is set
+ * by hardware, which indicates TVE#1 should be used instead of TVE#0.
+ * Many PCI devices are not capable of addressing that many bits, and as a
+ * result are limited to the 4GB of virtual memory made available to 32-bit
+ * devices in TVE#0.
+ *
+ * In order to work around this, reconfigure TVE#0 to be suitable for 64-bit
+ * devices by configuring the virtual memory past the first 4GB inaccessible
+ * by 64-bit DMAs.  This should only be used by devices that want more than
+ * 4GB, and only on PEs that have no 32-bit devices.
+ *
+ * Currently this will only work on PHB3 (POWER8).
+ */
+static int pnv_pci_ioda_dma_64bit_bypass(struct pnv_ioda_pe *pe)
+{
+	u64 window_size, table_size, tce_count, addr;
+	struct page *table_pages;
+	u64 tce_order = 28; /* 256MB TCEs */
+	__be64 *tces;
+	s64 rc;
+
+	/*
+	 * Window size needs to be a power of two, but needs to account for
+	 * shifting memory by the 4GB offset required to skip 32bit space.
+	 */
+	window_size = roundup_pow_of_two(memory_hotplug_max() + (1ULL << 32));
+	tce_count = window_size >> tce_order;
+	table_size = tce_count << 3;
+
+	if (table_size < PAGE_SIZE)
+		table_size = PAGE_SIZE;
+
+	table_pages = alloc_pages_node(pe->phb->hose->node, GFP_KERNEL,
+				       get_order(table_size));
+	if (!table_pages)
+		goto err;
+
+	tces = page_address(table_pages);
+	if (!tces)
+		goto err;
+
+	memset(tces, 0, table_size);
+
+	for (addr = 0; addr < memory_hotplug_max(); addr += (1 << tce_order)) {
+		tces[(addr + (1ULL << 32)) >> tce_order] =
+			cpu_to_be64(addr | TCE_PCI_READ | TCE_PCI_WRITE);
+	}
+
+	rc = opal_pci_map_pe_dma_window(pe->phb->opal_id,
+					pe->pe_number,
+					/* reconfigure window 0 */
+					(pe->pe_number << 1) + 0,
+					1,
+					__pa(tces),
+					table_size,
+					1 << tce_order);
+	if (rc == OPAL_SUCCESS) {
+		pe_info(pe, "Using 64-bit DMA iommu bypass (through TVE#0)\n");
+		return 0;
+	}
+err:
+	pe_err(pe, "Error configuring 64-bit DMA bypass\n");
+	return -EIO;
+}
+
 static int pnv_pci_ioda_dma_set_mask(struct pci_dev *pdev, u64 dma_mask)
 {
 	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
@@ -1751,6 +1820,7 @@ static int pnv_pci_ioda_dma_set_mask(struct pci_dev *pdev, u64 dma_mask)
 	struct pnv_ioda_pe *pe;
 	uint64_t top;
 	bool bypass = false;
+	s64 rc;
 
 	if (WARN_ON(!pdn || pdn->pe_number == IODA_INVALID_PE))
 		return -ENODEV;;
@@ -1765,8 +1835,27 @@ static int pnv_pci_ioda_dma_set_mask(struct pci_dev *pdev, u64 dma_mask)
 		dev_info(&pdev->dev, "Using 64-bit DMA iommu bypass\n");
 		set_dma_ops(&pdev->dev, &dma_direct_ops);
 	} else {
-		dev_info(&pdev->dev, "Using 32-bit DMA via iommu\n");
-		set_dma_ops(&pdev->dev, &dma_iommu_ops);
+		/*
+		 * If the device can't set the TCE bypass bit but still wants
+		 * to access 4GB or more, on PHB3 we can reconfigure TVE#0 to
+		 * bypass the 32-bit region and be usable for 64-bit DMAs.
+		 * The device needs to be able to address all of this space.
+		 */
+		if (dma_mask >> 32 &&
+		    dma_mask > (memory_hotplug_max() + (1ULL << 32)) &&
+		    pnv_pci_ioda_pe_single_vendor(pe) &&
+		    phb->model == PNV_PHB_MODEL_PHB3) {
+			/* Configure the bypass mode */
+			rc = pnv_pci_ioda_dma_64bit_bypass(pe);
+			if (rc)
+				return rc;
+			/* 4GB offset bypasses 32-bit space */
+			set_dma_offset(&pdev->dev, (1ULL << 32));
+			set_dma_ops(&pdev->dev, &dma_direct_ops);
+		} else {
+			dev_info(&pdev->dev, "Using 32-bit DMA via iommu\n");
+			set_dma_ops(&pdev->dev, &dma_iommu_ops);
+		}
 	}
 	*pdev->dev.dma_mask = dma_mask;
 
-- 
2.13.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] powerpc/powernv/pci: Add helper to check if a PE has a single vendor
  2017-06-21  7:18 [PATCH 1/2] powerpc/powernv/pci: Add helper to check if a PE has a single vendor Russell Currey
  2017-06-21  7:18 ` [PATCH 2/2] powerpc/powernv/pci: Enable 64-bit devices to access >4GB DMA space Russell Currey
@ 2017-06-23 16:15 ` kbuild test robot
  2017-06-26  4:48 ` Alistair Popple
  2017-06-29 12:21 ` [1/2] " Michael Ellerman
  3 siblings, 0 replies; 5+ messages in thread
From: kbuild test robot @ 2017-06-23 16:15 UTC (permalink / raw)
  To: Russell Currey; +Cc: kbuild-all, linuxppc-dev, alistair, Russell Currey

[-- Attachment #1: Type: text/plain, Size: 1971 bytes --]

Hi Russell,

[auto build test ERROR on powerpc/next]
[also build test ERROR on v4.12-rc6 next-20170623]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Russell-Currey/powerpc-powernv-pci-Add-helper-to-check-if-a-PE-has-a-single-vendor/20170623-201801
base:   https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
config: powerpc-ppc64_defconfig (attached as .config)
compiler: powerpc64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=powerpc 

Note: the linux-review/Russell-Currey/powerpc-powernv-pci-Add-helper-to-check-if-a-PE-has-a-single-vendor/20170623-201801 HEAD cc13610eab0edbbdf3d9a8b29b33b1bc02859672 builds fine.
      It only hurts bisectibility.

All errors (new ones prefixed by >>):

>> arch/powerpc/platforms/powernv/pci-ioda.c:1721:13: error: 'pnv_pci_ioda_pe_single_vendor' defined but not used [-Werror=unused-function]
    static bool pnv_pci_ioda_pe_single_vendor(struct pnv_ioda_pe *pe)
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: all warnings being treated as errors

vim +/pnv_pci_ioda_pe_single_vendor +1721 arch/powerpc/platforms/powernv/pci-ioda.c

  1715		 * for physical PE: the device is already added by now;
  1716		 * for virtual PE: sysfs entries are not ready yet and
  1717		 * tce_iommu_bus_notifier will add the device to a group later.
  1718		 */
  1719	}
  1720	
> 1721	static bool pnv_pci_ioda_pe_single_vendor(struct pnv_ioda_pe *pe)
  1722	{
  1723		unsigned short vendor = 0;
  1724		struct pci_dev *pdev;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 23394 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] powerpc/powernv/pci: Add helper to check if a PE has a single vendor
  2017-06-21  7:18 [PATCH 1/2] powerpc/powernv/pci: Add helper to check if a PE has a single vendor Russell Currey
  2017-06-21  7:18 ` [PATCH 2/2] powerpc/powernv/pci: Enable 64-bit devices to access >4GB DMA space Russell Currey
  2017-06-23 16:15 ` [PATCH 1/2] powerpc/powernv/pci: Add helper to check if a PE has a single vendor kbuild test robot
@ 2017-06-26  4:48 ` Alistair Popple
  2017-06-29 12:21 ` [1/2] " Michael Ellerman
  3 siblings, 0 replies; 5+ messages in thread
From: Alistair Popple @ 2017-06-26  4:48 UTC (permalink / raw)
  To: Russell Currey; +Cc: linuxppc-dev, benh

You may need some kind of temporary unused annotation to shut the
compiler/kbuild robot up but the patch itself looks fine.

Reviewed-by: Alistair Popple <alistair@popple.id.au>

On Wed, 21 Jun 2017 05:18:03 PM Russell Currey wrote:
> Add a helper that determines if all the devices contained in a given PE
> are all from the same vendor or not.  This can be useful in determining
> if it's okay to make PE-wide changes that may be suitable for some
> devices but not for others.
> 
> This is used later in the series.
> 
> Signed-off-by: Russell Currey <ruscur@russell.cc>
> ---
>  arch/powerpc/platforms/powernv/pci-ioda.c | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
> 
> diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
> index 283caf1070c9..13835ac30795 100644
> --- a/arch/powerpc/platforms/powernv/pci-ioda.c
> +++ b/arch/powerpc/platforms/powernv/pci-ioda.c
> @@ -1718,6 +1718,31 @@ static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev
>  	 */
>  }
>  
> +static bool pnv_pci_ioda_pe_single_vendor(struct pnv_ioda_pe *pe)
> +{
> +	unsigned short vendor = 0;
> +	struct pci_dev *pdev;
> +
> +	if (pe->device_count == 1)
> +		return true;
> +
> +	/* pe->pdev should be set if it's a single device, pe->pbus if not */
> +	if (!pe->pbus)
> +		return true;
> +
> +	list_for_each_entry(pdev, &pe->pbus->devices, bus_list) {
> +		if (!vendor) {
> +			vendor = pdev->vendor;
> +			continue;
> +		}
> +
> +		if (pdev->vendor != vendor)
> +			return false;
> +	}
> +
> +	return true;
> +}
> +
>  static int pnv_pci_ioda_dma_set_mask(struct pci_dev *pdev, u64 dma_mask)
>  {
>  	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [1/2] powerpc/powernv/pci: Add helper to check if a PE has a single vendor
  2017-06-21  7:18 [PATCH 1/2] powerpc/powernv/pci: Add helper to check if a PE has a single vendor Russell Currey
                   ` (2 preceding siblings ...)
  2017-06-26  4:48 ` Alistair Popple
@ 2017-06-29 12:21 ` Michael Ellerman
  3 siblings, 0 replies; 5+ messages in thread
From: Michael Ellerman @ 2017-06-29 12:21 UTC (permalink / raw)
  To: Russell Currey, linuxppc-dev; +Cc: alistair, Russell Currey

On Wed, 2017-06-21 at 07:18:03 UTC, Russell Currey wrote:
> Add a helper that determines if all the devices contained in a given PE
> are all from the same vendor or not.  This can be useful in determining
> if it's okay to make PE-wide changes that may be suitable for some
> devices but not for others.
> 
> This is used later in the series.
> 
> Signed-off-by: Russell Currey <ruscur@russell.cc>

Series applied to powerpc next, thanks.

https://git.kernel.org/powerpc/c/a0f98629f19943fb8387a7d5fd01e6

cheers

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-06-29 12:21 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-06-21  7:18 [PATCH 1/2] powerpc/powernv/pci: Add helper to check if a PE has a single vendor Russell Currey
2017-06-21  7:18 ` [PATCH 2/2] powerpc/powernv/pci: Enable 64-bit devices to access >4GB DMA space Russell Currey
2017-06-23 16:15 ` [PATCH 1/2] powerpc/powernv/pci: Add helper to check if a PE has a single vendor kbuild test robot
2017-06-26  4:48 ` Alistair Popple
2017-06-29 12:21 ` [1/2] " Michael Ellerman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).