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 <clomb...@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

Reply via email to