New upstream version 18.05
[deb_dpdk.git] / drivers / raw / ifpga_rawdev / base / ifpga_api.c
diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_api.c b/drivers/raw/ifpga_rawdev/base/ifpga_api.c
new file mode 100644 (file)
index 0000000..540e171
--- /dev/null
@@ -0,0 +1,294 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2018 Intel Corporation
+ */
+
+#include "ifpga_api.h"
+#include "ifpga_enumerate.h"
+#include "ifpga_feature_dev.h"
+
+#include "opae_hw_api.h"
+
+/* Accelerator APIs */
+static int ifpga_acc_get_uuid(struct opae_accelerator *acc,
+                             struct uuid *uuid)
+{
+       struct opae_bridge *br = acc->br;
+       struct ifpga_port_hw *port;
+
+       if (!br || !br->data)
+               return -EINVAL;
+
+       port = br->data;
+
+       return fpga_get_afu_uuid(port, uuid);
+}
+
+static int ifpga_acc_set_irq(struct opae_accelerator *acc,
+                            u32 start, u32 count, s32 evtfds[])
+{
+       struct ifpga_afu_info *afu_info = acc->data;
+       struct opae_bridge *br = acc->br;
+       struct ifpga_port_hw *port;
+       struct fpga_uafu_irq_set irq_set;
+
+       if (!br || !br->data)
+               return -EINVAL;
+
+       if (start >= afu_info->num_irqs || start + count > afu_info->num_irqs)
+               return -EINVAL;
+
+       port = br->data;
+
+       irq_set.start = start;
+       irq_set.count = count;
+       irq_set.evtfds = evtfds;
+
+       return ifpga_set_irq(port->parent, FEATURE_FIU_ID_PORT, port->port_id,
+                            IFPGA_PORT_FEATURE_ID_UINT, &irq_set);
+}
+
+static int ifpga_acc_get_info(struct opae_accelerator *acc,
+                             struct opae_acc_info *info)
+{
+       struct ifpga_afu_info *afu_info = acc->data;
+
+       if (!afu_info)
+               return -ENODEV;
+
+       info->num_regions = afu_info->num_regions;
+       info->num_irqs = afu_info->num_irqs;
+
+       return 0;
+}
+
+static int ifpga_acc_get_region_info(struct opae_accelerator *acc,
+                                    struct opae_acc_region_info *info)
+{
+       struct ifpga_afu_info *afu_info = acc->data;
+
+       if (!afu_info)
+               return -EINVAL;
+
+       if (info->index >= afu_info->num_regions)
+               return -EINVAL;
+
+       /* always one RW region only for AFU now */
+       info->flags = ACC_REGION_READ | ACC_REGION_WRITE | ACC_REGION_MMIO;
+       info->len = afu_info->region[info->index].len;
+       info->addr = afu_info->region[info->index].addr;
+
+       return 0;
+}
+
+static int ifpga_acc_read(struct opae_accelerator *acc, unsigned int region_idx,
+                         u64 offset, unsigned int byte, void *data)
+{
+       struct ifpga_afu_info *afu_info = acc->data;
+       struct opae_reg_region *region;
+
+       if (!afu_info)
+               return -EINVAL;
+
+       if (offset + byte <= offset)
+               return -EINVAL;
+
+       if (region_idx >= afu_info->num_regions)
+               return -EINVAL;
+
+       region = &afu_info->region[region_idx];
+       if (offset + byte > region->len)
+               return -EINVAL;
+
+       switch (byte) {
+       case 8:
+               *(u64  *)data = opae_readq(region->addr + offset);
+               break;
+       case 4:
+               *(u32 *)data = opae_readl(region->addr + offset);
+               break;
+       case 2:
+               *(u16 *)data = opae_readw(region->addr + offset);
+               break;
+       case 1:
+               *(u8 *)data = opae_readb(region->addr + offset);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int ifpga_acc_write(struct opae_accelerator *acc,
+                          unsigned int region_idx, u64 offset,
+                          unsigned int byte, void *data)
+{
+       struct ifpga_afu_info *afu_info = acc->data;
+       struct opae_reg_region *region;
+
+       if (!afu_info)
+               return -EINVAL;
+
+       if (offset + byte <= offset)
+               return -EINVAL;
+
+       if (region_idx >= afu_info->num_regions)
+               return -EINVAL;
+
+       region = &afu_info->region[region_idx];
+       if (offset + byte > region->len)
+               return -EINVAL;
+
+       /* normal mmio case */
+       switch (byte) {
+       case 8:
+               opae_writeq(*(u64 *)data, region->addr + offset);
+               break;
+       case 4:
+               opae_writel(*(u32 *)data, region->addr + offset);
+               break;
+       case 2:
+               opae_writew(*(u16 *)data, region->addr + offset);
+               break;
+       case 1:
+               opae_writeb(*(u8 *)data, region->addr + offset);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+struct opae_accelerator_ops ifpga_acc_ops = {
+       .read = ifpga_acc_read,
+       .write = ifpga_acc_write,
+       .set_irq = ifpga_acc_set_irq,
+       .get_info = ifpga_acc_get_info,
+       .get_region_info = ifpga_acc_get_region_info,
+       .get_uuid = ifpga_acc_get_uuid,
+};
+
+/* Bridge APIs */
+
+static int ifpga_br_reset(struct opae_bridge *br)
+{
+       struct ifpga_port_hw *port = br->data;
+
+       return fpga_port_reset(port);
+}
+
+struct opae_bridge_ops ifpga_br_ops = {
+       .reset = ifpga_br_reset,
+};
+
+/* Manager APIs */
+static int ifpga_mgr_flash(struct opae_manager *mgr, int id, void *buf,
+                          u32 size, u64 *status)
+{
+       struct ifpga_fme_hw *fme = mgr->data;
+       struct ifpga_hw *hw = fme->parent;
+
+       return ifpga_pr(hw, id, buf, size, status);
+}
+
+struct opae_manager_ops ifpga_mgr_ops = {
+       .flash = ifpga_mgr_flash,
+};
+
+/* Adapter APIs */
+static int ifpga_adapter_enumerate(struct opae_adapter *adapter)
+{
+       struct ifpga_hw *hw = malloc(sizeof(*hw));
+
+       if (hw) {
+               memset(hw, 0, sizeof(*hw));
+               hw->pci_data = adapter->data;
+               hw->adapter = adapter;
+               if (ifpga_bus_enumerate(hw))
+                       goto error;
+               return ifpga_bus_init(hw);
+       }
+
+error:
+       return -ENOMEM;
+}
+
+struct opae_adapter_ops ifpga_adapter_ops = {
+       .enumerate = ifpga_adapter_enumerate,
+};
+
+/**
+ *  ifpga_pr - do the partial reconfiguration for a given port device
+ *  @hw: pointer to the HW structure
+ *  @port_id: the port device id
+ *  @buffer: the buffer of the bitstream
+ *  @size: the size of the bitstream
+ *  @status: hardware status including PR error code if return -EIO.
+ *
+ *  @return
+ *   - 0: Success, partial reconfiguration finished.
+ *   - <0: Error code returned in partial reconfiguration.
+ **/
+int ifpga_pr(struct ifpga_hw *hw, u32 port_id, void *buffer, u32 size,
+            u64 *status)
+{
+       if (!is_valid_port_id(hw, port_id))
+               return -ENODEV;
+
+       return do_pr(hw, port_id, buffer, size, status);
+}
+
+int ifpga_get_prop(struct ifpga_hw *hw, u32 fiu_id, u32 port_id,
+                  struct feature_prop *prop)
+{
+       if (!hw || !prop)
+               return -EINVAL;
+
+       switch (fiu_id) {
+       case FEATURE_FIU_ID_FME:
+               return fme_get_prop(&hw->fme, prop);
+       case FEATURE_FIU_ID_PORT:
+               if (!is_valid_port_id(hw, port_id))
+                       return -ENODEV;
+               return port_get_prop(&hw->port[port_id], prop);
+       }
+
+       return -ENOENT;
+}
+
+int ifpga_set_prop(struct ifpga_hw *hw, u32 fiu_id, u32 port_id,
+                  struct feature_prop *prop)
+{
+       if (!hw || !prop)
+               return -EINVAL;
+
+       switch (fiu_id) {
+       case FEATURE_FIU_ID_FME:
+               return fme_set_prop(&hw->fme, prop);
+       case FEATURE_FIU_ID_PORT:
+               if (!is_valid_port_id(hw, port_id))
+                       return -ENODEV;
+               return port_set_prop(&hw->port[port_id], prop);
+       }
+
+       return -ENOENT;
+}
+
+int ifpga_set_irq(struct ifpga_hw *hw, u32 fiu_id, u32 port_id,
+                 u32 feature_id, void *irq_set)
+{
+       if (!hw || !irq_set)
+               return -EINVAL;
+
+       switch (fiu_id) {
+       case FEATURE_FIU_ID_FME:
+               return fme_set_irq(&hw->fme, feature_id, irq_set);
+       case FEATURE_FIU_ID_PORT:
+               if (!is_valid_port_id(hw, port_id))
+                       return -ENODEV;
+               return port_set_irq(&hw->port[port_id], feature_id, irq_set);
+       }
+
+       return -ENOENT;
+}