From: "Ian Munsie" <imunsie@au1.ibm.com>
To: Michael Ellerman <mpe@ellerman.id.au>,
Michael Neuling <mikey@neuling.org>,
Frederic Barrat <fbarrat@linux.vnet.ibm.com>,
Andrew Donnellan <andrew.donnellan@au1.ibm.com>,
linuxppc-dev@lists.ozlabs.org, Huy Nguyen <huyn@mellanox.com>
Cc: Ian Munsie <imunsie@au1.ibm.com>
Subject: [PATCH 06/14] powerpc/powernv: Add support for the cxl kernel api on the real phb
Date: Mon, 4 Jul 2016 23:22:04 +1000 [thread overview]
Message-ID: <1467638532-9250-7-git-send-email-imunsie@au.ibm.com> (raw)
In-Reply-To: <1467638532-9250-1-git-send-email-imunsie@au.ibm.com>
From: Ian Munsie <imunsie@au1.ibm.com>
This adds support for the peer model of the cxl kernel api to the
PowerNV PHB, and exports APIs to enable the mode, check if a PCI device
is attached to a PHB in this mode, and to set and get the peer AFU for
this mode.
The cxl driver will enable this mode for supported cards by calling
pnv_cxl_enable_phb_kernel_api(). This will set a flag in the PHB to note
that this mode is enabled, and switch out it's controller_ops for the
cxl version.
The cxl version of the controller_ops struct implements it's own
versions of the enable_device_hook and release_device to handle
refcounting on the peer AFU and to allocate a default context for the
device.
Once enabled, the cxl kernel API may not be disabled on a PHB. Currently
there is no safe way to disable cxl mode short of a reboot, so until
that changes there is no reason to support the disable path.
Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
---
arch/powerpc/include/asm/pnv-pci.h | 7 ++
arch/powerpc/platforms/powernv/pci-cxl.c | 112 ++++++++++++++++++++++++++++++
arch/powerpc/platforms/powernv/pci-ioda.c | 22 +++++-
arch/powerpc/platforms/powernv/pci.h | 16 +++++
4 files changed, 154 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/pnv-pci.h b/arch/powerpc/include/asm/pnv-pci.h
index 791db1b..c47097f 100644
--- a/arch/powerpc/include/asm/pnv-pci.h
+++ b/arch/powerpc/include/asm/pnv-pci.h
@@ -38,6 +38,13 @@ int pnv_cxl_alloc_hwirq_ranges(struct cxl_irq_ranges *irqs,
struct pci_dev *dev, int num);
void pnv_cxl_release_hwirq_ranges(struct cxl_irq_ranges *irqs,
struct pci_dev *dev);
+
+/* Support for the cxl kernel api on the real PHB (instead of vPHB) */
+int pnv_cxl_enable_phb_kernel_api(struct pci_controller *hose, bool enable);
+bool pnv_pci_on_cxl_phb(struct pci_dev *dev);
+struct cxl_afu *pnv_cxl_phb_to_afu(struct pci_controller *hose);
+void pnv_cxl_phb_set_peer_afu(struct pci_dev *dev, struct cxl_afu *afu);
+
#endif
#endif
diff --git a/arch/powerpc/platforms/powernv/pci-cxl.c b/arch/powerpc/platforms/powernv/pci-cxl.c
index ea8171f..2f386f5 100644
--- a/arch/powerpc/platforms/powernv/pci-cxl.c
+++ b/arch/powerpc/platforms/powernv/pci-cxl.c
@@ -7,8 +7,11 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/module.h>
+#include <asm/pci-bridge.h>
#include <asm/pnv-pci.h>
#include <asm/opal.h>
+#include <misc/cxl.h>
#include "pci.h"
@@ -161,3 +164,112 @@ int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq,
return 0;
}
EXPORT_SYMBOL(pnv_cxl_ioda_msi_setup);
+
+/*
+ * Sets flags and switches the controller ops to enable the cxl kernel api.
+ * Original the cxl kernel API operated on a virtual PHB, but certain cards
+ * such as the Mellanox CX4 use a peer model instead and for these cards the
+ * cxl kernel api will operate on the real PHB.
+ */
+int pnv_cxl_enable_phb_kernel_api(struct pci_controller *hose, bool enable)
+{
+ struct pnv_phb *phb = hose->private_data;
+ struct module *cxl_module;
+
+ if (!enable) {
+ /*
+ * Once cxl mode is enabled on the PHB, there is currently no
+ * known safe method to disable it again, and trying risks a
+ * checkstop. If we can find a way to safely disable cxl mode
+ * in the future we can revisit this, but for now the only sane
+ * thing to do is to refuse to disable cxl mode:
+ */
+ return -EPERM;
+ }
+
+ /*
+ * Hold a reference to the cxl module since several PHB operations now
+ * depend on it, and it would be insane to allow it to be removed so
+ * long as we are in this mode (and since we can't safely disable this
+ * mode once enabled...).
+ */
+ mutex_lock(&module_mutex);
+ cxl_module = find_module("cxl");
+ if (cxl_module)
+ __module_get(cxl_module);
+ mutex_unlock(&module_mutex);
+ if (!cxl_module)
+ return -ENODEV;
+
+ phb->flags |= PNV_PHB_FLAG_CXL;
+ hose->controller_ops = pnv_cxl_cx4_ioda_controller_ops;
+
+ return 0;
+}
+EXPORT_SYMBOL(pnv_cxl_enable_phb_kernel_api);
+
+bool pnv_pci_on_cxl_phb(struct pci_dev *dev)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ struct pnv_phb *phb = hose->private_data;
+
+ return !!(phb->flags & PNV_PHB_FLAG_CXL);
+}
+EXPORT_SYMBOL(pnv_pci_on_cxl_phb);
+
+struct cxl_afu *pnv_cxl_phb_to_afu(struct pci_controller *hose)
+{
+ struct pnv_phb *phb = hose->private_data;
+
+ return (struct cxl_afu *)phb->cxl_afu;
+}
+EXPORT_SYMBOL_GPL(pnv_cxl_phb_to_afu);
+
+void pnv_cxl_phb_set_peer_afu(struct pci_dev *dev, struct cxl_afu *afu)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ struct pnv_phb *phb = hose->private_data;
+
+ phb->cxl_afu = afu;
+}
+EXPORT_SYMBOL_GPL(pnv_cxl_phb_set_peer_afu);
+
+bool pnv_cxl_enable_device_hook(struct pci_dev *dev)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ struct pnv_phb *phb = hose->private_data;
+ struct cxl_afu *afu = phb->cxl_afu;
+
+ if (!pnv_pci_enable_device_hook(dev))
+ return false;
+
+ /* No special handling for cxl function: */
+ if (PCI_FUNC(dev->devfn) == 0)
+ return true;
+
+ if (!afu) {
+ dev_WARN(&dev->dev, "Attempted to enable function > 0 on CXL PHB without a peer AFU\n");
+ return false;
+ }
+
+ dev_info(&dev->dev, "Enabling function on CXL enabled PHB with peer AFU\n");
+
+ /* Make sure the peer AFU can't go away while this device is active */
+ cxl_afu_get(afu);
+
+ return cxl_pci_associate_default_context(dev, afu);
+}
+
+void pnv_cxl_disable_device(struct pci_dev *dev)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ struct pnv_phb *phb = hose->private_data;
+ struct cxl_afu *afu = phb->cxl_afu;
+
+ /* No special handling for cxl function: */
+ if (PCI_FUNC(dev->devfn) == 0)
+ return;
+
+ cxl_pci_disable_device(dev);
+ cxl_afu_put(afu);
+}
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index e0d8103..467085f 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -3222,7 +3222,7 @@ static resource_size_t pnv_pci_iov_resource_alignment(struct pci_dev *pdev,
/* Prevent enabling devices for which we couldn't properly
* assign a PE
*/
-static bool pnv_pci_enable_device_hook(struct pci_dev *dev)
+bool pnv_pci_enable_device_hook(struct pci_dev *dev)
{
struct pci_controller *hose = pci_bus_to_host(dev->bus);
struct pnv_phb *phb = hose->private_data;
@@ -3396,7 +3396,7 @@ static void pnv_ioda_release_pe(struct pnv_ioda_pe *pe)
pnv_ioda_free_pe(pe);
}
-static void pnv_pci_release_device(struct pci_dev *pdev)
+void pnv_pci_release_device(struct pci_dev *pdev)
{
struct pci_controller *hose = pci_bus_to_host(pdev->bus);
struct pnv_phb *phb = hose->private_data;
@@ -3423,7 +3423,7 @@ static void pnv_pci_ioda_shutdown(struct pci_controller *hose)
OPAL_ASSERT_RESET);
}
-static const struct pci_controller_ops pnv_pci_ioda_controller_ops = {
+const struct pci_controller_ops pnv_pci_ioda_controller_ops = {
.dma_dev_setup = pnv_pci_dma_dev_setup,
.dma_bus_setup = pnv_pci_dma_bus_setup,
#ifdef CONFIG_PCI_MSI
@@ -3461,6 +3461,22 @@ static const struct pci_controller_ops pnv_npu_ioda_controller_ops = {
.shutdown = pnv_pci_ioda_shutdown,
};
+#ifdef CONFIG_CXL_BASE
+const struct pci_controller_ops pnv_cxl_cx4_ioda_controller_ops = {
+ .dma_dev_setup = pnv_pci_dma_dev_setup,
+ .dma_bus_setup = pnv_pci_dma_bus_setup,
+ .enable_device_hook = pnv_cxl_enable_device_hook,
+ .disable_device = pnv_cxl_disable_device,
+ .release_device = pnv_pci_release_device,
+ .window_alignment = pnv_pci_window_alignment,
+ .setup_bridge = pnv_pci_setup_bridge,
+ .reset_secondary_bus = pnv_pci_reset_secondary_bus,
+ .dma_set_mask = pnv_pci_ioda_dma_set_mask,
+ .dma_get_required_mask = pnv_pci_ioda_dma_get_required_mask,
+ .shutdown = pnv_pci_ioda_shutdown,
+};
+#endif
+
static void __init pnv_pci_init_ioda_phb(struct device_node *np,
u64 hub_id, int ioda_type)
{
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index 49c2997..4d003dc 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -76,6 +76,7 @@ struct pnv_ioda_pe {
};
#define PNV_PHB_FLAG_EEH (1 << 0)
+#define PNV_PHB_FLAG_CXL (1 << 1) /* Real PHB supporting the cxl kernel API */
struct pnv_phb {
struct pci_controller *hose;
@@ -177,6 +178,9 @@ struct pnv_phb {
struct OpalIoP7IOCErrorData hub_diag;
} diag;
+#ifdef CONFIG_CXL_BASE
+ struct cxl_afu *cxl_afu;
+#endif
};
extern struct pci_ops pnv_pci_ops;
@@ -218,6 +222,8 @@ extern int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type);
extern void pnv_teardown_msi_irqs(struct pci_dev *pdev);
extern struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev);
extern void pnv_set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq);
+extern bool pnv_pci_enable_device_hook(struct pci_dev *dev);
+extern void pnv_pci_release_device(struct pci_dev *pdev);
extern void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level,
const char *fmt, ...);
@@ -238,4 +244,14 @@ extern long pnv_npu_unset_window(struct pnv_ioda_pe *npe, int num);
extern void pnv_npu_take_ownership(struct pnv_ioda_pe *npe);
extern void pnv_npu_release_ownership(struct pnv_ioda_pe *npe);
+
+/* cxl functions */
+extern bool pnv_cxl_enable_device_hook(struct pci_dev *dev);
+extern void pnv_cxl_disable_device(struct pci_dev *dev);
+
+
+/* phb ops (cxl switches these when enabling the kernel api on the phb) */
+extern const struct pci_controller_ops pnv_cxl_cx4_ioda_controller_ops;
+extern const struct pci_controller_ops pnv_pci_ioda_controller_ops;
+
#endif /* __POWERNV_PCI_H */
--
2.8.1
next prev parent reply other threads:[~2016-07-04 13:22 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-07-04 13:21 powerpc / cxl: Add support for the Mellanox CX4 in cxl mode Ian Munsie
2016-07-04 13:21 ` [PATCH 01/14] powerpc/powernv: Split cxl code out into a separate file Ian Munsie
2016-07-06 3:44 ` Andrew Donnellan
2016-07-06 16:27 ` Frederic Barrat
2016-07-04 13:22 ` [PATCH 02/14] cxl: Add cxl_slot_is_supported API Ian Munsie
2016-07-06 2:02 ` Andrew Donnellan
2016-07-06 16:36 ` Frederic Barrat
2016-07-04 13:22 ` [PATCH 03/14] cxl: Enable bus mastering for devices using CAPP DMA mode Ian Munsie
2016-07-06 4:04 ` Andrew Donnellan
2016-07-06 16:37 ` Frederic Barrat
2016-07-04 13:22 ` [PATCH 04/14] cxl: Move cxl_afu_get / cxl_afu_put to base Ian Munsie
2016-07-05 2:10 ` Andrew Donnellan
2016-07-06 16:45 ` Frederic Barrat
2016-07-04 13:22 ` [PATCH 05/14] cxl: Allow a default context to be associated with an external pci_dev Ian Munsie
2016-07-06 16:51 ` Frederic Barrat
2016-07-04 13:22 ` Ian Munsie [this message]
2016-07-06 17:38 ` [PATCH 06/14] powerpc/powernv: Add support for the cxl kernel api on the real phb Frederic Barrat
2016-07-07 6:28 ` Ian Munsie
2016-07-04 13:22 ` [PATCH 07/14] cxl: Add support for using the kernel API with a real PHB Ian Munsie
2016-07-06 17:39 ` Frederic Barrat
2016-07-06 18:30 ` Frederic Barrat
2016-07-07 6:32 ` Ian Munsie
2016-07-04 13:22 ` [PATCH 08/14] cxl: Add kernel APIs to get & set the max irqs per context Ian Munsie
2016-07-06 18:11 ` Frederic Barrat
2016-07-07 6:00 ` Ian Munsie
2016-07-04 13:22 ` [PATCH 09/14] cxl: Add preliminary workaround for CX4 interrupt limitation Ian Munsie
2016-07-06 18:34 ` Frederic Barrat
2016-07-04 13:22 ` [PATCH 10/14] cxl: Add support for interrupts on the Mellanox CX4 Ian Munsie
2016-07-06 18:41 ` Frederic Barrat
2016-07-07 6:03 ` Ian Munsie
2016-07-04 13:22 ` [PATCH 11/14] cxl: Workaround PE=0 hardware limitation in " Ian Munsie
2016-07-06 4:42 ` Andrew Donnellan
2016-07-06 18:42 ` Frederic Barrat
2016-07-04 13:22 ` [PATCH 12/14] PCI/hotplug: pnv_php: export symbols and move struct types needed by cxl Ian Munsie
2016-07-05 0:03 ` Gavin Shan
2016-07-05 1:08 ` Andrew Donnellan
2016-07-04 13:22 ` [PATCH 13/14] PCI/hotplug: pnv_php: handle OPAL_PCI_SLOT_OFFLINE power state Ian Munsie
2016-07-04 13:22 ` [PATCH 14/14] cxl: Add cxl_check_and_switch_mode() API to switch bi-modal cards Ian Munsie
2016-07-06 3:55 ` Andrew Donnellan
2016-07-06 18:51 ` Frederic Barrat
2016-07-07 1:18 ` Andrew Donnellan
2016-07-07 6:26 ` Ian Munsie
2016-07-07 6:44 ` Andrew Donnellan
2016-07-07 8:15 ` Andrew Donnellan
2016-07-11 9:19 ` Ian Munsie
2016-07-12 1:20 ` Andrew Donnellan
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=1467638532-9250-7-git-send-email-imunsie@au.ibm.com \
--to=imunsie@au1.ibm.com \
--cc=andrew.donnellan@au1.ibm.com \
--cc=fbarrat@linux.vnet.ibm.com \
--cc=huyn@mellanox.com \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=mikey@neuling.org \
--cc=mpe@ellerman.id.au \
/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 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).