[PATCH 1/3] ocxl: Introduce implementation-specific API
christophe lombard
clombard at linux.vnet.ibm.com
Tue Oct 22 18:52:45 AEDT 2019
The backend API (in ocxl.h) lists some low-level functions whose
implementation is different on bare-metal and in a guest. Each
environment implements its own functions, and the common code uses
them through function pointers, defined in ocxl_backend_ops
A new powernv.c file is created to call the pnv_ocxl_ API for the
bare-metal environment.
Signed-off-by: Christophe Lombard <clombard at linux.vnet.ibm.com>
---
drivers/misc/ocxl/Makefile | 2 +
drivers/misc/ocxl/config.c | 7 ++-
drivers/misc/ocxl/link.c | 31 +++++------
drivers/misc/ocxl/main.c | 5 ++
drivers/misc/ocxl/ocxl_internal.h | 24 +++++++++
drivers/misc/ocxl/powernv.c | 88 +++++++++++++++++++++++++++++++
6 files changed, 138 insertions(+), 19 deletions(-)
create mode 100644 drivers/misc/ocxl/powernv.c
diff --git a/drivers/misc/ocxl/Makefile b/drivers/misc/ocxl/Makefile
index d07d1bb8e8d4..bfdaeb232b83 100644
--- a/drivers/misc/ocxl/Makefile
+++ b/drivers/misc/ocxl/Makefile
@@ -4,6 +4,8 @@ ccflags-$(CONFIG_PPC_WERROR) += -Werror
ocxl-y += main.o pci.o config.o file.o pasid.o mmio.o
ocxl-y += link.o context.o afu_irq.o sysfs.o trace.o
ocxl-y += core.o
+ocxl-$(CONFIG_PPC_POWERNV) += powernv.o
+
obj-$(CONFIG_OCXL) += ocxl.o
# For tracepoints to include our trace.h from tracepoint infrastructure:
diff --git a/drivers/misc/ocxl/config.c b/drivers/misc/ocxl/config.c
index 7ca0f6744125..981a3bcfe742 100644
--- a/drivers/misc/ocxl/config.c
+++ b/drivers/misc/ocxl/config.c
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
// Copyright 2017 IBM Corp.
#include <linux/pci.h>
-#include <asm/pnv-ocxl.h>
#include <misc/ocxl-config.h>
#include "ocxl_internal.h"
@@ -649,7 +648,7 @@ int ocxl_config_get_actag_info(struct pci_dev *dev, u16 *base, u16 *enabled,
* avoid an external driver using ocxl as a library to call
* platform-dependent code
*/
- rc = pnv_ocxl_get_actag(dev, base, enabled, supported);
+ rc = ocxl_ops->get_actag(dev, base, enabled, supported);
if (rc) {
dev_err(&dev->dev, "Can't get actag for device: %d\n", rc);
return rc;
@@ -673,7 +672,7 @@ EXPORT_SYMBOL_GPL(ocxl_config_set_afu_actag);
int ocxl_config_get_pasid_info(struct pci_dev *dev, int *count)
{
- return pnv_ocxl_get_pasid_count(dev, count);
+ return ocxl_ops->get_pasid_count(dev, count);
}
void ocxl_config_set_afu_pasid(struct pci_dev *dev, int pos, int pasid_base,
@@ -715,7 +714,7 @@ int ocxl_config_set_TL(struct pci_dev *dev, int tl_dvsec)
if (PCI_FUNC(dev->devfn) != 0)
return 0;
- return pnv_ocxl_set_TL(dev, tl_dvsec);
+ return ocxl_ops->set_tl(dev, tl_dvsec);
}
EXPORT_SYMBOL_GPL(ocxl_config_set_TL);
diff --git a/drivers/misc/ocxl/link.c b/drivers/misc/ocxl/link.c
index e936a3bd5957..9f4d164180a7 100644
--- a/drivers/misc/ocxl/link.c
+++ b/drivers/misc/ocxl/link.c
@@ -5,7 +5,6 @@
#include <linux/mm_types.h>
#include <linux/mmu_context.h>
#include <asm/copro.h>
-#include <asm/pnv-ocxl.h>
#include <misc/ocxl.h>
#include "ocxl_internal.h"
#include "trace.h"
@@ -83,7 +82,7 @@ static void ack_irq(struct ocxl_link *link, enum xsl_response r)
link->xsl_fault.dsisr,
link->xsl_fault.dar,
reg);
- pnv_ocxl_handle_fault(link->platform_data, reg);
+ ocxl_ops->ack_irq(link->platform_data, reg);
}
}
@@ -146,8 +145,8 @@ static irqreturn_t xsl_fault_handler(int irq, void *data)
int pid;
bool schedule = false;
- pnv_ocxl_get_fault_state(link->platform_data, &dsisr, &dar,
- &pe_handle, &pid);
+ ocxl_ops->get_fault_state(link->platform_data, &dsisr, &dar,
+ &pe_handle, &pid);
trace_ocxl_fault(pe_handle, dsisr, dar, -1);
/* We could be reading all null values here if the PE is being
@@ -282,8 +281,8 @@ static int alloc_link(struct pci_dev *dev, int PE_mask, struct ocxl_link **out_l
INIT_WORK(&link->xsl_fault.fault_work, xsl_fault_handler_bh);
/* platform specific hook */
- rc = pnv_ocxl_platform_setup(dev, PE_mask, &xsl_irq,
- &link->platform_data);
+ rc = ocxl_ops->platform_setup(dev, PE_mask, &xsl_irq,
+ &link->platform_data);
if (rc)
goto err_free;
@@ -298,7 +297,7 @@ static int alloc_link(struct pci_dev *dev, int PE_mask, struct ocxl_link **out_l
return 0;
err_xsl_irq:
- pnv_ocxl_platform_release(link->platform_data);
+ ocxl_ops->platform_release(link->platform_data);
err_free:
kfree(link);
return rc;
@@ -344,7 +343,7 @@ static void release_xsl(struct kref *ref)
list_del(&link->list);
/* call platform code before releasing data */
- pnv_ocxl_platform_release(link->platform_data);
+ ocxl_ops->platform_release(link->platform_data);
free_link(link);
}
@@ -378,8 +377,8 @@ int ocxl_link_add_pe(void *link_handle, int pasid, u32 pidr, u32 tidr,
pe_data->xsl_err_cb = xsl_err_cb;
pe_data->xsl_err_data = xsl_err_data;
- rc = pnv_ocxl_set_pe(link->platform_data, mfspr(SPRN_LPID),
- pasid, pidr, tidr, amr, &pe_handle);
+ rc = ocxl_ops->set_pe(link->platform_data, pasid, pidr, tidr,
+ amr, &pe_handle);
if (rc) {
kfree(pe_data);
goto unlock;
@@ -429,7 +428,9 @@ int ocxl_link_update_pe(void *link_handle, int pasid, __u16 tid)
int rc;
mutex_lock(&link->pe_lock);
- rc = pnv_ocxl_update_pe(link->platform_data, pasid, tid);
+
+ rc = ocxl_ops->update_pe(link->platform_data, pasid, tid);
+
mutex_unlock(&link->pe_lock);
return rc;
@@ -462,8 +463,8 @@ int ocxl_link_remove_pe(void *link_handle, int pasid)
*/
mutex_lock(&link->pe_lock);
- rc = pnv_ocxl_remove_pe(link->platform_data, pasid, &pid, &tid,
- &pe_handle);
+ rc = ocxl_ops->remove_pe(link->platform_data, pasid, &pid, &tid,
+ &pe_handle);
if (rc)
goto unlock;
@@ -494,7 +495,7 @@ int ocxl_link_irq_alloc(void *link_handle, int *hw_irq, u64 *trigger_addr)
if (atomic_dec_if_positive(&link->irq_available) < 0)
return -ENOSPC;
- rc = pnv_ocxl_alloc_xive_irq(&irq, &addr);
+ rc = ocxl_ops->alloc_xive_irq(link->platform_data, &irq, &addr);
if (rc) {
atomic_inc(&link->irq_available);
return rc;
@@ -510,7 +511,7 @@ void ocxl_link_free_irq(void *link_handle, int hw_irq)
{
struct ocxl_link *link = (struct ocxl_link *) link_handle;
- pnv_ocxl_free_xive_irq(hw_irq);
+ ocxl_ops->free_xive_irq(link->platform_data, hw_irq);
atomic_inc(&link->irq_available);
}
EXPORT_SYMBOL_GPL(ocxl_link_free_irq);
diff --git a/drivers/misc/ocxl/main.c b/drivers/misc/ocxl/main.c
index 7210d9e059be..95df2ba4d473 100644
--- a/drivers/misc/ocxl/main.c
+++ b/drivers/misc/ocxl/main.c
@@ -4,6 +4,8 @@
#include <linux/pci.h>
#include "ocxl_internal.h"
+const struct ocxl_backend_ops *ocxl_ops;
+
static int __init init_ocxl(void)
{
int rc = 0;
@@ -12,6 +14,9 @@ static int __init init_ocxl(void)
if (rc)
return rc;
+ if (cpu_has_feature(CPU_FTR_HVMODE))
+ ocxl_ops = &ocxl_powernv_ops;
+
rc = pci_register_driver(&ocxl_pci_driver);
if (rc) {
ocxl_file_exit();
diff --git a/drivers/misc/ocxl/ocxl_internal.h b/drivers/misc/ocxl/ocxl_internal.h
index 6e1e9cd315c0..2bdea279bdc6 100644
--- a/drivers/misc/ocxl/ocxl_internal.h
+++ b/drivers/misc/ocxl/ocxl_internal.h
@@ -82,6 +82,30 @@ struct ocxl_context {
u16 tidr; // Thread ID used for P9 wait implementation
};
+struct ocxl_backend_ops {
+ struct module *module;
+ void (*ack_irq)(void *data, u64 tfc);
+ int (*alloc_xive_irq)(void *data, u32 *irq, u64 *trigger_addr);
+ void (*free_xive_irq)(void *data, u32 irq);
+ int (*get_actag)(struct pci_dev *dev, u16 *base, u16 *enabled,
+ u16 *supported);
+ void (*get_fault_state)(void *data, u64 *dsisr, u64 *dar,
+ u64 *pe_handle, int *pid);
+ int (*get_pasid_count)(struct pci_dev *dev, int *count);
+ void (*platform_release)(void *data);
+ int (*platform_setup)(struct pci_dev *dev, int PE_mask,
+ int *hwirq, void **data);
+ int (*remove_pe)(void *data, int pasid, u32 *pid, u32 *tid,
+ int *pe_handle);
+ int (*set_pe)(void *data, int pasid, u32 pidr, u32 tidr,
+ u64 amr, int *pe_handle);
+ int (*set_tl)(struct pci_dev *dev, int tl_dvsec);
+ int (*update_pe)(void *data, int pasid, __u16 tid);
+};
+
+extern const struct ocxl_backend_ops ocxl_powernv_ops;
+extern const struct ocxl_backend_ops *ocxl_ops;
+
int ocxl_create_cdev(struct ocxl_afu *afu);
void ocxl_destroy_cdev(struct ocxl_afu *afu);
int ocxl_file_register_afu(struct ocxl_afu *afu);
diff --git a/drivers/misc/ocxl/powernv.c b/drivers/misc/ocxl/powernv.c
new file mode 100644
index 000000000000..13c98fcf7fc7
--- /dev/null
+++ b/drivers/misc/ocxl/powernv.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2018 IBM Corp.
+#include <asm/pnv-ocxl.h>
+#include <misc/ocxl-config.h>
+#include "ocxl_internal.h"
+
+static void ack_irq(void *data, u64 tfc)
+{
+ pnv_ocxl_handle_fault(data, tfc);
+}
+
+static int alloc_xive_irq(void *unused, u32 *irq,
+ u64 *trigger_addr)
+{
+ return pnv_ocxl_alloc_xive_irq(irq, trigger_addr);
+}
+
+static void free_xive_irq(void *unused, u32 irq)
+{
+ pnv_ocxl_free_xive_irq(irq);
+}
+
+static int get_actag(struct pci_dev *dev, u16 *base,
+ u16 *enabled, u16 *supported)
+{
+ return pnv_ocxl_get_actag(dev, base, enabled, supported);
+}
+
+static void get_fault_state(void *data, u64 *dsisr, u64 *dar,
+ u64 *pe_handle, int *pid)
+{
+ pnv_ocxl_get_fault_state(data, dsisr, dar, pe_handle, pid);
+}
+
+static int get_pasid_count(struct pci_dev *dev, int *count)
+{
+ return pnv_ocxl_get_pasid_count(dev, count);
+}
+
+static void platform_release(void *data)
+{
+ return pnv_ocxl_platform_release(data);
+}
+
+static int platform_setup(struct pci_dev *dev, int PE_mask, int *hwirq,
+ void **data)
+{
+ return pnv_ocxl_platform_setup(dev, PE_mask, hwirq, data);
+}
+
+static int remove_pe(void *data, int pasid, u32 *pid,
+ u32 *tid, int *pe_handle)
+{
+ return pnv_ocxl_remove_pe(data, pasid, pid, tid, pe_handle);
+}
+
+static int set_pe(void *data, int pasid, u32 pidr, u32 tidr,
+ u64 amr, int *pe_handle)
+{
+ return pnv_ocxl_set_pe(data, mfspr(SPRN_LPID), pasid,
+ pidr, tidr, amr, pe_handle);
+}
+
+static int set_tl(struct pci_dev *dev, int tl_dvsec)
+{
+ return pnv_ocxl_set_TL(dev, tl_dvsec);
+}
+
+static int update_pe(void *data, int pasid, __u16 tid)
+{
+ return pnv_ocxl_update_pe(data, pasid, tid);
+}
+
+const struct ocxl_backend_ops ocxl_powernv_ops = {
+ .module = THIS_MODULE,
+ .ack_irq = ack_irq,
+ .alloc_xive_irq = alloc_xive_irq,
+ .free_xive_irq = free_xive_irq,
+ .get_actag = get_actag,
+ .get_fault_state = get_fault_state,
+ .get_pasid_count = get_pasid_count,
+ .platform_release = platform_release,
+ .platform_setup = platform_setup,
+ .remove_pe = remove_pe,
+ .set_pe = set_pe,
+ .set_tl = set_tl,
+ .update_pe = update_pe,
+};
--
2.21.0
More information about the Linuxppc-dev
mailing list