* [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).