Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1613003 > unrolled thread
| Started by | Wu Hao <hao.wu@intel.com> |
|---|---|
| First post | 2017-03-30 14:20 +0200 |
| Last post | 2017-04-06 22:30 +0200 |
| Articles | 20 on this page of 61 — 8 participants |
Back to article view | Back to linux.kernel
[PATCH 00/16] Intel FPGA Device Drivers Wu Hao <hao.wu@intel.com> - 2017-03-30 14:20 +0200
[PATCH 02/16] fpga: add FPGA device framework Wu Hao <hao.wu@intel.com> - 2017-03-30 14:20 +0200
Re: [PATCH 02/16] fpga: add FPGA device framework Greg KH <greg@kroah.com> - 2017-03-31 08:10 +0200
Re: [PATCH 02/16] fpga: add FPGA device framework Wu Hao <hao.wu@intel.com> - 2017-03-31 10:00 +0200
Re: [PATCH 02/16] fpga: add FPGA device framework Greg KH <greg@kroah.com> - 2017-03-31 11:10 +0200
Re: [PATCH 02/16] fpga: add FPGA device framework Wu Hao <hao.wu@intel.com> - 2017-03-31 14:30 +0200
Re: [PATCH 02/16] fpga: add FPGA device framework matthew.gerlach@linux.intel.com - 2017-03-31 21:10 +0200
Re: [PATCH 02/16] fpga: add FPGA device framework Wu Hao <hao.wu@intel.com> - 2017-04-01 14:30 +0200
Re: [PATCH 02/16] fpga: add FPGA device framework Greg KH <greg@kroah.com> - 2017-03-31 08:20 +0200
Re: [PATCH 02/16] fpga: add FPGA device framework Wu Hao <hao.wu@intel.com> - 2017-03-31 15:40 +0200
Re: [PATCH 02/16] fpga: add FPGA device framework Greg KH <greg@kroah.com> - 2017-03-31 16:20 +0200
Re: [PATCH 02/16] fpga: add FPGA device framework Wu Hao <hao.wu@intel.com> - 2017-04-01 13:50 +0200
[PATCH 03/16] fpga: intel: add FPGA PCIe device driver Wu Hao <hao.wu@intel.com> - 2017-03-30 14:20 +0200
Re: [PATCH 03/16] fpga: intel: add FPGA PCIe device driver Moritz Fischer <mdf@kernel.org> - 2017-04-04 04:20 +0200
RE: [PATCH 03/16] fpga: intel: add FPGA PCIe device driver "Wu, Hao" <hao.wu@intel.com> - 2017-04-05 15:20 +0200
[PATCH 15/16] fpga: intel: afu: add user afu sub feature support Wu Hao <hao.wu@intel.com> - 2017-03-30 14:20 +0200
[PATCH 12/16] fpga: intel: add FPGA Accelerated Function Unit driver basic framework Wu Hao <hao.wu@intel.com> - 2017-03-30 14:20 +0200
[PATCH 09/16] fpga: intel: fme: add header sub feature support Wu Hao <hao.wu@intel.com> - 2017-03-30 14:20 +0200
[PATCH 16/16] fpga: intel: afu: add FPGA_PORT_DMA_MAP/UNMAP ioctls support Wu Hao <hao.wu@intel.com> - 2017-03-30 14:20 +0200
[PATCH 07/16] fpga: intel: add feature device infrastructure Wu Hao <hao.wu@intel.com> - 2017-03-30 14:20 +0200
[PATCH 05/16] fpga: intel: pcie: add chardev support for feature devices Wu Hao <hao.wu@intel.com> - 2017-03-30 14:20 +0200
[PATCH 04/16] fpga: intel: pcie: parse feature list and create platform device for features. Wu Hao <hao.wu@intel.com> - 2017-03-30 14:20 +0200
Re: [PATCH 04/16] fpga: intel: pcie: parse feature list and create platform device for features. Alan Tull <atull@kernel.org> - 2017-04-03 23:50 +0200
Re: [PATCH 04/16] fpga: intel: pcie: parse feature list and create platform device for features. Wu Hao <hao.wu@intel.com> - 2017-04-05 14:10 +0200
Re: [PATCH 04/16] fpga: intel: pcie: parse feature list and create platform device for features. Alan Tull <atull@kernel.org> - 2017-04-05 00:20 +0200
Re: [PATCH 04/16] fpga: intel: pcie: parse feature list and create platform device for features. Wu Hao <hao.wu@intel.com> - 2017-04-05 16:20 +0200
[PATCH 10/16] fpga: intel: fme: add FPGA_GET_API_VERSION/CHECK_EXTENSION ioctls support Wu Hao <hao.wu@intel.com> - 2017-03-30 14:20 +0200
[PATCH 14/16] fpga: intel: afu add FPGA_GET_API_VERSION/CHECK_EXTENSION ioctls support Wu Hao <hao.wu@intel.com> - 2017-03-30 14:20 +0200
[PATCH 01/16] docs: fpga: add a document for Intel FPGA driver overview Wu Hao <hao.wu@intel.com> - 2017-03-30 14:20 +0200
Re: [PATCH 01/16] docs: fpga: add a document for Intel FPGA driver overview matthew.gerlach@linux.intel.com - 2017-03-31 20:30 +0200
Re: [PATCH 01/16] docs: fpga: add a document for Intel FPGA driver overview Alan Tull <atull@kernel.org> - 2017-03-31 20:40 +0200
Re: [PATCH 01/16] docs: fpga: add a document for Intel FPGA driver overview Wu Hao <hao.wu@intel.com> - 2017-04-01 13:30 +0200
Re: [PATCH 01/16] docs: fpga: add a document for Intel FPGA driver overview Moritz Fischer <mdf@kernel.org> - 2017-04-02 16:50 +0200
Re: [PATCH 01/16] docs: fpga: add a document for Intel FPGA driver overview Alan Tull <atull@kernel.org> - 2017-04-03 22:50 +0200
Re: [PATCH 01/16] docs: fpga: add a document for Intel FPGA driver overview Wu Hao <hao.wu@intel.com> - 2017-04-04 07:30 +0200
Re: [PATCH 01/16] docs: fpga: add a document for Intel FPGA driver overview Wu Hao <hao.wu@intel.com> - 2017-04-04 07:20 +0200
[PATCH 06/16] fpga: intel: pcie: adds fpga_for_each_port callback for fme device Wu Hao <hao.wu@intel.com> - 2017-03-30 14:20 +0200
[PATCH 13/16] fpga: intel: afu: add header sub feature support Wu Hao <hao.wu@intel.com> - 2017-03-30 14:20 +0200
[PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Wu Hao <hao.wu@intel.com> - 2017-03-30 14:20 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Alan Tull <atull@kernel.org> - 2017-03-30 22:40 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Xiao Guangrong <xiaoguangrong.eric@gmail.com> - 2017-03-31 06:20 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Wu Hao <hao.wu@intel.com> - 2017-03-31 11:00 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Alan Tull <atull@kernel.org> - 2017-04-03 22:30 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Wu Hao <hao.wu@intel.com> - 2017-04-04 07:40 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Alan Tull <atull@kernel.org> - 2017-03-31 21:20 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Wu Hao <hao.wu@intel.com> - 2017-04-01 13:20 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Alan Tull <atull@kernel.org> - 2017-04-03 18:40 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Wu Hao <hao.wu@intel.com> - 2017-04-04 08:20 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Alan Tull <atull@kernel.org> - 2017-04-05 00:40 +0200
RE: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support "Wu, Hao" <hao.wu@intel.com> - 2017-04-05 13:50 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Alan Tull <atull@kernel.org> - 2017-04-05 17:30 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Alan Tull <atull@kernel.org> - 2017-04-05 17:50 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Wu Hao <hao.wu@intel.com> - 2017-04-06 13:10 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Alan Tull <atull@kernel.org> - 2017-04-06 21:30 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Wu Hao <hao.wu@intel.com> - 2017-04-07 08:10 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Alan Tull <atull@kernel.org> - 2017-04-03 23:30 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support matthew.gerlach@linux.intel.com - 2017-04-04 00:50 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Wu Hao <hao.wu@intel.com> - 2017-04-04 09:00 +0200
Re: [PATCH 11/16] fpga: intel: fme: add partial reconfiguration sub feature support Wu Hao <hao.wu@intel.com> - 2017-04-04 08:40 +0200
Re: [PATCH 00/16] Intel FPGA Device Drivers Moritz Fischer <mdf@kernel.org> - 2017-03-30 19:20 +0200
Re: [PATCH 00/16] Intel FPGA Device Drivers Jerome Glisse <jglisse@redhat.com> - 2017-04-06 22:30 +0200
Page 1 of 4 [1] 2 3 4 Next page →
| From | Wu Hao <hao.wu@intel.com> |
|---|---|
| Date | 2017-03-30 14:20 +0200 |
| Subject | [PATCH 00/16] Intel FPGA Device Drivers |
| Message-ID | <tqHdv-69w-11@gated-at.bofh.it> |
Hi All,
Here is a patch-series adding drivers for Intel FPGA devices.
The Intel FPGA driver provides interfaces for userspace applications to
configure, enumerate, open, and access FPGA accelerators on platforms
equipped with Intel(R) FPGA solutions and enables system level management
functions such as FPGA partial reconfiguration, power management and
virtualization.
This patch series only adds the basic functions for FPGA accelerators and
partial reconfiguration. Patches for more functions, e.g power management
and virtualization, will be submitted after this series gets reviewed.
Patch 1: add a document for Intel FPGA driver overview, including the HW
architecture, driver organization, device enumeration, virtualization and
opens.
Patch 2: introduce a fpga-dev class. It's used in below Intel FPGA PCIe
device driver, to represent a FPGA device on the system, and all actual
feature devices should be registered as child nodes of this container
fpga-dev device.
Patch 3-7: implement Intel FPGA PCIe device driver. It walks through the
'Device Feature List' in the PCI Bar, creates the container fpga-dev as
parent and platform devices as children for the feature devices it found.
Patch 8-11: implement Intel FPGA Management Engine (FME) driver. It's a
platform driver matching with the FME platform device created by above
PCIe driver. Sysfs and device file ioctls are exposed as user interfaces
to allow partial reconfiguration to Accelerated Function Units (AFUs) from
user space applications.
Patch 12-16: implement Intel FPGA Accelerated Function Unit (AFU) driver.
It's a platform driver matching with AFU platform device created by above
PCIe driver. It provides user interfaces to expose the AFU MMIO region,
map/unmap dma buffer, and control the port which AFU connects to.
Kang Luwei (3):
fpga: intel: add FPGA Management Engine driver basic framework
fpga: intel: fme: add header sub feature support
fpga: intel: fme: add partial reconfiguration sub feature support
Wu Hao (8):
docs: fpga: add a document for Intel FPGA driver overview
fpga: add FPGA device framework
fpga: intel: pcie: adds fpga_for_each_port callback for fme device
fpga: intel: fme: add FPGA_GET_API_VERSION/CHECK_EXTENSION ioctls
support
fpga: intel: add FPGA Accelerated Function Unit driver basic framework
fpga: intel: afu: add header sub feature support
fpga: intel: afu add FPGA_GET_API_VERSION/CHECK_EXTENSION ioctls
support
fpga: intel: afu: add FPGA_PORT_DMA_MAP/UNMAP ioctls support
Xiao Guangrong (4):
fpga: intel: pcie: parse feature list and create platform device for
features.
fpga: intel: pcie: add chardev support for feature devices
fpga: intel: add feature device infrastructure
fpga: intel: afu: add user afu sub feature support
Zhang Yi (1):
fpga: intel: add FPGA PCIe device driver
Documentation/fpga/intel-fpga.txt | 259 +++++++++
Documentation/ioctl/ioctl-number.txt | 1 +
drivers/fpga/Kconfig | 8 +
drivers/fpga/Makefile | 6 +
drivers/fpga/fpga-dev.c | 120 ++++
drivers/fpga/intel/Kconfig | 44 ++
drivers/fpga/intel/LICENSE.BSD | 24 +
drivers/fpga/intel/Makefile | 7 +
drivers/fpga/intel/afu-dma-region.c | 373 +++++++++++++
drivers/fpga/intel/afu-main.c | 471 ++++++++++++++++
drivers/fpga/intel/afu-region.c | 129 +++++
drivers/fpga/intel/afu.h | 72 +++
drivers/fpga/intel/feature-dev.c | 281 ++++++++++
drivers/fpga/intel/feature-dev.h | 499 +++++++++++++++++
drivers/fpga/intel/fme-main.c | 267 +++++++++
drivers/fpga/intel/fme-pr.c | 400 ++++++++++++++
drivers/fpga/intel/fme.h | 32 ++
drivers/fpga/intel/pcie.c | 1006 ++++++++++++++++++++++++++++++++++
include/linux/fpga/fpga-dev.h | 34 ++
include/uapi/linux/intel-fpga.h | 194 +++++++
20 files changed, 4227 insertions(+)
create mode 100644 Documentation/fpga/intel-fpga.txt
create mode 100644 drivers/fpga/fpga-dev.c
create mode 100644 drivers/fpga/intel/Kconfig
create mode 100644 drivers/fpga/intel/LICENSE.BSD
create mode 100644 drivers/fpga/intel/Makefile
create mode 100644 drivers/fpga/intel/afu-dma-region.c
create mode 100644 drivers/fpga/intel/afu-main.c
create mode 100644 drivers/fpga/intel/afu-region.c
create mode 100644 drivers/fpga/intel/afu.h
create mode 100644 drivers/fpga/intel/feature-dev.c
create mode 100644 drivers/fpga/intel/feature-dev.h
create mode 100644 drivers/fpga/intel/fme-main.c
create mode 100644 drivers/fpga/intel/fme-pr.c
create mode 100644 drivers/fpga/intel/fme.h
create mode 100644 drivers/fpga/intel/pcie.c
create mode 100644 include/linux/fpga/fpga-dev.h
create mode 100644 include/uapi/linux/intel-fpga.h
--
2.7.4
[toc] | [next] | [standalone]
| From | Wu Hao <hao.wu@intel.com> |
|---|---|
| Date | 2017-03-30 14:20 +0200 |
| Subject | [PATCH 02/16] fpga: add FPGA device framework |
| Message-ID | <tqHdw-69w-35@gated-at.bofh.it> |
| In reply to | #1613003 |
During FPGA device (e.g PCI-based) discovery, platform devices are
registered for different FPGA function units. But the device node path
isn't quite friendly to applications.
Consider this case, applications want to access child device's sysfs file
for some information.
1) Access using bus-based path (e.g PCI)
/sys/bus/pci/devices/xxxxx/fpga_func_a.0/sysfs_file
From the path, it's clear which PCI device is the parent, but not perfect
solution for applications. PCI device BDF is not fixed, application may
need to search all PCI device to find the actual FPGA Device.
2) Or access using platform device path
/sys/bus/platform/devices/fpga_func_a.0/sysfs_file
Applications find the actual function by name easily, but no information
about which fpga device it belongs to. It's quite confusing if multiple
FPGA devices are in one system.
'FPGA Device' class is introduced to resolve this problem. Each node under
this class represents a fpga device, which may have one or more child
devices. Applications only need to search under this FPGA Device class
folder to find the child device node it needs.
For example, for the platform has 2 fpga devices, each fpga device has
3 child devices, the hierarchy looks like this.
Two nodes are under /sys/class/fpga/:
/sys/class/fpga/fpga.0
/sys/class/fpga/fpga.1
Each node has 1 function A device and 2 function B devices:
/sys/class/fpga/fpga.0/func_a.0
/sys/class/fpga/fpga.0/func_b.0
/sys/class/fpga/fpga.0/func_b.1
/sys/class/fpga/fpga.1/func_a.1
/sys/class/fpga/fpga.1/func_b.2
/sys/class/fpga/fpga.1/func_b.3
This following APIs are provided by FPGA device framework:
* fpga_dev_create
Create fpga device under the given parent device.
* fpga_dev_destroy
Destroy fpga device
The following sysfs files are created:
* /sys/class/fpga/<fpga.x>/name
Name of the fpga device.
Signed-off-by: Tim Whisonant <tim.whisonant@intel.com>
Signed-off-by: Enno Luebbers <enno.luebbers@intel.com>
Signed-off-by: Shiva Rao <shiva.rao@intel.com>
Signed-off-by: Christopher Rauer <christopher.rauer@intel.com>
Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
Signed-off-by: Wu Hao <hao.wu@intel.com>
---
drivers/fpga/Kconfig | 6 +++
drivers/fpga/Makefile | 3 ++
drivers/fpga/fpga-dev.c | 120 ++++++++++++++++++++++++++++++++++++++++++
include/linux/fpga/fpga-dev.h | 34 ++++++++++++
4 files changed, 163 insertions(+)
create mode 100644 drivers/fpga/fpga-dev.c
create mode 100644 include/linux/fpga/fpga-dev.h
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index ce861a2..d99b640 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -12,6 +12,12 @@ config FPGA
manager drivers.
if FPGA
+config FPGA_DEVICE
+ tristate "FPGA Device Framework"
+ help
+ Say Y here if you want support for FPGA Devices from the kernel.
+ The FPGA Device Framework adds a FPGA device class and provide
+ interfaces to create FPGA devices.
config FPGA_REGION
tristate "FPGA Region"
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 8df07bc..53a41d2 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -5,6 +5,9 @@
# Core FPGA Manager Framework
obj-$(CONFIG_FPGA) += fpga-mgr.o
+# FPGA Device Framework
+obj-$(CONFIG_FPGA_DEVICE) += fpga-dev.o
+
# FPGA Manager Drivers
obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o
obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o
diff --git a/drivers/fpga/fpga-dev.c b/drivers/fpga/fpga-dev.c
new file mode 100644
index 0000000..0f4c0ed
--- /dev/null
+++ b/drivers/fpga/fpga-dev.c
@@ -0,0 +1,120 @@
+/*
+ * FPGA Device Framework Driver
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * This work is licensed under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license. See the
+ * LICENSE.BSD file under drivers/fpga/intel for the BSD license and see
+ * the COPYING file in the top-level directory for the GPLv2 license.
+ */
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/fpga/fpga-dev.h>
+
+static DEFINE_IDA(fpga_dev_ida);
+static struct class *fpga_dev_class;
+
+static ssize_t name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fpga_dev *fdev = to_fpga_dev(dev);
+
+ return sprintf(buf, "%s\n", fdev->name);
+}
+static DEVICE_ATTR_RO(name);
+
+static struct attribute *fpga_dev_attrs[] = {
+ &dev_attr_name.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(fpga_dev);
+
+/**
+ * fpga_dev_create - create a fpga device
+ * @parent: parent device
+ * @name: fpga device name
+ *
+ * Return fpga_dev struct for success, error code otherwise.
+ */
+struct fpga_dev *fpga_dev_create(struct device *parent, const char *name)
+{
+ struct fpga_dev *fdev;
+ int id, ret = 0;
+
+ if (!name || !strlen(name)) {
+ dev_err(parent, "Attempt to register with no name!\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ fdev = kzalloc(sizeof(*fdev), GFP_KERNEL);
+ if (!fdev)
+ return ERR_PTR(-ENOMEM);
+
+ id = ida_simple_get(&fpga_dev_ida, 0, 0, GFP_KERNEL);
+ if (id < 0) {
+ ret = id;
+ goto error_kfree;
+ }
+
+ fdev->name = name;
+
+ device_initialize(&fdev->dev);
+ fdev->dev.class = fpga_dev_class;
+ fdev->dev.parent = parent;
+ fdev->dev.id = id;
+
+ ret = dev_set_name(&fdev->dev, "fpga.%d", id);
+ if (ret)
+ goto error_device;
+
+ ret = device_add(&fdev->dev);
+ if (ret)
+ goto error_device;
+
+ dev_dbg(fdev->dev.parent, "fpga device [%s] created\n", fdev->name);
+
+ return fdev;
+
+error_device:
+ ida_simple_remove(&fpga_dev_ida, id);
+error_kfree:
+ kfree(fdev);
+
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(fpga_dev_create);
+
+static void fpga_dev_release(struct device *dev)
+{
+ struct fpga_dev *fdev = to_fpga_dev(dev);
+
+ ida_simple_remove(&fpga_dev_ida, fdev->dev.id);
+ kfree(fdev);
+}
+
+static int __init fpga_dev_class_init(void)
+{
+ pr_info("FPGA Device framework\n");
+
+ fpga_dev_class = class_create(THIS_MODULE, "fpga");
+ if (IS_ERR(fpga_dev_class))
+ return PTR_ERR(fpga_dev_class);
+
+ fpga_dev_class->dev_groups = fpga_dev_groups;
+ fpga_dev_class->dev_release = fpga_dev_release;
+
+ return 0;
+}
+
+static void __exit fpga_dev_class_exit(void)
+{
+ class_destroy(fpga_dev_class);
+}
+
+MODULE_DESCRIPTION("FPGA Device framework");
+MODULE_LICENSE("Dual BSD/GPL");
+
+subsys_initcall(fpga_dev_class_init);
+module_exit(fpga_dev_class_exit);
diff --git a/include/linux/fpga/fpga-dev.h b/include/linux/fpga/fpga-dev.h
new file mode 100644
index 0000000..7b58356
--- /dev/null
+++ b/include/linux/fpga/fpga-dev.h
@@ -0,0 +1,34 @@
+/*
+ * FPGA Device Driver Header
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * This work is licensed under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license. See the
+ * LICENSE.BSD file under drivers/fpga/intel for the BSD license and see
+ * the COPYING file in the top-level directory for the GPLv2 license.
+ *
+ */
+#ifndef _LINUX_FPGA_DEV_H
+#define _LINUX_FPGA_DEV_H
+
+/**
+ * struct fpga_dev - fpga device structure
+ * @name: name of fpga device
+ * @dev: fpga device
+ */
+struct fpga_dev {
+ const char *name;
+ struct device dev;
+};
+
+#define to_fpga_dev(d) container_of(d, struct fpga_dev, dev)
+
+struct fpga_dev *fpga_dev_create(struct device *parent, const char *name);
+
+static inline void fpga_dev_destroy(struct fpga_dev *fdev)
+{
+ device_unregister(&fdev->dev);
+}
+
+#endif
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Greg KH <greg@kroah.com> |
|---|---|
| Date | 2017-03-31 08:10 +0200 |
| Subject | Re: [PATCH 02/16] fpga: add FPGA device framework |
| Message-ID | <tqXUZ-Kk-1@gated-at.bofh.it> |
| In reply to | #1613005 |
On Thu, Mar 30, 2017 at 08:08:02PM +0800, Wu Hao wrote: > During FPGA device (e.g PCI-based) discovery, platform devices are > registered for different FPGA function units. But the device node path > isn't quite friendly to applications. > > Consider this case, applications want to access child device's sysfs file > for some information. > > 1) Access using bus-based path (e.g PCI) > > /sys/bus/pci/devices/xxxxx/fpga_func_a.0/sysfs_file > > From the path, it's clear which PCI device is the parent, but not perfect > solution for applications. PCI device BDF is not fixed, application may > need to search all PCI device to find the actual FPGA Device. > > 2) Or access using platform device path > > /sys/bus/platform/devices/fpga_func_a.0/sysfs_file > > Applications find the actual function by name easily, but no information > about which fpga device it belongs to. It's quite confusing if multiple > FPGA devices are in one system. > > 'FPGA Device' class is introduced to resolve this problem. Each node under > this class represents a fpga device, which may have one or more child > devices. Applications only need to search under this FPGA Device class > folder to find the child device node it needs. > > For example, for the platform has 2 fpga devices, each fpga device has > 3 child devices, the hierarchy looks like this. > > Two nodes are under /sys/class/fpga/: > /sys/class/fpga/fpga.0 > /sys/class/fpga/fpga.1 > > Each node has 1 function A device and 2 function B devices: > /sys/class/fpga/fpga.0/func_a.0 > /sys/class/fpga/fpga.0/func_b.0 > /sys/class/fpga/fpga.0/func_b.1 > > /sys/class/fpga/fpga.1/func_a.1 > /sys/class/fpga/fpga.1/func_b.2 > /sys/class/fpga/fpga.1/func_b.3 > > This following APIs are provided by FPGA device framework: > * fpga_dev_create > Create fpga device under the given parent device. > * fpga_dev_destroy > Destroy fpga device > > The following sysfs files are created: > * /sys/class/fpga/<fpga.x>/name > Name of the fpga device. How does this interact with the existing "fpga class" that is in the kernel already? thanks, greg k-h
[toc] | [prev] | [next] | [standalone]
| From | Wu Hao <hao.wu@intel.com> |
|---|---|
| Date | 2017-03-31 10:00 +0200 |
| Subject | Re: [PATCH 02/16] fpga: add FPGA device framework |
| Message-ID | <tqZDr-1Hf-9@gated-at.bofh.it> |
| In reply to | #1613649 |
On Fri, Mar 31, 2017 at 08:09:09AM +0200, Greg KH wrote: > On Thu, Mar 30, 2017 at 08:08:02PM +0800, Wu Hao wrote: > > During FPGA device (e.g PCI-based) discovery, platform devices are > > registered for different FPGA function units. But the device node path > > isn't quite friendly to applications. > > > > Consider this case, applications want to access child device's sysfs file > > for some information. > > > > 1) Access using bus-based path (e.g PCI) > > > > /sys/bus/pci/devices/xxxxx/fpga_func_a.0/sysfs_file > > > > From the path, it's clear which PCI device is the parent, but not perfect > > solution for applications. PCI device BDF is not fixed, application may > > need to search all PCI device to find the actual FPGA Device. > > > > 2) Or access using platform device path > > > > /sys/bus/platform/devices/fpga_func_a.0/sysfs_file > > > > Applications find the actual function by name easily, but no information > > about which fpga device it belongs to. It's quite confusing if multiple > > FPGA devices are in one system. > > > > 'FPGA Device' class is introduced to resolve this problem. Each node under > > this class represents a fpga device, which may have one or more child > > devices. Applications only need to search under this FPGA Device class > > folder to find the child device node it needs. > > > > For example, for the platform has 2 fpga devices, each fpga device has > > 3 child devices, the hierarchy looks like this. > > > > Two nodes are under /sys/class/fpga/: > > /sys/class/fpga/fpga.0 > > /sys/class/fpga/fpga.1 > > > > Each node has 1 function A device and 2 function B devices: > > /sys/class/fpga/fpga.0/func_a.0 > > /sys/class/fpga/fpga.0/func_b.0 > > /sys/class/fpga/fpga.0/func_b.1 > > > > /sys/class/fpga/fpga.1/func_a.1 > > /sys/class/fpga/fpga.1/func_b.2 > > /sys/class/fpga/fpga.1/func_b.3 > > > > This following APIs are provided by FPGA device framework: > > * fpga_dev_create > > Create fpga device under the given parent device. > > * fpga_dev_destroy > > Destroy fpga device > > > > The following sysfs files are created: > > * /sys/class/fpga/<fpga.x>/name > > Name of the fpga device. > > How does this interact with the existing "fpga class" that is in the > kernel already? The fpga-dev introduced by this patch, is only a container device, and drivers could register different functions under it. Per my understanding, the existing "fpga class", including fpga-region, fpga-bridge and fpga-manager, is used to provide reconfiguration function for FPGA. So driver can create child node using this existing "fpga class" to provide FPGA reconfiguration function, and more nodes under this container for different functions for given FPGA device. For Intel FPGA device, partial reconfiguration is only one function of Intel FPGA Management Engine (FME). FME driver creates fpga_manager under below path for partial reconfiguration, and other interfaces for more functions, e.g power management, virtualization support and etc. /sys/class/fpga/<fpga.x>/<intel-fpga-fme.x>/fpga_manager Thanks Hao > > thanks, > > greg k-h
[toc] | [prev] | [next] | [standalone]
| From | Greg KH <greg@kroah.com> |
|---|---|
| Date | 2017-03-31 11:10 +0200 |
| Subject | Re: [PATCH 02/16] fpga: add FPGA device framework |
| Message-ID | <tr0Je-2AS-95@gated-at.bofh.it> |
| In reply to | #1613714 |
On Fri, Mar 31, 2017 at 03:48:42PM +0800, Wu Hao wrote: > On Fri, Mar 31, 2017 at 08:09:09AM +0200, Greg KH wrote: > > On Thu, Mar 30, 2017 at 08:08:02PM +0800, Wu Hao wrote: > > > During FPGA device (e.g PCI-based) discovery, platform devices are > > > registered for different FPGA function units. But the device node path > > > isn't quite friendly to applications. > > > > > > Consider this case, applications want to access child device's sysfs file > > > for some information. > > > > > > 1) Access using bus-based path (e.g PCI) > > > > > > /sys/bus/pci/devices/xxxxx/fpga_func_a.0/sysfs_file > > > > > > From the path, it's clear which PCI device is the parent, but not perfect > > > solution for applications. PCI device BDF is not fixed, application may > > > need to search all PCI device to find the actual FPGA Device. > > > > > > 2) Or access using platform device path > > > > > > /sys/bus/platform/devices/fpga_func_a.0/sysfs_file > > > > > > Applications find the actual function by name easily, but no information > > > about which fpga device it belongs to. It's quite confusing if multiple > > > FPGA devices are in one system. > > > > > > 'FPGA Device' class is introduced to resolve this problem. Each node under > > > this class represents a fpga device, which may have one or more child > > > devices. Applications only need to search under this FPGA Device class > > > folder to find the child device node it needs. > > > > > > For example, for the platform has 2 fpga devices, each fpga device has > > > 3 child devices, the hierarchy looks like this. > > > > > > Two nodes are under /sys/class/fpga/: > > > /sys/class/fpga/fpga.0 > > > /sys/class/fpga/fpga.1 > > > > > > Each node has 1 function A device and 2 function B devices: > > > /sys/class/fpga/fpga.0/func_a.0 > > > /sys/class/fpga/fpga.0/func_b.0 > > > /sys/class/fpga/fpga.0/func_b.1 > > > > > > /sys/class/fpga/fpga.1/func_a.1 > > > /sys/class/fpga/fpga.1/func_b.2 > > > /sys/class/fpga/fpga.1/func_b.3 > > > > > > This following APIs are provided by FPGA device framework: > > > * fpga_dev_create > > > Create fpga device under the given parent device. > > > * fpga_dev_destroy > > > Destroy fpga device > > > > > > The following sysfs files are created: > > > * /sys/class/fpga/<fpga.x>/name > > > Name of the fpga device. > > > > How does this interact with the existing "fpga class" that is in the > > kernel already? > > The fpga-dev introduced by this patch, is only a container device, and > drivers could register different functions under it. Per my understanding, > the existing "fpga class", including fpga-region, fpga-bridge and > fpga-manager, is used to provide reconfiguration function for FPGA. So > driver can create child node using this existing "fpga class" to provide > FPGA reconfiguration function, and more nodes under this container for > different functions for given FPGA device. > > For Intel FPGA device, partial reconfiguration is only one function of > Intel FPGA Management Engine (FME). FME driver creates fpga_manager under > below path for partial reconfiguration, and other interfaces for more > functions, e.g power management, virtualization support and etc. > > /sys/class/fpga/<fpga.x>/<intel-fpga-fme.x>/fpga_manager So there is now two different levels of fpga class interfaces? I'm not disagreeing with this, just that it seems a bit confusing, don't you think? greg k-h
[toc] | [prev] | [next] | [standalone]
| From | Wu Hao <hao.wu@intel.com> |
|---|---|
| Date | 2017-03-31 14:30 +0200 |
| Subject | Re: [PATCH 02/16] fpga: add FPGA device framework |
| Message-ID | <tr3QJ-4xM-3@gated-at.bofh.it> |
| In reply to | #1613785 |
On Fri, Mar 31, 2017 at 11:03:28AM +0200, Greg KH wrote: > On Fri, Mar 31, 2017 at 03:48:42PM +0800, Wu Hao wrote: > > On Fri, Mar 31, 2017 at 08:09:09AM +0200, Greg KH wrote: > > > On Thu, Mar 30, 2017 at 08:08:02PM +0800, Wu Hao wrote: > > > > During FPGA device (e.g PCI-based) discovery, platform devices are > > > > registered for different FPGA function units. But the device node path > > > > isn't quite friendly to applications. > > > > > > > > Consider this case, applications want to access child device's sysfs file > > > > for some information. > > > > > > > > 1) Access using bus-based path (e.g PCI) > > > > > > > > /sys/bus/pci/devices/xxxxx/fpga_func_a.0/sysfs_file > > > > > > > > From the path, it's clear which PCI device is the parent, but not perfect > > > > solution for applications. PCI device BDF is not fixed, application may > > > > need to search all PCI device to find the actual FPGA Device. > > > > > > > > 2) Or access using platform device path > > > > > > > > /sys/bus/platform/devices/fpga_func_a.0/sysfs_file > > > > > > > > Applications find the actual function by name easily, but no information > > > > about which fpga device it belongs to. It's quite confusing if multiple > > > > FPGA devices are in one system. > > > > > > > > 'FPGA Device' class is introduced to resolve this problem. Each node under > > > > this class represents a fpga device, which may have one or more child > > > > devices. Applications only need to search under this FPGA Device class > > > > folder to find the child device node it needs. > > > > > > > > For example, for the platform has 2 fpga devices, each fpga device has > > > > 3 child devices, the hierarchy looks like this. > > > > > > > > Two nodes are under /sys/class/fpga/: > > > > /sys/class/fpga/fpga.0 > > > > /sys/class/fpga/fpga.1 > > > > > > > > Each node has 1 function A device and 2 function B devices: > > > > /sys/class/fpga/fpga.0/func_a.0 > > > > /sys/class/fpga/fpga.0/func_b.0 > > > > /sys/class/fpga/fpga.0/func_b.1 > > > > > > > > /sys/class/fpga/fpga.1/func_a.1 > > > > /sys/class/fpga/fpga.1/func_b.2 > > > > /sys/class/fpga/fpga.1/func_b.3 > > > > > > > > This following APIs are provided by FPGA device framework: > > > > * fpga_dev_create > > > > Create fpga device under the given parent device. > > > > * fpga_dev_destroy > > > > Destroy fpga device > > > > > > > > The following sysfs files are created: > > > > * /sys/class/fpga/<fpga.x>/name > > > > Name of the fpga device. > > > > > > How does this interact with the existing "fpga class" that is in the > > > kernel already? > > > > The fpga-dev introduced by this patch, is only a container device, and > > drivers could register different functions under it. Per my understanding, > > the existing "fpga class", including fpga-region, fpga-bridge and > > fpga-manager, is used to provide reconfiguration function for FPGA. So > > driver can create child node using this existing "fpga class" to provide > > FPGA reconfiguration function, and more nodes under this container for > > different functions for given FPGA device. > > > > For Intel FPGA device, partial reconfiguration is only one function of > > Intel FPGA Management Engine (FME). FME driver creates fpga_manager under > > below path for partial reconfiguration, and other interfaces for more > > functions, e.g power management, virtualization support and etc. > > > > /sys/class/fpga/<fpga.x>/<intel-fpga-fme.x>/fpga_manager > > So there is now two different levels of fpga class interfaces? > > I'm not disagreeing with this, just that it seems a bit confusing, don't > you think? I am not so sure, but the main purpose of fpga-dev, is trying to provide enduser a more clear sysfs hierarchy reflecting the real hardware. And fpga-things can be registered to fpga-dev directly if the hardware arch is simple. From enduser point of view, he could find everything of this FPGA device under /sys/class/fpga/<fpga.x>/, including all fpga-regions, fpga-bridges and fpga-managers. I feel it is not a bad choice. :) Thanks Hao > > greg k-h
[toc] | [prev] | [next] | [standalone]
| From | matthew.gerlach@linux.intel.com |
|---|---|
| Date | 2017-03-31 21:10 +0200 |
| Subject | Re: [PATCH 02/16] fpga: add FPGA device framework |
| Message-ID | <tra5Q-eL-27@gated-at.bofh.it> |
| In reply to | #1613714 |
On Fri, 31 Mar 2017, Wu Hao wrote: > On Fri, Mar 31, 2017 at 08:09:09AM +0200, Greg KH wrote: >> On Thu, Mar 30, 2017 at 08:08:02PM +0800, Wu Hao wrote: >>> During FPGA device (e.g PCI-based) discovery, platform devices are >>> registered for different FPGA function units. But the device node path >>> isn't quite friendly to applications. >>> >>> Consider this case, applications want to access child device's sysfs file >>> for some information. >>> >>> 1) Access using bus-based path (e.g PCI) >>> >>> /sys/bus/pci/devices/xxxxx/fpga_func_a.0/sysfs_file >>> >>> From the path, it's clear which PCI device is the parent, but not perfect >>> solution for applications. PCI device BDF is not fixed, application may >>> need to search all PCI device to find the actual FPGA Device. >>> >>> 2) Or access using platform device path >>> >>> /sys/bus/platform/devices/fpga_func_a.0/sysfs_file >>> >>> Applications find the actual function by name easily, but no information >>> about which fpga device it belongs to. It's quite confusing if multiple >>> FPGA devices are in one system. >>> >>> 'FPGA Device' class is introduced to resolve this problem. Each node under >>> this class represents a fpga device, which may have one or more child >>> devices. Applications only need to search under this FPGA Device class >>> folder to find the child device node it needs. >>> >>> For example, for the platform has 2 fpga devices, each fpga device has >>> 3 child devices, the hierarchy looks like this. >>> >>> Two nodes are under /sys/class/fpga/: >>> /sys/class/fpga/fpga.0 >>> /sys/class/fpga/fpga.1 >>> >>> Each node has 1 function A device and 2 function B devices: >>> /sys/class/fpga/fpga.0/func_a.0 >>> /sys/class/fpga/fpga.0/func_b.0 >>> /sys/class/fpga/fpga.0/func_b.1 >>> >>> /sys/class/fpga/fpga.1/func_a.1 >>> /sys/class/fpga/fpga.1/func_b.2 >>> /sys/class/fpga/fpga.1/func_b.3 >>> >>> This following APIs are provided by FPGA device framework: >>> * fpga_dev_create >>> Create fpga device under the given parent device. >>> * fpga_dev_destroy >>> Destroy fpga device >>> >>> The following sysfs files are created: >>> * /sys/class/fpga/<fpga.x>/name >>> Name of the fpga device. >> >> How does this interact with the existing "fpga class" that is in the >> kernel already? > > The fpga-dev introduced by this patch, is only a container device, and I completely understand the need for a container device. The fpga-region is also primarily a container, and in some cases the fpga-region may represent the entire fpga. Over time this code may become redundant. > drivers could register different functions under it. Per my understanding, > the existing "fpga class", including fpga-region, fpga-bridge and > fpga-manager, is used to provide reconfiguration function for FPGA. So > driver can create child node using this existing "fpga class" to provide > FPGA reconfiguration function, and more nodes under this container for > different functions for given FPGA device. > > For Intel FPGA device, partial reconfiguration is only one function of > Intel FPGA Management Engine (FME). FME driver creates fpga_manager under > below path for partial reconfiguration, and other interfaces for more > functions, e.g power management, virtualization support and etc. > > /sys/class/fpga/<fpga.x>/<intel-fpga-fme.x>/fpga_manager > > Thanks > Hao > >> >> thanks, >> >> greg k-h > -- > To unsubscribe from this list: send the line "unsubscribe linux-fpga" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html >
[toc] | [prev] | [next] | [standalone]
| From | Wu Hao <hao.wu@intel.com> |
|---|---|
| Date | 2017-04-01 14:30 +0200 |
| Subject | Re: [PATCH 02/16] fpga: add FPGA device framework |
| Message-ID | <trqkh-2Bi-3@gated-at.bofh.it> |
| In reply to | #1614262 |
On Fri, Mar 31, 2017 at 12:01:13PM -0700, matthew.gerlach@linux.intel.com wrote: > On Fri, 31 Mar 2017, Wu Hao wrote: > >On Fri, Mar 31, 2017 at 08:09:09AM +0200, Greg KH wrote: > >>On Thu, Mar 30, 2017 at 08:08:02PM +0800, Wu Hao wrote: > >>>During FPGA device (e.g PCI-based) discovery, platform devices are > >>>registered for different FPGA function units. But the device node path > >>>isn't quite friendly to applications. > >>> > >>>Consider this case, applications want to access child device's sysfs file > >>>for some information. > >>> > >>>1) Access using bus-based path (e.g PCI) > >>> > >>> /sys/bus/pci/devices/xxxxx/fpga_func_a.0/sysfs_file > >>> > >>> From the path, it's clear which PCI device is the parent, but not perfect > >>> solution for applications. PCI device BDF is not fixed, application may > >>> need to search all PCI device to find the actual FPGA Device. > >>> > >>>2) Or access using platform device path > >>> > >>> /sys/bus/platform/devices/fpga_func_a.0/sysfs_file > >>> > >>> Applications find the actual function by name easily, but no information > >>> about which fpga device it belongs to. It's quite confusing if multiple > >>> FPGA devices are in one system. > >>> > >>>'FPGA Device' class is introduced to resolve this problem. Each node under > >>>this class represents a fpga device, which may have one or more child > >>>devices. Applications only need to search under this FPGA Device class > >>>folder to find the child device node it needs. > >>> > >>>For example, for the platform has 2 fpga devices, each fpga device has > >>>3 child devices, the hierarchy looks like this. > >>> > >>>Two nodes are under /sys/class/fpga/: > >>>/sys/class/fpga/fpga.0 > >>>/sys/class/fpga/fpga.1 > >>> > >>>Each node has 1 function A device and 2 function B devices: > >>>/sys/class/fpga/fpga.0/func_a.0 > >>>/sys/class/fpga/fpga.0/func_b.0 > >>>/sys/class/fpga/fpga.0/func_b.1 > >>> > >>>/sys/class/fpga/fpga.1/func_a.1 > >>>/sys/class/fpga/fpga.1/func_b.2 > >>>/sys/class/fpga/fpga.1/func_b.3 > >>> > >>>This following APIs are provided by FPGA device framework: > >>>* fpga_dev_create > >>> Create fpga device under the given parent device. > >>>* fpga_dev_destroy > >>> Destroy fpga device > >>> > >>>The following sysfs files are created: > >>>* /sys/class/fpga/<fpga.x>/name > >>> Name of the fpga device. > >> > >>How does this interact with the existing "fpga class" that is in the > >>kernel already? > > > >The fpga-dev introduced by this patch, is only a container device, and > > I completely understand the need for a container device. The fpga-region is > also primarily a container, and in some cases the fpga-region may represent > the entire fpga. Over time this code may become redundant. Thanks a lot for your review and comments. I feel that the fpga-region implies that it supports reconfiguration, but in our cases, the Intel FPGA device, doesn't have base fpga-region for full reconfiguration, but many accelerators with partial reconfiguration support. A fpga-region brings together everything needed for the reconfiguration, and a fpga-dev is trying to brings everything on a FPGA device together, including fpga-region/bridge/manager, access different accelerators and other function units. I think it's not mandatory to use fpga-dev, as fpga-dev is just trying to provide one more option here for some complex hardware. Thanks Hao > >drivers could register different functions under it. Per my understanding, > >the existing "fpga class", including fpga-region, fpga-bridge and > >fpga-manager, is used to provide reconfiguration function for FPGA. So > >driver can create child node using this existing "fpga class" to provide > >FPGA reconfiguration function, and more nodes under this container for > >different functions for given FPGA device. > > > >For Intel FPGA device, partial reconfiguration is only one function of > >Intel FPGA Management Engine (FME). FME driver creates fpga_manager under > >below path for partial reconfiguration, and other interfaces for more > >functions, e.g power management, virtualization support and etc. > > > >/sys/class/fpga/<fpga.x>/<intel-fpga-fme.x>/fpga_manager > > > >Thanks > >Hao > > > >> > >>thanks, > >> > >>greg k-h > >-- > >To unsubscribe from this list: send the line "unsubscribe linux-fpga" in > >the body of a message to majordomo@vger.kernel.org > >More majordomo info at http://vger.kernel.org/majordomo-info.html > >
[toc] | [prev] | [next] | [standalone]
| From | Greg KH <greg@kroah.com> |
|---|---|
| Date | 2017-03-31 08:20 +0200 |
| Subject | Re: [PATCH 02/16] fpga: add FPGA device framework |
| Message-ID | <tqY4F-NR-5@gated-at.bofh.it> |
| In reply to | #1613005 |
On Thu, Mar 30, 2017 at 08:08:02PM +0800, Wu Hao wrote:
> During FPGA device (e.g PCI-based) discovery, platform devices are
> registered for different FPGA function units. But the device node path
> isn't quite friendly to applications.
>
> Consider this case, applications want to access child device's sysfs file
> for some information.
>
> 1) Access using bus-based path (e.g PCI)
>
> /sys/bus/pci/devices/xxxxx/fpga_func_a.0/sysfs_file
>
> From the path, it's clear which PCI device is the parent, but not perfect
> solution for applications. PCI device BDF is not fixed, application may
> need to search all PCI device to find the actual FPGA Device.
>
> 2) Or access using platform device path
>
> /sys/bus/platform/devices/fpga_func_a.0/sysfs_file
>
> Applications find the actual function by name easily, but no information
> about which fpga device it belongs to. It's quite confusing if multiple
> FPGA devices are in one system.
>
> 'FPGA Device' class is introduced to resolve this problem. Each node under
> this class represents a fpga device, which may have one or more child
> devices. Applications only need to search under this FPGA Device class
> folder to find the child device node it needs.
>
> For example, for the platform has 2 fpga devices, each fpga device has
> 3 child devices, the hierarchy looks like this.
>
> Two nodes are under /sys/class/fpga/:
> /sys/class/fpga/fpga.0
> /sys/class/fpga/fpga.1
>
> Each node has 1 function A device and 2 function B devices:
> /sys/class/fpga/fpga.0/func_a.0
> /sys/class/fpga/fpga.0/func_b.0
> /sys/class/fpga/fpga.0/func_b.1
>
> /sys/class/fpga/fpga.1/func_a.1
> /sys/class/fpga/fpga.1/func_b.2
> /sys/class/fpga/fpga.1/func_b.3
>
> This following APIs are provided by FPGA device framework:
> * fpga_dev_create
> Create fpga device under the given parent device.
> * fpga_dev_destroy
> Destroy fpga device
>
> The following sysfs files are created:
> * /sys/class/fpga/<fpga.x>/name
> Name of the fpga device.
>
> Signed-off-by: Tim Whisonant <tim.whisonant@intel.com>
> Signed-off-by: Enno Luebbers <enno.luebbers@intel.com>
> Signed-off-by: Shiva Rao <shiva.rao@intel.com>
> Signed-off-by: Christopher Rauer <christopher.rauer@intel.com>
> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> Signed-off-by: Wu Hao <hao.wu@intel.com>
> ---
> drivers/fpga/Kconfig | 6 +++
> drivers/fpga/Makefile | 3 ++
> drivers/fpga/fpga-dev.c | 120 ++++++++++++++++++++++++++++++++++++++++++
> include/linux/fpga/fpga-dev.h | 34 ++++++++++++
> 4 files changed, 163 insertions(+)
> create mode 100644 drivers/fpga/fpga-dev.c
> create mode 100644 include/linux/fpga/fpga-dev.h
>
> diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
> index ce861a2..d99b640 100644
> --- a/drivers/fpga/Kconfig
> +++ b/drivers/fpga/Kconfig
> @@ -12,6 +12,12 @@ config FPGA
> manager drivers.
>
> if FPGA
> +config FPGA_DEVICE
> + tristate "FPGA Device Framework"
> + help
> + Say Y here if you want support for FPGA Devices from the kernel.
> + The FPGA Device Framework adds a FPGA device class and provide
> + interfaces to create FPGA devices.
>
> config FPGA_REGION
> tristate "FPGA Region"
> diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
> index 8df07bc..53a41d2 100644
> --- a/drivers/fpga/Makefile
> +++ b/drivers/fpga/Makefile
> @@ -5,6 +5,9 @@
> # Core FPGA Manager Framework
> obj-$(CONFIG_FPGA) += fpga-mgr.o
>
> +# FPGA Device Framework
> +obj-$(CONFIG_FPGA_DEVICE) += fpga-dev.o
> +
> # FPGA Manager Drivers
> obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o
> obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o
> diff --git a/drivers/fpga/fpga-dev.c b/drivers/fpga/fpga-dev.c
> new file mode 100644
> index 0000000..0f4c0ed
> --- /dev/null
> +++ b/drivers/fpga/fpga-dev.c
> @@ -0,0 +1,120 @@
> +/*
> + * FPGA Device Framework Driver
> + *
> + * Copyright (C) 2017 Intel Corporation, Inc.
> + *
> + * This work is licensed under a dual BSD/GPLv2 license. When using or
> + * redistributing this file, you may do so under either license. See the
> + * LICENSE.BSD file under drivers/fpga/intel for the BSD license and see
> + * the COPYING file in the top-level directory for the GPLv2 license.
Really? A BSD licened file that does EXPORT_SYMBOL_GPL and interacts
directly with the driver core? Please go talk to some of your lawyers
about this before you resubmit this correctly...
> + */
> +#include <linux/device.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/fpga/fpga-dev.h>
> +
> +static DEFINE_IDA(fpga_dev_ida);
> +static struct class *fpga_dev_class;
> +
> +static ssize_t name_show(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct fpga_dev *fdev = to_fpga_dev(dev);
> +
> + return sprintf(buf, "%s\n", fdev->name);
> +}
> +static DEVICE_ATTR_RO(name);
There already is a name for the device, it's the directory name.
> +
> +static struct attribute *fpga_dev_attrs[] = {
> + &dev_attr_name.attr,
> + NULL,
> +};
> +ATTRIBUTE_GROUPS(fpga_dev);
> +
> +/**
> + * fpga_dev_create - create a fpga device
> + * @parent: parent device
> + * @name: fpga device name
> + *
> + * Return fpga_dev struct for success, error code otherwise.
> + */
> +struct fpga_dev *fpga_dev_create(struct device *parent, const char *name)
> +{
> + struct fpga_dev *fdev;
> + int id, ret = 0;
> +
> + if (!name || !strlen(name)) {
> + dev_err(parent, "Attempt to register with no name!\n");
> + return ERR_PTR(-EINVAL);
> + }
> +
> + fdev = kzalloc(sizeof(*fdev), GFP_KERNEL);
> + if (!fdev)
> + return ERR_PTR(-ENOMEM);
> +
> + id = ida_simple_get(&fpga_dev_ida, 0, 0, GFP_KERNEL);
> + if (id < 0) {
> + ret = id;
> + goto error_kfree;
> + }
> +
> + fdev->name = name;
> +
> + device_initialize(&fdev->dev);
> + fdev->dev.class = fpga_dev_class;
> + fdev->dev.parent = parent;
> + fdev->dev.id = id;
> +
> + ret = dev_set_name(&fdev->dev, "fpga.%d", id);
> + if (ret)
> + goto error_device;
> +
> + ret = device_add(&fdev->dev);
> + if (ret)
> + goto error_device;
> +
> + dev_dbg(fdev->dev.parent, "fpga device [%s] created\n", fdev->name);
> +
> + return fdev;
> +
> +error_device:
> + ida_simple_remove(&fpga_dev_ida, id);
> +error_kfree:
> + kfree(fdev);
> +
> + return ERR_PTR(ret);
> +}
> +EXPORT_SYMBOL_GPL(fpga_dev_create);
> +
> +static void fpga_dev_release(struct device *dev)
> +{
> + struct fpga_dev *fdev = to_fpga_dev(dev);
> +
> + ida_simple_remove(&fpga_dev_ida, fdev->dev.id);
> + kfree(fdev);
> +}
> +
> +static int __init fpga_dev_class_init(void)
> +{
> + pr_info("FPGA Device framework\n");
> +
> + fpga_dev_class = class_create(THIS_MODULE, "fpga");
> + if (IS_ERR(fpga_dev_class))
> + return PTR_ERR(fpga_dev_class);
> +
> + fpga_dev_class->dev_groups = fpga_dev_groups;
> + fpga_dev_class->dev_release = fpga_dev_release;
> +
> + return 0;
> +}
> +
> +static void __exit fpga_dev_class_exit(void)
> +{
> + class_destroy(fpga_dev_class);
> +}
> +
> +MODULE_DESCRIPTION("FPGA Device framework");
> +MODULE_LICENSE("Dual BSD/GPL");
> +
> +subsys_initcall(fpga_dev_class_init);
> +module_exit(fpga_dev_class_exit);
> diff --git a/include/linux/fpga/fpga-dev.h b/include/linux/fpga/fpga-dev.h
> new file mode 100644
> index 0000000..7b58356
> --- /dev/null
> +++ b/include/linux/fpga/fpga-dev.h
> @@ -0,0 +1,34 @@
> +/*
> + * FPGA Device Driver Header
> + *
> + * Copyright (C) 2017 Intel Corporation, Inc.
> + *
> + * This work is licensed under a dual BSD/GPLv2 license. When using or
> + * redistributing this file, you may do so under either license. See the
> + * LICENSE.BSD file under drivers/fpga/intel for the BSD license and see
> + * the COPYING file in the top-level directory for the GPLv2 license.
Again with the dual license, please fix up.
> + *
> + */
> +#ifndef _LINUX_FPGA_DEV_H
> +#define _LINUX_FPGA_DEV_H
> +
> +/**
> + * struct fpga_dev - fpga device structure
> + * @name: name of fpga device
> + * @dev: fpga device
> + */
> +struct fpga_dev {
> + const char *name;
> + struct device dev;
struct device already has a name, why duplicate it here?
thanks,
greg k-h
[toc] | [prev] | [next] | [standalone]
| From | Wu Hao <hao.wu@intel.com> |
|---|---|
| Date | 2017-03-31 15:40 +0200 |
| Subject | Re: [PATCH 02/16] fpga: add FPGA device framework |
| Message-ID | <tr4Wu-5cZ-13@gated-at.bofh.it> |
| In reply to | #1613653 |
> On Thu, Mar 30, 2017 at 08:08:02PM +0800, Wu Hao wrote:
> > During FPGA device (e.g PCI-based) discovery, platform devices are
> > registered for different FPGA function units. But the device node path
> > isn't quite friendly to applications.
> >
> > Consider this case, applications want to access child device's sysfs
> > file for some information.
> >
> > 1) Access using bus-based path (e.g PCI)
> >
> > /sys/bus/pci/devices/xxxxx/fpga_func_a.0/sysfs_file
> >
> > From the path, it's clear which PCI device is the parent, but not perfect
> > solution for applications. PCI device BDF is not fixed, application may
> > need to search all PCI device to find the actual FPGA Device.
> >
> > 2) Or access using platform device path
> >
> > /sys/bus/platform/devices/fpga_func_a.0/sysfs_file
> >
> > Applications find the actual function by name easily, but no information
> > about which fpga device it belongs to. It's quite confusing if multiple
> > FPGA devices are in one system.
> >
> > 'FPGA Device' class is introduced to resolve this problem. Each node
> > under this class represents a fpga device, which may have one or more
> > child devices. Applications only need to search under this FPGA Device
> > class folder to find the child device node it needs.
> >
> > For example, for the platform has 2 fpga devices, each fpga device has
> > 3 child devices, the hierarchy looks like this.
> >
> > Two nodes are under /sys/class/fpga/:
> > /sys/class/fpga/fpga.0
> > /sys/class/fpga/fpga.1
> >
> > Each node has 1 function A device and 2 function B devices:
> > /sys/class/fpga/fpga.0/func_a.0
> > /sys/class/fpga/fpga.0/func_b.0
> > /sys/class/fpga/fpga.0/func_b.1
> >
> > /sys/class/fpga/fpga.1/func_a.1
> > /sys/class/fpga/fpga.1/func_b.2
> > /sys/class/fpga/fpga.1/func_b.3
> >
> > This following APIs are provided by FPGA device framework:
> > * fpga_dev_create
> > Create fpga device under the given parent device.
> > * fpga_dev_destroy
> > Destroy fpga device
> >
> > The following sysfs files are created:
> > * /sys/class/fpga/<fpga.x>/name
> > Name of the fpga device.
> >
> > Signed-off-by: Tim Whisonant <tim.whisonant@intel.com>
> > Signed-off-by: Enno Luebbers <enno.luebbers@intel.com>
> > Signed-off-by: Shiva Rao <shiva.rao@intel.com>
> > Signed-off-by: Christopher Rauer <christopher.rauer@intel.com>
> > Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> > Signed-off-by: Wu Hao <hao.wu@intel.com>
> > ---
> > drivers/fpga/Kconfig | 6 +++
> > drivers/fpga/Makefile | 3 ++
> > drivers/fpga/fpga-dev.c | 120 ++++++++++++++++++++++++++++++++++++++++++
> > include/linux/fpga/fpga-dev.h | 34 ++++++++++++
> > 4 files changed, 163 insertions(+)
> > create mode 100644 drivers/fpga/fpga-dev.c create mode 100644
> > include/linux/fpga/fpga-dev.h
> >
> > diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index
> > ce861a2..d99b640 100644
> > --- a/drivers/fpga/Kconfig
> > +++ b/drivers/fpga/Kconfig
> > @@ -12,6 +12,12 @@ config FPGA
> > manager drivers.
> >
> > if FPGA
> > +config FPGA_DEVICE
> > + tristate "FPGA Device Framework"
> > + help
> > + Say Y here if you want support for FPGA Devices from the kernel.
> > + The FPGA Device Framework adds a FPGA device class and provide
> > + interfaces to create FPGA devices.
> >
> > config FPGA_REGION
> > tristate "FPGA Region"
> > diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index
> > 8df07bc..53a41d2 100644
> > --- a/drivers/fpga/Makefile
> > +++ b/drivers/fpga/Makefile
> > @@ -5,6 +5,9 @@
> > # Core FPGA Manager Framework
> > obj-$(CONFIG_FPGA) += fpga-mgr.o
> >
> > +# FPGA Device Framework
> > +obj-$(CONFIG_FPGA_DEVICE) += fpga-dev.o
> > +
> > # FPGA Manager Drivers
> > obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o
> > obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o
> > diff --git a/drivers/fpga/fpga-dev.c b/drivers/fpga/fpga-dev.c new
> > file mode 100644 index 0000000..0f4c0ed
> > --- /dev/null
> > +++ b/drivers/fpga/fpga-dev.c
> > @@ -0,0 +1,120 @@
> > +/*
> > + * FPGA Device Framework Driver
> > + *
> > + * Copyright (C) 2017 Intel Corporation, Inc.
> > + *
> > + * This work is licensed under a dual BSD/GPLv2 license. When using
> > +or
> > + * redistributing this file, you may do so under either license. See
> > +the
> > + * LICENSE.BSD file under drivers/fpga/intel for the BSD license and
> > +see
> > + * the COPYING file in the top-level directory for the GPLv2 license.
>
> Really? A BSD licened file that does EXPORT_SYMBOL_GPL and interacts directly with the driver core? Please go talk to some of your lawyers about this before you resubmit this correctly...
Sorry, will check and fix this in next version.
>
>
> > + */
> > +#include <linux/device.h>
> > +#include <linux/module.h>
> > +#include <linux/slab.h>
> > +#include <linux/fpga/fpga-dev.h>
> > +
> > +static DEFINE_IDA(fpga_dev_ida);
> > +static struct class *fpga_dev_class;
> > +
> > +static ssize_t name_show(struct device *dev,
> > + struct device_attribute *attr, char *buf) {
> > + struct fpga_dev *fdev = to_fpga_dev(dev);
> > +
> > + return sprintf(buf, "%s\n", fdev->name); } static
> > +DEVICE_ATTR_RO(name);
>
> There already is a name for the device, it's the directory name.
For current implementation, the directory will have a common name like
/sys/class/fpga/fpga.0
/sys/class/fpga/fpga.1
/sys/class/fpga/fpga.2
...
For the 'name' sysfs interface, driver can put more device specific info
into this 'name', e.g intel-fpga-dev. Userspace can use this information
to know which kind of FPGA device it is. e.g if applications read the
/sys/class/fpga/fpga.5/name as intel-fpga-dev, it means the 5th fpga
device on the system is a Intel FPGA device, and then application applies
related method to enumerate the accelerators for it.
And other existing fpga class has similar sysfs interface too, so I would
like to keep it aligned with others.
>
> > +
> > +static struct attribute *fpga_dev_attrs[] = {
> > + &dev_attr_name.attr,
> > + NULL,
> > +};
> > +ATTRIBUTE_GROUPS(fpga_dev);
> > +
> > +/**
> > + * fpga_dev_create - create a fpga device
> > + * @parent: parent device
> > + * @name: fpga device name
> > + *
> > + * Return fpga_dev struct for success, error code otherwise.
> > + */
> > +struct fpga_dev *fpga_dev_create(struct device *parent, const char
> > +*name) {
> > + struct fpga_dev *fdev;
> > + int id, ret = 0;
> > +
> > + if (!name || !strlen(name)) {
> > + dev_err(parent, "Attempt to register with no name!\n");
> > + return ERR_PTR(-EINVAL);
> > + }
> > +
> > + fdev = kzalloc(sizeof(*fdev), GFP_KERNEL);
> > + if (!fdev)
> > + return ERR_PTR(-ENOMEM);
> > +
> > + id = ida_simple_get(&fpga_dev_ida, 0, 0, GFP_KERNEL);
> > + if (id < 0) {
> > + ret = id;
> > + goto error_kfree;
> > + }
> > +
> > + fdev->name = name;
> > +
> > + device_initialize(&fdev->dev);
> > + fdev->dev.class = fpga_dev_class;
> > + fdev->dev.parent = parent;
> > + fdev->dev.id = id;
> > +
> > + ret = dev_set_name(&fdev->dev, "fpga.%d", id);
> > + if (ret)
> > + goto error_device;
> > +
> > + ret = device_add(&fdev->dev);
> > + if (ret)
> > + goto error_device;
> > +
> > + dev_dbg(fdev->dev.parent, "fpga device [%s] created\n", fdev->name);
> > +
> > + return fdev;
> > +
> > +error_device:
> > + ida_simple_remove(&fpga_dev_ida, id);
> > +error_kfree:
> > + kfree(fdev);
> > +
> > + return ERR_PTR(ret);
> > +}
> > +EXPORT_SYMBOL_GPL(fpga_dev_create);
> > +
> > +static void fpga_dev_release(struct device *dev) {
> > + struct fpga_dev *fdev = to_fpga_dev(dev);
> > +
> > + ida_simple_remove(&fpga_dev_ida, fdev->dev.id);
> > + kfree(fdev);
> > +}
> > +
> > +static int __init fpga_dev_class_init(void) {
> > + pr_info("FPGA Device framework\n");
> > +
> > + fpga_dev_class = class_create(THIS_MODULE, "fpga");
> > + if (IS_ERR(fpga_dev_class))
> > + return PTR_ERR(fpga_dev_class);
> > +
> > + fpga_dev_class->dev_groups = fpga_dev_groups;
> > + fpga_dev_class->dev_release = fpga_dev_release;
> > +
> > + return 0;
> > +}
> > +
> > +static void __exit fpga_dev_class_exit(void) {
> > + class_destroy(fpga_dev_class);
> > +}
> > +
> > +MODULE_DESCRIPTION("FPGA Device framework"); MODULE_LICENSE("Dual
> > +BSD/GPL");
> > +
> > +subsys_initcall(fpga_dev_class_init);
> > +module_exit(fpga_dev_class_exit);
> > diff --git a/include/linux/fpga/fpga-dev.h
> > b/include/linux/fpga/fpga-dev.h new file mode 100644 index
> > 0000000..7b58356
> > --- /dev/null
> > +++ b/include/linux/fpga/fpga-dev.h
> > @@ -0,0 +1,34 @@
> > +/*
> > + * FPGA Device Driver Header
> > + *
> > + * Copyright (C) 2017 Intel Corporation, Inc.
> > + *
> > + * This work is licensed under a dual BSD/GPLv2 license. When using
> > +or
> > + * redistributing this file, you may do so under either license. See
> > +the
> > + * LICENSE.BSD file under drivers/fpga/intel for the BSD license and
> > +see
> > + * the COPYING file in the top-level directory for the GPLv2 license.
>
> Again with the dual license, please fix up.
>
Sorry, will fix this in the next version.
> > + *
> > + */
> > +#ifndef _LINUX_FPGA_DEV_H
> > +#define _LINUX_FPGA_DEV_H
> > +
> > +/**
> > + * struct fpga_dev - fpga device structure
> > + * @name: name of fpga device
> > + * @dev: fpga device
> > + */
> > +struct fpga_dev {
> > + const char *name;
> > + struct device dev;
>
> struct device already has a name, why duplicate it here?
As mentioned above, dev has common name as fpga.x, but 'name' could have
more meaningful information, e.g venodr and device information.
Thanks
Hao
>
> thanks,
>
> greg k-h
[toc] | [prev] | [next] | [standalone]
| From | Greg KH <greg@kroah.com> |
|---|---|
| Date | 2017-03-31 16:20 +0200 |
| Subject | Re: [PATCH 02/16] fpga: add FPGA device framework |
| Message-ID | <tr5zc-5Hc-15@gated-at.bofh.it> |
| In reply to | #1614032 |
On Fri, Mar 31, 2017 at 09:31:09PM +0800, Wu Hao wrote:
> > On Thu, Mar 30, 2017 at 08:08:02PM +0800, Wu Hao wrote:
> > > +#include <linux/device.h>
> > > +#include <linux/module.h>
> > > +#include <linux/slab.h>
> > > +#include <linux/fpga/fpga-dev.h>
> > > +
> > > +static DEFINE_IDA(fpga_dev_ida);
> > > +static struct class *fpga_dev_class;
> > > +
> > > +static ssize_t name_show(struct device *dev,
> > > + struct device_attribute *attr, char *buf) {
> > > + struct fpga_dev *fdev = to_fpga_dev(dev);
> > > +
> > > + return sprintf(buf, "%s\n", fdev->name); } static
> > > +DEVICE_ATTR_RO(name);
> >
> > There already is a name for the device, it's the directory name.
>
> For current implementation, the directory will have a common name like
>
> /sys/class/fpga/fpga.0
> /sys/class/fpga/fpga.1
> /sys/class/fpga/fpga.2
> ...
>
> For the 'name' sysfs interface, driver can put more device specific info
> into this 'name', e.g intel-fpga-dev. Userspace can use this information
> to know which kind of FPGA device it is. e.g if applications read the
> /sys/class/fpga/fpga.5/name as intel-fpga-dev, it means the 5th fpga
> device on the system is a Intel FPGA device, and then application applies
> related method to enumerate the accelerators for it.
> And other existing fpga class has similar sysfs interface too, so I would
> like to keep it aligned with others.
Ok, then document the heck out of this in Documentation/ABI/ which I
don't think you did for the sysfs files you are creating.
thanks,
greg k-h
[toc] | [prev] | [next] | [standalone]
| From | Wu Hao <hao.wu@intel.com> |
|---|---|
| Date | 2017-04-01 13:50 +0200 |
| Subject | Re: [PATCH 02/16] fpga: add FPGA device framework |
| Message-ID | <trpHA-244-7@gated-at.bofh.it> |
| In reply to | #1614060 |
On Fri, Mar 31, 2017 at 04:10:09PM +0200, Greg KH wrote:
> On Fri, Mar 31, 2017 at 09:31:09PM +0800, Wu Hao wrote:
> > > On Thu, Mar 30, 2017 at 08:08:02PM +0800, Wu Hao wrote:
> > > > +#include <linux/device.h>
> > > > +#include <linux/module.h>
> > > > +#include <linux/slab.h>
> > > > +#include <linux/fpga/fpga-dev.h>
> > > > +
> > > > +static DEFINE_IDA(fpga_dev_ida);
> > > > +static struct class *fpga_dev_class;
> > > > +
> > > > +static ssize_t name_show(struct device *dev,
> > > > + struct device_attribute *attr, char *buf) {
> > > > + struct fpga_dev *fdev = to_fpga_dev(dev);
> > > > +
> > > > + return sprintf(buf, "%s\n", fdev->name); } static
> > > > +DEVICE_ATTR_RO(name);
> > >
> > > There already is a name for the device, it's the directory name.
> >
> > For current implementation, the directory will have a common name like
> >
> > /sys/class/fpga/fpga.0
> > /sys/class/fpga/fpga.1
> > /sys/class/fpga/fpga.2
> > ...
> >
> > For the 'name' sysfs interface, driver can put more device specific info
> > into this 'name', e.g intel-fpga-dev. Userspace can use this information
> > to know which kind of FPGA device it is. e.g if applications read the
> > /sys/class/fpga/fpga.5/name as intel-fpga-dev, it means the 5th fpga
> > device on the system is a Intel FPGA device, and then application applies
> > related method to enumerate the accelerators for it.
> > And other existing fpga class has similar sysfs interface too, so I would
> > like to keep it aligned with others.
>
> Ok, then document the heck out of this in Documentation/ABI/ which I
> don't think you did for the sysfs files you are creating.
Sure, thanks a lot for the reminder.
I will prepare the sysfs docs in the next version.
Thanks
Hao
>
> thanks,
>
> greg k-h
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fpga" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
[toc] | [prev] | [next] | [standalone]
| From | Wu Hao <hao.wu@intel.com> |
|---|---|
| Date | 2017-03-30 14:20 +0200 |
| Subject | [PATCH 03/16] fpga: intel: add FPGA PCIe device driver |
| Message-ID | <tqHdw-69w-19@gated-at.bofh.it> |
| In reply to | #1613003 |
From: Zhang Yi <yi.z.zhang@intel.com>
The Intel FPGA device appears as a PCIe device on the system. This patch
implements the basic framework of the driver for Intel PCIe device which
locates between CPU and Accelerated Function Units (AFUs).
Signed-off-by: Tim Whisonant <tim.whisonant@intel.com>
Signed-off-by: Enno Luebbers <enno.luebbers@intel.com>
Signed-off-by: Shiva Rao <shiva.rao@intel.com>
Signed-off-by: Christopher Rauer <christopher.rauer@intel.com>
Signed-off-by: Zhang Yi <yi.z.zhang@intel.com>
Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
Signed-off-by: Wu Hao <hao.wu@intel.com>
---
drivers/fpga/Kconfig | 2 +
drivers/fpga/Makefile | 3 +
drivers/fpga/intel/Kconfig | 27 +++++++++
drivers/fpga/intel/LICENSE.BSD | 24 ++++++++
drivers/fpga/intel/Makefile | 3 +
drivers/fpga/intel/pcie.c | 129 +++++++++++++++++++++++++++++++++++++++++
6 files changed, 188 insertions(+)
create mode 100644 drivers/fpga/intel/Kconfig
create mode 100644 drivers/fpga/intel/LICENSE.BSD
create mode 100644 drivers/fpga/intel/Makefile
create mode 100644 drivers/fpga/intel/pcie.c
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index d99b640..4e49aee 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -69,6 +69,8 @@ config ALTERA_FREEZE_BRIDGE
isolate one region of the FPGA from the busses while that
region is being reprogrammed.
+source "drivers/fpga/intel/Kconfig"
+
endif # FPGA
endmenu
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 53a41d2..46f1a5d 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -20,3 +20,6 @@ obj-$(CONFIG_ALTERA_FREEZE_BRIDGE) += altera-freeze-bridge.o
# High Level Interfaces
obj-$(CONFIG_FPGA_REGION) += fpga-region.o
+
+# Intel FPGA Support
+obj-$(CONFIG_INTEL_FPGA) += intel/
diff --git a/drivers/fpga/intel/Kconfig b/drivers/fpga/intel/Kconfig
new file mode 100644
index 0000000..bf402f3
--- /dev/null
+++ b/drivers/fpga/intel/Kconfig
@@ -0,0 +1,27 @@
+menuconfig INTEL_FPGA
+ tristate "Intel(R) FPGA support"
+ depends on FPGA_DEVICE
+ help
+ Select this option to enable driver support for Intel(R)
+ Field-Programmable Gate Array (FPGA) solutions. This driver
+ provides interfaces for userspace applications to configure,
+ enumerate, open, and access FPGA accelerators on platforms
+ equipped with Intel(R) FPGA solutions and enables system
+ level management functions such as FPGA reconfiguration,
+ power management, and virtualization.
+
+ Say Y if your platform has this technology. Say N if unsure.
+
+if INTEL_FPGA
+
+config INTEL_FPGA_PCI
+ tristate "Intel FPGA PCIe Driver"
+ depends on PCI
+ help
+ This is the driver for the PCIe device which locates between
+ CPU and Accelerated Function Units (AFUs) and allows them to
+ communicate with each other.
+
+ To compile this as a module, choose M here.
+
+endif
diff --git a/drivers/fpga/intel/LICENSE.BSD b/drivers/fpga/intel/LICENSE.BSD
new file mode 100644
index 0000000..309d2b7
--- /dev/null
+++ b/drivers/fpga/intel/LICENSE.BSD
@@ -0,0 +1,24 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/drivers/fpga/intel/Makefile b/drivers/fpga/intel/Makefile
new file mode 100644
index 0000000..61fd8ea
--- /dev/null
+++ b/drivers/fpga/intel/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_INTEL_FPGA_PCI) += intel-fpga-pci.o
+
+intel-fpga-pci-objs := pcie.o
diff --git a/drivers/fpga/intel/pcie.c b/drivers/fpga/intel/pcie.c
new file mode 100644
index 0000000..132d9da
--- /dev/null
+++ b/drivers/fpga/intel/pcie.c
@@ -0,0 +1,129 @@
+/*
+ * Driver for Intel FPGA PCIe device
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ * Zhang Yi <Yi.Z.Zhang@intel.com>
+ * Xiao Guangrong <guangrong.xiao@linux.intel.com>
+ * Joseph Grecco <joe.grecco@intel.com>
+ * Enno Luebbers <enno.luebbers@intel.com>
+ * Tim Whisonant <tim.whisonant@intel.com>
+ * Ananda Ravuri <ananda.ravuri@intel.com>
+ * Henry Mitchel <henry.mitchel@intel.com>
+ *
+ * This work is licensed under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license. See the
+ * LICENSE.BSD file under this directory for the BSD license and see
+ * the COPYING file in the top-level directory for the GPLv2 license.
+ */
+
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include <linux/errno.h>
+#include <linux/aer.h>
+
+#define DRV_VERSION "EXPERIMENTAL VERSION"
+#define DRV_NAME "intel-fpga-pci"
+
+/* PCI Device ID */
+#define PCIe_DEVICE_ID_PF_INT_5_X 0xBCBD
+#define PCIe_DEVICE_ID_PF_INT_6_X 0xBCC0
+#define PCIe_DEVICE_ID_PF_DSC_1_X 0x09C4
+/* VF Device */
+#define PCIe_DEVICE_ID_VF_INT_5_X 0xBCBF
+#define PCIe_DEVICE_ID_VF_INT_6_X 0xBCC1
+#define PCIe_DEVICE_ID_VF_DSC_1_X 0x09C5
+
+static struct pci_device_id cci_pcie_id_tbl[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_PF_INT_5_X),},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_VF_INT_5_X),},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_PF_INT_6_X),},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_VF_INT_6_X),},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_PF_DSC_1_X),},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_VF_DSC_1_X),},
+ {0,}
+};
+MODULE_DEVICE_TABLE(pci, cci_pcie_id_tbl);
+
+static
+int cci_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *pcidevid)
+{
+ int ret;
+
+ ret = pci_enable_device(pcidev);
+ if (ret < 0) {
+ dev_err(&pcidev->dev, "Failed to enable device %d.\n", ret);
+ goto exit;
+ }
+
+ ret = pci_enable_pcie_error_reporting(pcidev);
+ if (ret && ret != -EINVAL)
+ dev_info(&pcidev->dev, "PCIE AER unavailable %d.\n", ret);
+
+ ret = pci_request_regions(pcidev, DRV_NAME);
+ if (ret) {
+ dev_err(&pcidev->dev, "Failed to request regions.\n");
+ goto disable_error_report_exit;
+ }
+
+ pci_set_master(pcidev);
+ pci_save_state(pcidev);
+
+ if (!dma_set_mask(&pcidev->dev, DMA_BIT_MASK(64))) {
+ dma_set_coherent_mask(&pcidev->dev, DMA_BIT_MASK(64));
+ } else if (!dma_set_mask(&pcidev->dev, DMA_BIT_MASK(32))) {
+ dma_set_coherent_mask(&pcidev->dev, DMA_BIT_MASK(32));
+ } else {
+ ret = -EIO;
+ dev_err(&pcidev->dev, "No suitable DMA support available.\n");
+ goto release_region_exit;
+ }
+
+ /* TODO: create and add the platform device per feature list */
+ return 0;
+
+release_region_exit:
+ pci_release_regions(pcidev);
+disable_error_report_exit:
+ pci_disable_pcie_error_reporting(pcidev);
+ pci_disable_device(pcidev);
+exit:
+ return ret;
+}
+
+static void cci_pci_remove(struct pci_dev *pcidev)
+{
+ pci_release_regions(pcidev);
+ pci_disable_pcie_error_reporting(pcidev);
+ pci_disable_device(pcidev);
+}
+
+static struct pci_driver cci_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = cci_pcie_id_tbl,
+ .probe = cci_pci_probe,
+ .remove = cci_pci_remove,
+};
+
+static int __init ccidrv_init(void)
+{
+ pr_info("Intel(R) FPGA PCIe Driver: Version %s\n", DRV_VERSION);
+
+ return pci_register_driver(&cci_pci_driver);
+}
+
+static void __exit ccidrv_exit(void)
+{
+ pci_unregister_driver(&cci_pci_driver);
+}
+
+module_init(ccidrv_init);
+module_exit(ccidrv_exit);
+
+MODULE_DESCRIPTION("Intel FPGA PCIe Device Driver");
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("Dual BSD/GPL");
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Moritz Fischer <mdf@kernel.org> |
|---|---|
| Date | 2017-04-04 04:20 +0200 |
| Subject | Re: [PATCH 03/16] fpga: intel: add FPGA PCIe device driver |
| Message-ID | <tsmeC-6Y3-1@gated-at.bofh.it> |
| In reply to | #1613006 |
[Multipart message — attachments visible in raw view] — view raw
On Thu, Mar 30, 2017 at 08:08:03PM +0800, Wu Hao wrote:
> From: Zhang Yi <yi.z.zhang@intel.com>
>
> The Intel FPGA device appears as a PCIe device on the system. This patch
> implements the basic framework of the driver for Intel PCIe device which
> locates between CPU and Accelerated Function Units (AFUs).
>
> Signed-off-by: Tim Whisonant <tim.whisonant@intel.com>
> Signed-off-by: Enno Luebbers <enno.luebbers@intel.com>
> Signed-off-by: Shiva Rao <shiva.rao@intel.com>
> Signed-off-by: Christopher Rauer <christopher.rauer@intel.com>
> Signed-off-by: Zhang Yi <yi.z.zhang@intel.com>
> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> Signed-off-by: Wu Hao <hao.wu@intel.com>
> ---
> drivers/fpga/Kconfig | 2 +
> drivers/fpga/Makefile | 3 +
> drivers/fpga/intel/Kconfig | 27 +++++++++
> drivers/fpga/intel/LICENSE.BSD | 24 ++++++++
> drivers/fpga/intel/Makefile | 3 +
> drivers/fpga/intel/pcie.c | 129 +++++++++++++++++++++++++++++++++++++++++
> 6 files changed, 188 insertions(+)
> create mode 100644 drivers/fpga/intel/Kconfig
> create mode 100644 drivers/fpga/intel/LICENSE.BSD
> create mode 100644 drivers/fpga/intel/Makefile
> create mode 100644 drivers/fpga/intel/pcie.c
>
> diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
> index d99b640..4e49aee 100644
> --- a/drivers/fpga/Kconfig
> +++ b/drivers/fpga/Kconfig
> @@ -69,6 +69,8 @@ config ALTERA_FREEZE_BRIDGE
> isolate one region of the FPGA from the busses while that
> region is being reprogrammed.
>
> +source "drivers/fpga/intel/Kconfig"
> +
> endif # FPGA
>
> endmenu
> diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
> index 53a41d2..46f1a5d 100644
> --- a/drivers/fpga/Makefile
> +++ b/drivers/fpga/Makefile
> @@ -20,3 +20,6 @@ obj-$(CONFIG_ALTERA_FREEZE_BRIDGE) += altera-freeze-bridge.o
>
> # High Level Interfaces
> obj-$(CONFIG_FPGA_REGION) += fpga-region.o
> +
> +# Intel FPGA Support
> +obj-$(CONFIG_INTEL_FPGA) += intel/
> diff --git a/drivers/fpga/intel/Kconfig b/drivers/fpga/intel/Kconfig
> new file mode 100644
> index 0000000..bf402f3
> --- /dev/null
> +++ b/drivers/fpga/intel/Kconfig
> @@ -0,0 +1,27 @@
> +menuconfig INTEL_FPGA
> + tristate "Intel(R) FPGA support"
> + depends on FPGA_DEVICE
> + help
> + Select this option to enable driver support for Intel(R)
> + Field-Programmable Gate Array (FPGA) solutions. This driver
> + provides interfaces for userspace applications to configure,
> + enumerate, open, and access FPGA accelerators on platforms
> + equipped with Intel(R) FPGA solutions and enables system
> + level management functions such as FPGA reconfiguration,
> + power management, and virtualization.
> +
> + Say Y if your platform has this technology. Say N if unsure.
> +
> +if INTEL_FPGA
> +
> +config INTEL_FPGA_PCI
> + tristate "Intel FPGA PCIe Driver"
> + depends on PCI
> + help
> + This is the driver for the PCIe device which locates between
> + CPU and Accelerated Function Units (AFUs) and allows them to
> + communicate with each other.
> +
> + To compile this as a module, choose M here.
> +
> +endif
> diff --git a/drivers/fpga/intel/LICENSE.BSD b/drivers/fpga/intel/LICENSE.BSD
> new file mode 100644
> index 0000000..309d2b7
> --- /dev/null
> +++ b/drivers/fpga/intel/LICENSE.BSD
> @@ -0,0 +1,24 @@
> +Redistribution and use in source and binary forms, with or without
> +modification, are permitted provided that the following conditions
> +are met:
> + * Redistributions of source code must retain the above copyright
> + notice, this list of conditions and the following disclaimer.
> + * Redistributions in binary form must reproduce the above copyright
> + notice, this list of conditions and the following disclaimer in
> + the documentation and/or other materials provided with the
> + distribution.
> + * Neither the name of Intel Corporation nor the names of its
> + contributors may be used to endorse or promote products derived
> + from this software without specific prior written permission.
> +
> +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> diff --git a/drivers/fpga/intel/Makefile b/drivers/fpga/intel/Makefile
> new file mode 100644
> index 0000000..61fd8ea
> --- /dev/null
> +++ b/drivers/fpga/intel/Makefile
> @@ -0,0 +1,3 @@
> +obj-$(CONFIG_INTEL_FPGA_PCI) += intel-fpga-pci.o
> +
> +intel-fpga-pci-objs := pcie.o
> diff --git a/drivers/fpga/intel/pcie.c b/drivers/fpga/intel/pcie.c
> new file mode 100644
> index 0000000..132d9da
> --- /dev/null
> +++ b/drivers/fpga/intel/pcie.c
> @@ -0,0 +1,129 @@
> +/*
> + * Driver for Intel FPGA PCIe device
> + *
> + * Copyright (C) 2017 Intel Corporation, Inc.
> + *
> + * Authors:
> + * Zhang Yi <Yi.Z.Zhang@intel.com>
> + * Xiao Guangrong <guangrong.xiao@linux.intel.com>
> + * Joseph Grecco <joe.grecco@intel.com>
> + * Enno Luebbers <enno.luebbers@intel.com>
> + * Tim Whisonant <tim.whisonant@intel.com>
> + * Ananda Ravuri <ananda.ravuri@intel.com>
> + * Henry Mitchel <henry.mitchel@intel.com>
> + *
> + * This work is licensed under a dual BSD/GPLv2 license. When using or
> + * redistributing this file, you may do so under either license. See the
> + * LICENSE.BSD file under this directory for the BSD license and see
> + * the COPYING file in the top-level directory for the GPLv2 license.
> + */
> +
> +#include <linux/pci.h>
> +#include <linux/types.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/stddef.h>
> +#include <linux/errno.h>
> +#include <linux/aer.h>
> +
> +#define DRV_VERSION "EXPERIMENTAL VERSION"
Is that a leftover? :)
> +#define DRV_NAME "intel-fpga-pci"
> +
> +/* PCI Device ID */
> +#define PCIe_DEVICE_ID_PF_INT_5_X 0xBCBD
> +#define PCIe_DEVICE_ID_PF_INT_6_X 0xBCC0
> +#define PCIe_DEVICE_ID_PF_DSC_1_X 0x09C4
> +/* VF Device */
> +#define PCIe_DEVICE_ID_VF_INT_5_X 0xBCBF
> +#define PCIe_DEVICE_ID_VF_INT_6_X 0xBCC1
> +#define PCIe_DEVICE_ID_VF_DSC_1_X 0x09C5
> +
> +static struct pci_device_id cci_pcie_id_tbl[] = {
> + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_PF_INT_5_X),},
> + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_VF_INT_5_X),},
> + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_PF_INT_6_X),},
> + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_VF_INT_6_X),},
> + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_PF_DSC_1_X),},
> + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_VF_DSC_1_X),},
> + {0,}
> +};
> +MODULE_DEVICE_TABLE(pci, cci_pcie_id_tbl);
> +
> +static
> +int cci_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *pcidevid)
> +{
> + int ret;
> +
> + ret = pci_enable_device(pcidev);
> + if (ret < 0) {
> + dev_err(&pcidev->dev, "Failed to enable device %d.\n", ret);
> + goto exit;
Why not 'return ret' here ?
> + }
> +
> + ret = pci_enable_pcie_error_reporting(pcidev);
> + if (ret && ret != -EINVAL)
> + dev_info(&pcidev->dev, "PCIE AER unavailable %d.\n", ret);
What if it is EINVAL?
> +
> + ret = pci_request_regions(pcidev, DRV_NAME);
> + if (ret) {
> + dev_err(&pcidev->dev, "Failed to request regions.\n");
> + goto disable_error_report_exit;
> + }
> +
> + pci_set_master(pcidev);
> + pci_save_state(pcidev);
> +
> + if (!dma_set_mask(&pcidev->dev, DMA_BIT_MASK(64))) {
> + dma_set_coherent_mask(&pcidev->dev, DMA_BIT_MASK(64));
> + } else if (!dma_set_mask(&pcidev->dev, DMA_BIT_MASK(32))) {
> + dma_set_coherent_mask(&pcidev->dev, DMA_BIT_MASK(32));
> + } else {
> + ret = -EIO;
> + dev_err(&pcidev->dev, "No suitable DMA support available.\n");
> + goto release_region_exit;
> + }
> +
> + /* TODO: create and add the platform device per feature list */
> + return 0;
> +
> +release_region_exit:
> + pci_release_regions(pcidev);
> +disable_error_report_exit:
> + pci_disable_pcie_error_reporting(pcidev);
> + pci_disable_device(pcidev);
> +exit:
> + return ret;
If you return as suggested above, this can go away.
> +}
> +
> +static void cci_pci_remove(struct pci_dev *pcidev)
> +{
> + pci_release_regions(pcidev);
> + pci_disable_pcie_error_reporting(pcidev);
> + pci_disable_device(pcidev);
> +}
> +
> +static struct pci_driver cci_pci_driver = {
> + .name = DRV_NAME,
> + .id_table = cci_pcie_id_tbl,
> + .probe = cci_pci_probe,
> + .remove = cci_pci_remove,
> +};
> +
> +static int __init ccidrv_init(void)
> +{
> + pr_info("Intel(R) FPGA PCIe Driver: Version %s\n", DRV_VERSION);
> +
> + return pci_register_driver(&cci_pci_driver);
> +}
> +
> +static void __exit ccidrv_exit(void)
> +{
> + pci_unregister_driver(&cci_pci_driver);
> +}
> +
> +module_init(ccidrv_init);
> +module_exit(ccidrv_exit);
> +
> +MODULE_DESCRIPTION("Intel FPGA PCIe Device Driver");
> +MODULE_AUTHOR("Intel Corporation");
> +MODULE_LICENSE("Dual BSD/GPL");
> --
> 2.7.4
>
Cheers,
Moritz
[toc] | [prev] | [next] | [standalone]
| From | "Wu, Hao" <hao.wu@intel.com> |
|---|---|
| Date | 2017-04-05 15:20 +0200 |
| Subject | RE: [PATCH 03/16] fpga: intel: add FPGA PCIe device driver |
| Message-ID | <tsT0S-364-15@gated-at.bofh.it> |
| In reply to | #1615656 |
> > +#include <linux/pci.h>
> > +#include <linux/types.h>
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/stddef.h>
> > +#include <linux/errno.h>
> > +#include <linux/aer.h>
> > +
> > +#define DRV_VERSION "EXPERIMENTAL VERSION"
>
> Is that a leftover? :)
Sorry, will fix this.
> > +#define DRV_NAME "intel-fpga-pci"
> > +
> > +/* PCI Device ID */
> > +#define PCIe_DEVICE_ID_PF_INT_5_X 0xBCBD
> > +#define PCIe_DEVICE_ID_PF_INT_6_X 0xBCC0
> > +#define PCIe_DEVICE_ID_PF_DSC_1_X 0x09C4
> > +/* VF Device */
> > +#define PCIe_DEVICE_ID_VF_INT_5_X 0xBCBF
> > +#define PCIe_DEVICE_ID_VF_INT_6_X 0xBCC1
> > +#define PCIe_DEVICE_ID_VF_DSC_1_X 0x09C5
> > +
> > +static struct pci_device_id cci_pcie_id_tbl[] = {
> > + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_PF_INT_5_X),},
> > + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_VF_INT_5_X),},
> > + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_PF_INT_6_X),},
> > + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_VF_INT_6_X),},
> > + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_PF_DSC_1_X),},
> > + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_VF_DSC_1_X),},
> > + {0,}
> > +};
> > +MODULE_DEVICE_TABLE(pci, cci_pcie_id_tbl);
> > +
> > +static
> > +int cci_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *pcidevid)
> > +{
> > + int ret;
> > +
> > + ret = pci_enable_device(pcidev);
> > + if (ret < 0) {
> > + dev_err(&pcidev->dev, "Failed to enable device %d.\n", ret);
> > + goto exit;
> Why not 'return ret' here ?
Yes, you are right, will fix this.
> > + }
> > +
> > + ret = pci_enable_pcie_error_reporting(pcidev);
> > + if (ret && ret != -EINVAL)
> > + dev_info(&pcidev->dev, "PCIE AER unavailable %d.\n", ret);
>
> What if it is EINVAL?
pci_enable_pcie_error_reporting is always return -EINVAL when CONFIG_PCIEAER is not selected.
Then we don't need this boring message. : )
>
> > +
> > + ret = pci_request_regions(pcidev, DRV_NAME);
> > + if (ret) {
> > + dev_err(&pcidev->dev, "Failed to request regions.\n");
> > + goto disable_error_report_exit;
> > + }
> > +
> > + pci_set_master(pcidev);
> > + pci_save_state(pcidev);
> > +
> > + if (!dma_set_mask(&pcidev->dev, DMA_BIT_MASK(64))) {
> > + dma_set_coherent_mask(&pcidev->dev, DMA_BIT_MASK(64));
> > + } else if (!dma_set_mask(&pcidev->dev, DMA_BIT_MASK(32))) {
> > + dma_set_coherent_mask(&pcidev->dev, DMA_BIT_MASK(32));
> > + } else {
> > + ret = -EIO;
> > + dev_err(&pcidev->dev, "No suitable DMA support available.\n");
> > + goto release_region_exit;
> > + }
> > +
> > + /* TODO: create and add the platform device per feature list */
> > + return 0;
> > +
> > +release_region_exit:
> > + pci_release_regions(pcidev);
> > +disable_error_report_exit:
> > + pci_disable_pcie_error_reporting(pcidev);
> > + pci_disable_device(pcidev);
> > +exit:
> > + return ret;
> If you return as suggested above, this can go away.
Yes, you are right. Will fix this in next version.
Thanks a lot for your review and comments. : )
Hao
[toc] | [prev] | [next] | [standalone]
| From | Wu Hao <hao.wu@intel.com> |
|---|---|
| Date | 2017-03-30 14:20 +0200 |
| Subject | [PATCH 15/16] fpga: intel: afu: add user afu sub feature support |
| Message-ID | <tqHdw-69w-21@gated-at.bofh.it> |
| In reply to | #1613003 |
From: Xiao Guangrong <guangrong.xiao@linux.intel.com>
User Accelerated Function Unit sub feature exposes the MMIO region of
the AFU. After valid green bitstream (GBS) is programmed and port is
enabled, then this MMIO region could be accessed.
This patch adds support to enumerate the AFU MMIO region and expose it
to userspace via mmap file operation. Below interfaces are exposed to user:
Sysfs interface:
* /sys/class/fpga/<fpga.x>/<intel-fpga-port.x>/afu_id
Read-only. Indicate which green bitstream is programmed to this AFU.
Ioctl interfaces:
* FPGA_PORT_GET_INFO
Provide info to userspace on the number of supported region.
Only UAFU region is supported now.
* FPGA_PORT_GET_REGION_INFO
Provide region information, including access permission, region size,
offset from the start of device fd.
Signed-off-by: Tim Whisonant <tim.whisonant@intel.com>
Signed-off-by: Enno Luebbers <enno.luebbers@intel.com>
Signed-off-by: Shiva Rao <shiva.rao@intel.com>
Signed-off-by: Christopher Rauer <christopher.rauer@intel.com>
Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
Signed-off-by: Wu Hao <hao.wu@intel.com>
---
drivers/fpga/intel/Makefile | 2 +-
drivers/fpga/intel/afu-main.c | 204 +++++++++++++++++++++++++++++++++++++++-
drivers/fpga/intel/afu-region.c | 129 +++++++++++++++++++++++++
drivers/fpga/intel/afu.h | 54 +++++++++++
include/uapi/linux/intel-fpga.h | 47 +++++++++
5 files changed, 432 insertions(+), 4 deletions(-)
create mode 100644 drivers/fpga/intel/afu-region.c
create mode 100644 drivers/fpga/intel/afu.h
diff --git a/drivers/fpga/intel/Makefile b/drivers/fpga/intel/Makefile
index 53a54ab..5c33216 100644
--- a/drivers/fpga/intel/Makefile
+++ b/drivers/fpga/intel/Makefile
@@ -4,4 +4,4 @@ obj-$(CONFIG_INTEL_FPGA_AFU) += intel-fpga-afu.o
intel-fpga-pci-objs := pcie.o feature-dev.o
intel-fpga-fme-objs := fme-main.o fme-pr.o
-intel-fpga-afu-objs := afu-main.o
+intel-fpga-afu-objs := afu-main.o afu-region.o
diff --git a/drivers/fpga/intel/afu-main.c b/drivers/fpga/intel/afu-main.c
index 89d4b2f..db2aec3 100644
--- a/drivers/fpga/intel/afu-main.c
+++ b/drivers/fpga/intel/afu-main.c
@@ -20,9 +20,10 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/uaccess.h>
#include <linux/intel-fpga.h>
-#include "feature-dev.h"
+#include "afu.h"
static ssize_t
id_show(struct device *dev, struct device_attribute *attr, char *buf)
@@ -82,12 +83,69 @@ struct feature_ops port_hdr_ops = {
.ioctl = port_hdr_ioctl,
};
+static ssize_t
+afu_id_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct feature_platform_data *pdata = dev_get_platdata(dev);
+ struct feature_port_header *port_hdr =
+ get_feature_ioaddr_by_index(dev, PORT_FEATURE_ID_UAFU);
+ u64 guidl;
+ u64 guidh;
+
+ mutex_lock(&pdata->lock);
+ guidl = readq(&port_hdr->afu_header.guid.b[0]);
+ guidh = readq(&port_hdr->afu_header.guid.b[8]);
+ mutex_unlock(&pdata->lock);
+
+ return scnprintf(buf, PAGE_SIZE, "%016llx%016llx\n", guidh, guidl);
+}
+static DEVICE_ATTR_RO(afu_id);
+
+static const struct attribute *port_uafu_attrs[] = {
+ &dev_attr_afu_id.attr,
+ NULL
+};
+
+static int port_uafu_init(struct platform_device *pdev, struct feature *feature)
+{
+ struct resource *res = &pdev->resource[feature->resource_index];
+ u32 flags = FPGA_REGION_READ | FPGA_REGION_WRITE | FPGA_REGION_MMAP;
+ int ret;
+
+ dev_dbg(&pdev->dev, "PORT AFU Init.\n");
+
+ ret = afu_region_add(dev_get_platdata(&pdev->dev),
+ FPGA_PORT_INDEX_UAFU, resource_size(res),
+ res->start, flags);
+ if (ret)
+ return ret;
+
+ return sysfs_create_files(&pdev->dev.kobj, port_uafu_attrs);
+}
+
+static void port_uafu_uinit(struct platform_device *pdev,
+ struct feature *feature)
+{
+ dev_dbg(&pdev->dev, "PORT AFU UInit.\n");
+
+ sysfs_remove_files(&pdev->dev.kobj, port_uafu_attrs);
+}
+
+struct feature_ops port_uafu_ops = {
+ .init = port_uafu_init,
+ .uinit = port_uafu_uinit,
+};
+
static struct feature_driver port_feature_drvs[] = {
{
.name = PORT_FEATURE_HEADER,
.ops = &port_hdr_ops,
},
{
+ .name = PORT_FEATURE_UAFU,
+ .ops = &port_uafu_ops,
+ },
+ {
.ops = NULL,
}
};
@@ -131,6 +189,64 @@ static long afu_ioctl_check_extension(struct feature_platform_data *pdata,
return 0;
}
+static long
+afu_ioctl_get_info(struct feature_platform_data *pdata, void __user *arg)
+{
+ struct fpga_port_info info;
+ struct fpga_afu *afu;
+ unsigned long minsz;
+
+ minsz = offsetofend(struct fpga_port_info, num_umsgs);
+
+ if (copy_from_user(&info, arg, minsz))
+ return -EFAULT;
+
+ if (info.argsz < minsz)
+ return -EINVAL;
+
+ mutex_lock(&pdata->lock);
+ afu = fpga_pdata_get_private(pdata);
+ info.flags = 0;
+ info.num_regions = afu->num_regions;
+ info.num_umsgs = afu->num_umsgs;
+ mutex_unlock(&pdata->lock);
+
+ if (copy_to_user(arg, &info, sizeof(info)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static long
+afu_ioctl_get_region_info(struct feature_platform_data *pdata, void __user *arg)
+{
+ struct fpga_port_region_info rinfo;
+ struct fpga_afu_region region;
+ unsigned long minsz;
+ long ret;
+
+ minsz = offsetofend(struct fpga_port_region_info, offset);
+
+ if (copy_from_user(&rinfo, arg, minsz))
+ return -EFAULT;
+
+ if (rinfo.argsz < minsz || rinfo.padding)
+ return -EINVAL;
+
+ ret = afu_get_region_by_index(pdata, rinfo.index, ®ion);
+ if (ret)
+ return ret;
+
+ rinfo.flags = region.flags;
+ rinfo.size = region.size;
+ rinfo.offset = region.offset;
+
+ if (copy_to_user(arg, &rinfo, sizeof(rinfo)))
+ return -EFAULT;
+
+ return 0;
+}
+
static long afu_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct platform_device *pdev = filp->private_data;
@@ -145,6 +261,10 @@ static long afu_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return FPGA_API_VERSION;
case FPGA_CHECK_EXTENSION:
return afu_ioctl_check_extension(pdata, arg);
+ case FPGA_PORT_GET_INFO:
+ return afu_ioctl_get_info(pdata, (void __user *)arg);
+ case FPGA_PORT_GET_REGION_INFO:
+ return afu_ioctl_get_region_info(pdata, (void __user *)arg);
default:
/*
* Let sub-feature's ioctl function to handle the cmd
@@ -165,27 +285,104 @@ static long afu_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return -EINVAL;
}
+static int afu_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct fpga_afu_region region;
+ struct platform_device *pdev = filp->private_data;
+ struct feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ u64 size = vma->vm_end - vma->vm_start;
+ u64 offset;
+ int ret;
+
+ if (!(vma->vm_flags & VM_SHARED))
+ return -EINVAL;
+
+ offset = vma->vm_pgoff << PAGE_SHIFT;
+ ret = afu_get_region_by_offset(pdata, offset, size, ®ion);
+ if (ret)
+ return ret;
+
+ if (!(region.flags & FPGA_REGION_MMAP))
+ return -EINVAL;
+
+ if ((vma->vm_flags & VM_READ) && !(region.flags & FPGA_REGION_READ))
+ return -EPERM;
+
+ if ((vma->vm_flags & VM_WRITE) && !(region.flags & FPGA_REGION_WRITE))
+ return -EPERM;
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ return remap_pfn_range(vma, vma->vm_start,
+ (region.phys + (offset - region.offset)) >> PAGE_SHIFT,
+ size, vma->vm_page_prot);
+}
+
static const struct file_operations afu_fops = {
.owner = THIS_MODULE,
.open = afu_open,
.release = afu_release,
.unlocked_ioctl = afu_ioctl,
+ .mmap = afu_mmap,
};
+static int afu_dev_init(struct platform_device *pdev)
+{
+ struct fpga_afu *afu;
+ struct feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+
+ afu = devm_kzalloc(&pdev->dev, sizeof(*afu), GFP_KERNEL);
+ if (!afu)
+ return -ENOMEM;
+
+ afu->pdata = pdata;
+
+ mutex_lock(&pdata->lock);
+ fpga_pdata_set_private(pdata, afu);
+ afu_region_init(pdata);
+ mutex_unlock(&pdata->lock);
+ return 0;
+}
+
+static int afu_dev_destroy(struct platform_device *pdev)
+{
+ struct feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct fpga_afu *afu;
+
+ mutex_lock(&pdata->lock);
+ afu = fpga_pdata_get_private(pdata);
+ afu_region_destroy(pdata);
+ fpga_pdata_set_private(pdata, NULL);
+ mutex_unlock(&pdata->lock);
+
+ devm_kfree(&pdev->dev, afu);
+ return 0;
+}
+
static int afu_probe(struct platform_device *pdev)
{
int ret;
dev_dbg(&pdev->dev, "%s\n", __func__);
+ ret = afu_dev_init(pdev);
+ if (ret)
+ goto exit;
+
ret = fpga_dev_feature_init(pdev, port_feature_drvs);
if (ret)
- return ret;
+ goto dev_destroy;
ret = fpga_register_dev_ops(pdev, &afu_fops, THIS_MODULE);
- if (ret)
+ if (ret) {
fpga_dev_feature_uinit(pdev);
+ goto dev_destroy;
+ }
+
+ return 0;
+dev_destroy:
+ afu_dev_destroy(pdev);
+exit:
return ret;
}
@@ -195,6 +392,7 @@ static int afu_remove(struct platform_device *pdev)
fpga_dev_feature_uinit(pdev);
fpga_unregister_dev_ops(pdev);
+ afu_dev_destroy(pdev);
return 0;
}
diff --git a/drivers/fpga/intel/afu-region.c b/drivers/fpga/intel/afu-region.c
new file mode 100644
index 0000000..1eec08f2
--- /dev/null
+++ b/drivers/fpga/intel/afu-region.c
@@ -0,0 +1,129 @@
+/*
+ * Driver for Intel FPGA Accelerated Function Unit (AFU) Region Management
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ * Wu Hao <hao.wu@intel.com>
+ * Xiao Guangrong <guangrong.xiao@linux.intel.com>
+ *
+ * This work is licensed under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license. See the
+ * LICENSE.BSD file under this directory for the BSD license and see
+ * the COPYING file in the top-level directory for the GPLv2 license.
+ */
+
+#include "afu.h"
+
+void afu_region_init(struct feature_platform_data *pdata)
+{
+ struct fpga_afu *afu = fpga_pdata_get_private(pdata);
+
+ INIT_LIST_HEAD(&afu->regions);
+}
+
+#define for_each_region(region, afu) \
+ list_for_each_entry((region), &(afu)->regions, node)
+static struct fpga_afu_region *get_region_by_index(struct fpga_afu *afu,
+ u32 region_index)
+{
+ struct fpga_afu_region *region;
+
+ for_each_region(region, afu)
+ if (region->index == region_index)
+ return region;
+
+ return NULL;
+}
+
+int afu_region_add(struct feature_platform_data *pdata, u32 region_index,
+ u64 region_size, u64 phys, u32 flags)
+{
+ struct fpga_afu_region *region;
+ struct fpga_afu *afu;
+ int ret = 0;
+
+ region = devm_kzalloc(&pdata->dev->dev, sizeof(*region), GFP_KERNEL);
+ if (!region)
+ return -ENOMEM;
+
+ region->index = region_index;
+ region->size = region_size;
+ region->phys = phys;
+ region->flags = flags;
+
+ mutex_lock(&pdata->lock);
+
+ afu = fpga_pdata_get_private(pdata);
+
+ /* check if @index already exists */
+ if (get_region_by_index(afu, region_index)) {
+ mutex_unlock(&pdata->lock);
+ ret = -EEXIST;
+ goto exit;
+ }
+
+ region_size = PAGE_ALIGN(region_size);
+ region->offset = afu->region_cur_offset;
+ list_add(®ion->node, &afu->regions);
+
+ afu->region_cur_offset += region_size;
+ afu->num_regions++;
+ mutex_unlock(&pdata->lock);
+ return 0;
+
+exit:
+ devm_kfree(&pdata->dev->dev, region);
+ return ret;
+}
+
+void afu_region_destroy(struct feature_platform_data *pdata)
+{
+ struct fpga_afu_region *tmp, *region;
+ struct fpga_afu *afu = fpga_pdata_get_private(pdata);
+
+ list_for_each_entry_safe(region, tmp, &afu->regions, node)
+ devm_kfree(&pdata->dev->dev, region);
+}
+
+int afu_get_region_by_index(struct feature_platform_data *pdata,
+ u32 region_index, struct fpga_afu_region *pregion)
+{
+ struct fpga_afu_region *region;
+ struct fpga_afu *afu;
+ int ret = 0;
+
+ mutex_lock(&pdata->lock);
+ afu = fpga_pdata_get_private(pdata);
+ region = get_region_by_index(afu, region_index);
+ if (!region) {
+ ret = -EINVAL;
+ goto exit;
+ }
+ *pregion = *region;
+exit:
+ mutex_unlock(&pdata->lock);
+ return ret;
+}
+
+int afu_get_region_by_offset(struct feature_platform_data *pdata,
+ u64 offset, u64 size,
+ struct fpga_afu_region *pregion)
+{
+ struct fpga_afu_region *region;
+ struct fpga_afu *afu;
+ int ret = 0;
+
+ mutex_lock(&pdata->lock);
+ afu = fpga_pdata_get_private(pdata);
+ for_each_region(region, afu)
+ if (region->offset <= offset &&
+ region->offset + region->size >= offset + size) {
+ *pregion = *region;
+ goto exit;
+ }
+ ret = -EINVAL;
+exit:
+ mutex_unlock(&pdata->lock);
+ return ret;
+}
diff --git a/drivers/fpga/intel/afu.h b/drivers/fpga/intel/afu.h
new file mode 100644
index 0000000..fca4dbc
--- /dev/null
+++ b/drivers/fpga/intel/afu.h
@@ -0,0 +1,54 @@
+/*
+ * Header file for Intel FPGA Accelerated Function Unit (AFU) Driver
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ * Wu Hao <hao.wu@intel.com>
+ * Xiao Guangrong <guangrong.xiao@linux.intel.com>
+ * Joseph Grecco <joe.grecco@intel.com>
+ * Enno Luebbers <enno.luebbers@intel.com>
+ * Tim Whisonant <tim.whisonant@intel.com>
+ * Ananda Ravuri <ananda.ravuri@intel.com>
+ * Henry Mitchel <henry.mitchel@intel.com>
+ *
+ * This work is licensed under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license. See the
+ * LICENSE.BSD file under this directory for the BSD license and see
+ * the COPYING file in the top-level directory for the GPLv2 license.
+ */
+
+#ifndef __INTEL_AFU_H
+#define __INTEL_AFU_H
+
+#include "feature-dev.h"
+
+struct fpga_afu_region {
+ u32 index;
+ u32 flags;
+ u64 size;
+ u64 offset;
+ u64 phys;
+ struct list_head node;
+};
+
+struct fpga_afu {
+ u64 region_cur_offset;
+ int num_regions;
+ u8 num_umsgs;
+ struct list_head regions;
+
+ struct feature_platform_data *pdata;
+};
+
+void afu_region_init(struct feature_platform_data *pdata);
+int afu_region_add(struct feature_platform_data *pdata, u32 region_index,
+ u64 region_size, u64 phys, u32 flags);
+void afu_region_destroy(struct feature_platform_data *pdata);
+int afu_get_region_by_index(struct feature_platform_data *pdata,
+ u32 region_index, struct fpga_afu_region *pregion);
+int afu_get_region_by_offset(struct feature_platform_data *pdata,
+ u64 offset, u64 size,
+ struct fpga_afu_region *pregion);
+
+#endif
diff --git a/include/uapi/linux/intel-fpga.h b/include/uapi/linux/intel-fpga.h
index 13b2e61..86a5168 100644
--- a/include/uapi/linux/intel-fpga.h
+++ b/include/uapi/linux/intel-fpga.h
@@ -66,6 +66,53 @@
#define FPGA_PORT_RESET _IO(FPGA_MAGIC, PORT_BASE + 0)
+/**
+ * FPGA_PORT_GET_INFO - _IOR(FPGA_MAGIC, PORT_BASE + 1, struct fpga_port_info)
+ *
+ * Retrieve information about the fpga port.
+ * Driver fills the info in provided struct fpga_port_info.
+ * Return: 0 on success, -errno on failure.
+ */
+struct fpga_port_info {
+ /* Input */
+ __u32 argsz; /* Structure length */
+ /* Output */
+ __u32 flags; /* Zero for now */
+ __u32 num_regions; /* The number of supported regions */
+ __u32 num_umsgs; /* The number of allocated umsgs */
+};
+
+#define FPGA_PORT_GET_INFO _IO(FPGA_MAGIC, PORT_BASE + 1)
+
+/**
+ * FPGA_PORT_GET_REGION_INFO - _IOWR(FPGA_MAGIC, PORT_BASE + 2,
+ * struct fpga_port_region_info)
+ *
+ * Retrieve information about a device region.
+ * Caller provides struct fpga_port_region_info with index value set.
+ * Driver returns the region info in other fields.
+ * Return: 0 on success, -errno on failure.
+ */
+struct fpga_port_region_info {
+ /* input */
+ __u32 argsz; /* Structure length */
+ /* Output */
+ __u32 flags; /* Access permission */
+#define FPGA_REGION_READ (1 << 0) /* Region is readable */
+#define FPGA_REGION_WRITE (1 << 1) /* Region is writable */
+#define FPGA_REGION_MMAP (1 << 2) /* Can be mmaped to userspace */
+ /* Input */
+ __u32 index; /* Region index */
+#define FPGA_PORT_INDEX_UAFU 0 /* User AFU */
+#define FPGA_PORT_INDEX_STP 1 /* Signal Tap */
+ __u32 padding;
+ /* Output */
+ __u64 size; /* Region size (bytes) */
+ __u64 offset; /* Region offset from start of device fd */
+};
+
+#define FPGA_PORT_GET_REGION_INFO _IO(FPGA_MAGIC, PORT_BASE + 2)
+
/* IOCTLs for FME file descriptor */
/**
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Wu Hao <hao.wu@intel.com> |
|---|---|
| Date | 2017-03-30 14:20 +0200 |
| Subject | [PATCH 12/16] fpga: intel: add FPGA Accelerated Function Unit driver basic framework |
| Message-ID | <tqHdw-69w-39@gated-at.bofh.it> |
| In reply to | #1613003 |
On Intel FPGA devices, the Accelerated Function Unit (AFU), can be
reprogrammed for different functions. It connects to the FPGA
infrastructure("blue bistream") via a Port. Port CSRs are implemented
separately from the AFU CSRs to provide control and status of the Port.
Once valid green bitstream is programmed into the AFU, it allows access
to the AFU CSRs in the AFU MMIO space.
This patch only implements basic driver framework for AFU, including
device file operation framework.
Signed-off-by: Tim Whisonant <tim.whisonant@intel.com>
Signed-off-by: Enno Luebbers <enno.luebbers@intel.com>
Signed-off-by: Shiva Rao <shiva.rao@intel.com>
Signed-off-by: Christopher Rauer <christopher.rauer@intel.com>
Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
Signed-off-by: Wu Hao <hao.wu@intel.com>
---
drivers/fpga/intel/Kconfig | 9 +++
drivers/fpga/intel/Makefile | 2 +
drivers/fpga/intel/afu-main.c | 161 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 172 insertions(+)
create mode 100644 drivers/fpga/intel/afu-main.c
diff --git a/drivers/fpga/intel/Kconfig b/drivers/fpga/intel/Kconfig
index 62e2160..0e7112f 100644
--- a/drivers/fpga/intel/Kconfig
+++ b/drivers/fpga/intel/Kconfig
@@ -32,4 +32,13 @@ config INTEL_FPGA_FME
all FPGA platform level management features. There shall be 1
FME per Intel FPGA.
+config INTEL_FPGA_AFU
+ tristate "Intel FPGA AFU Driver"
+ depends on INTEL_FPGA_PCI
+ help
+ This is the driver for FPGA Accelerated Function Unit (AFU) which
+ implements AFU and Port management features. A User AFU connects
+ to the FPGA infrastructure via a Port. There may be more than 1
+ Port/AFU per Intel FPGA.
+
endif
diff --git a/drivers/fpga/intel/Makefile b/drivers/fpga/intel/Makefile
index 0452cb6..53a54ab 100644
--- a/drivers/fpga/intel/Makefile
+++ b/drivers/fpga/intel/Makefile
@@ -1,5 +1,7 @@
obj-$(CONFIG_INTEL_FPGA_PCI) += intel-fpga-pci.o
obj-$(CONFIG_INTEL_FPGA_FME) += intel-fpga-fme.o
+obj-$(CONFIG_INTEL_FPGA_AFU) += intel-fpga-afu.o
intel-fpga-pci-objs := pcie.o feature-dev.o
intel-fpga-fme-objs := fme-main.o fme-pr.o
+intel-fpga-afu-objs := afu-main.o
diff --git a/drivers/fpga/intel/afu-main.c b/drivers/fpga/intel/afu-main.c
new file mode 100644
index 0000000..1c2035b
--- /dev/null
+++ b/drivers/fpga/intel/afu-main.c
@@ -0,0 +1,161 @@
+/*
+ * Driver for Intel FPGA Accelerated Function Unit (AFU)
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ * Wu Hao <hao.wu@intel.com>
+ * Xiao Guangrong <guangrong.xiao@linux.intel.com>
+ * Joseph Grecco <joe.grecco@intel.com>
+ * Enno Luebbers <enno.luebbers@intel.com>
+ * Tim Whisonant <tim.whisonant@intel.com>
+ * Ananda Ravuri <ananda.ravuri@intel.com>
+ * Henry Mitchel <henry.mitchel@intel.com>
+ *
+ * This work is licensed under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license. See the
+ * LICENSE.BSD file under this directory for the BSD license and see
+ * the COPYING file in the top-level directory for the GPLv2 license.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "feature-dev.h"
+
+static int port_hdr_init(struct platform_device *pdev, struct feature *feature)
+{
+ dev_dbg(&pdev->dev, "PORT HDR Init.\n");
+
+ return 0;
+}
+
+static void port_hdr_uinit(struct platform_device *pdev,
+ struct feature *feature)
+{
+ dev_dbg(&pdev->dev, "PORT HDR UInit.\n");
+}
+
+struct feature_ops port_hdr_ops = {
+ .init = port_hdr_init,
+ .uinit = port_hdr_uinit,
+};
+
+static struct feature_driver port_feature_drvs[] = {
+ {
+ .name = PORT_FEATURE_HEADER,
+ .ops = &port_hdr_ops,
+ },
+ {
+ .ops = NULL,
+ }
+};
+
+static int afu_open(struct inode *inode, struct file *filp)
+{
+ struct platform_device *fdev = fpga_inode_to_feature_dev(inode);
+ struct feature_platform_data *pdata;
+ int ret;
+
+ pdata = dev_get_platdata(&fdev->dev);
+ if (WARN_ON(!pdata))
+ return -ENODEV;
+
+ ret = feature_dev_use_begin(pdata);
+ if (ret)
+ return ret;
+
+ dev_dbg(&fdev->dev, "Device File Open\n");
+ filp->private_data = fdev;
+
+ return 0;
+}
+
+static int afu_release(struct inode *inode, struct file *filp)
+{
+ struct platform_device *pdev = filp->private_data;
+ struct feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+
+ dev_dbg(&pdev->dev, "Device File Release\n");
+
+ feature_dev_use_end(pdata);
+ return 0;
+}
+
+static long afu_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ struct platform_device *pdev = filp->private_data;
+ struct feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct feature *f;
+ long ret;
+
+ dev_dbg(&pdev->dev, "%s cmd 0x%x\n", __func__, cmd);
+
+ switch (cmd) {
+ default:
+ /*
+ * Let sub-feature's ioctl function to handle the cmd
+ * Sub-feature's ioctl returns -ENODEV when cmd is not
+ * handled in this sub feature, and returns 0 and other
+ * error code if cmd is handled.
+ */
+ fpga_dev_for_each_feature(pdata, f)
+ if (f->ops && f->ops->ioctl) {
+ ret = f->ops->ioctl(pdev, f, cmd, arg);
+ if (ret == -ENODEV)
+ continue;
+ else
+ return ret;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static const struct file_operations afu_fops = {
+ .owner = THIS_MODULE,
+ .open = afu_open,
+ .release = afu_release,
+ .unlocked_ioctl = afu_ioctl,
+};
+
+static int afu_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ dev_dbg(&pdev->dev, "%s\n", __func__);
+
+ ret = fpga_dev_feature_init(pdev, port_feature_drvs);
+ if (ret)
+ return ret;
+
+ ret = fpga_register_dev_ops(pdev, &afu_fops, THIS_MODULE);
+ if (ret)
+ fpga_dev_feature_uinit(pdev);
+
+ return ret;
+}
+
+static int afu_remove(struct platform_device *pdev)
+{
+ dev_dbg(&pdev->dev, "%s\n", __func__);
+
+ fpga_dev_feature_uinit(pdev);
+ fpga_unregister_dev_ops(pdev);
+ return 0;
+}
+
+static struct platform_driver afu_driver = {
+ .driver = {
+ .name = "intel-fpga-port",
+ },
+ .probe = afu_probe,
+ .remove = afu_remove,
+};
+
+module_platform_driver(afu_driver);
+
+MODULE_DESCRIPTION("Intel FPGA Accelerated Function Unit driver");
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:intel-fpga-port");
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Wu Hao <hao.wu@intel.com> |
|---|---|
| Date | 2017-03-30 14:20 +0200 |
| Subject | [PATCH 09/16] fpga: intel: fme: add header sub feature support |
| Message-ID | <tqHdw-69w-25@gated-at.bofh.it> |
| In reply to | #1613003 |
From: Kang Luwei <luwei.kang@intel.com>
The header register set is always present for FPGA Management Engine (FME),
this patch implements init and uinit function for header sub feature and
introduce several read-only sysfs interfaces for the capability and status.
Sysfs interfaces:
* /sys/class/fpga/<fpga.x>/<intel-fpga-fme.x>/ports_num
Read-only. Number of ports implemented
* /sys/class/fpga/<fpga.x>/<intel-fpga-fme.x>/bitstream_id
Read-only. Blue Bitstream identifier number
* /sys/class/fpga/<fpga.x>/<intel-fpga-fme.x>/bitstream_metadata
Read-only. Blue Bitstream meta data
Signed-off-by: Tim Whisonant <tim.whisonant@intel.com>
Signed-off-by: Enno Luebbers <enno.luebbers@intel.com>
Signed-off-by: Shiva Rao <shiva.rao@intel.com>
Signed-off-by: Christopher Rauer <christopher.rauer@intel.com>
Signed-off-by: Kang Luwei <luwei.kang@intel.com>
Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
Signed-off-by: Wu Hao <hao.wu@intel.com>
---
drivers/fpga/intel/feature-dev.h | 3 +++
drivers/fpga/intel/fme-main.c | 55 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 58 insertions(+)
diff --git a/drivers/fpga/intel/feature-dev.h b/drivers/fpga/intel/feature-dev.h
index 9d39b94..dccc283 100644
--- a/drivers/fpga/intel/feature-dev.h
+++ b/drivers/fpga/intel/feature-dev.h
@@ -124,6 +124,9 @@ struct feature_fme_header {
u64 rsvd[2];
struct feature_fme_capability capability;
struct feature_fme_port port[MAX_FPGA_PORT_NUM];
+ u64 rsvd1;
+ u64 bitstream_id;
+ u64 bitstream_md;
};
/* FME Thermal Sub Feature Register Set */
diff --git a/drivers/fpga/intel/fme-main.c b/drivers/fpga/intel/fme-main.c
index c603268..a7c69fc 100644
--- a/drivers/fpga/intel/fme-main.c
+++ b/drivers/fpga/intel/fme-main.c
@@ -23,15 +23,70 @@
#include "feature-dev.h"
+static ssize_t ports_num_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct feature_fme_header *fme_hdr
+ = get_feature_ioaddr_by_index(dev, FME_FEATURE_ID_HEADER);
+ struct feature_fme_capability fme_capability;
+
+ fme_capability.csr = readq(&fme_hdr->capability);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", fme_capability.num_ports);
+}
+static DEVICE_ATTR_RO(ports_num);
+
+static ssize_t bitstream_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct feature_fme_header *fme_hdr
+ = get_feature_ioaddr_by_index(dev, FME_FEATURE_ID_HEADER);
+ u64 bitstream_id = readq(&fme_hdr->bitstream_id);
+
+ return scnprintf(buf, PAGE_SIZE, "0x%llx\n",
+ (unsigned long long)bitstream_id);
+}
+static DEVICE_ATTR_RO(bitstream_id);
+
+static ssize_t bitstream_metadata_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct feature_fme_header *fme_hdr
+ = get_feature_ioaddr_by_index(dev, FME_FEATURE_ID_HEADER);
+ u64 bitstream_md = readq(&fme_hdr->bitstream_md);
+
+ return scnprintf(buf, PAGE_SIZE, "0x%llx\n",
+ (unsigned long long)bitstream_md);
+}
+static DEVICE_ATTR_RO(bitstream_metadata);
+
+static const struct attribute *fme_hdr_attrs[] = {
+ &dev_attr_ports_num.attr,
+ &dev_attr_bitstream_id.attr,
+ &dev_attr_bitstream_metadata.attr,
+ NULL,
+};
+
static int fme_hdr_init(struct platform_device *pdev, struct feature *feature)
{
+ struct feature_fme_header *fme_hdr = feature->ioaddr;
+ int ret;
+
dev_dbg(&pdev->dev, "FME HDR Init.\n");
+ dev_dbg(&pdev->dev, "FME cap %llx.\n",
+ (unsigned long long)fme_hdr->capability.csr);
+
+ ret = sysfs_create_files(&pdev->dev.kobj, fme_hdr_attrs);
+ if (ret)
+ return ret;
+
return 0;
}
static void fme_hdr_uinit(struct platform_device *pdev, struct feature *feature)
{
dev_dbg(&pdev->dev, "FME HDR UInit.\n");
+ sysfs_remove_files(&pdev->dev.kobj, fme_hdr_attrs);
}
struct feature_ops fme_hdr_ops = {
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Wu Hao <hao.wu@intel.com> |
|---|---|
| Date | 2017-03-30 14:20 +0200 |
| Subject | [PATCH 16/16] fpga: intel: afu: add FPGA_PORT_DMA_MAP/UNMAP ioctls support |
| Message-ID | <tqHdw-69w-23@gated-at.bofh.it> |
| In reply to | #1613003 |
DMA memory regions are required for Accelerated Function Unit (AFU) usage.
These two ioctls allow user space applications to map user memory regions
for dma, and unmap them after use. Iova is returned from driver to user
space application via FPGA_PORT_DMA_MAP ioctl. Application needs to unmap
it after use, otherwise, driver will unmap them in device file release
operation.
All the mapped regions are managed via a rb tree.
Ioctl interfaces:
* FPGA_PORT_DMA_MAP
Do the dma mapping per user_addr and length which provided by user.
Return iova in provided struct afu_port_dma_map.
* FPGA_PORT_DMA_UNMAP
Unmap the dma region per iova provided by user.
Signed-off-by: Tim Whisonant <tim.whisonant@intel.com>
Signed-off-by: Enno Luebbers <enno.luebbers@intel.com>
Signed-off-by: Shiva Rao <shiva.rao@intel.com>
Signed-off-by: Christopher Rauer <christopher.rauer@intel.com>
Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
Signed-off-by: Wu Hao <hao.wu@intel.com>
---
drivers/fpga/intel/Makefile | 2 +-
drivers/fpga/intel/afu-dma-region.c | 373 ++++++++++++++++++++++++++++++++++++
drivers/fpga/intel/afu-main.c | 61 +++++-
drivers/fpga/intel/afu.h | 18 ++
include/uapi/linux/intel-fpga.h | 37 ++++
5 files changed, 489 insertions(+), 2 deletions(-)
create mode 100644 drivers/fpga/intel/afu-dma-region.c
diff --git a/drivers/fpga/intel/Makefile b/drivers/fpga/intel/Makefile
index 5c33216..26ef583 100644
--- a/drivers/fpga/intel/Makefile
+++ b/drivers/fpga/intel/Makefile
@@ -4,4 +4,4 @@ obj-$(CONFIG_INTEL_FPGA_AFU) += intel-fpga-afu.o
intel-fpga-pci-objs := pcie.o feature-dev.o
intel-fpga-fme-objs := fme-main.o fme-pr.o
-intel-fpga-afu-objs := afu-main.o afu-region.o
+intel-fpga-afu-objs := afu-main.o afu-region.o afu-dma-region.o
diff --git a/drivers/fpga/intel/afu-dma-region.c b/drivers/fpga/intel/afu-dma-region.c
new file mode 100644
index 0000000..5a525f1
--- /dev/null
+++ b/drivers/fpga/intel/afu-dma-region.c
@@ -0,0 +1,373 @@
+/*
+ * Driver for Intel FPGA Accelerated Function Unit (AFU) DMA Region Management
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ * Wu Hao <hao.wu@intel.com>
+ * Xiao Guangrong <guangrong.xiao@linux.intel.com>
+ *
+ * This work is licensed under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license. See the
+ * LICENSE.BSD file under this directory for the BSD license and see
+ * the COPYING file in the top-level directory for the GPLv2 license.
+ */
+
+#include <linux/sched/signal.h>
+#include <linux/uaccess.h>
+
+#include "afu.h"
+
+static void put_all_pages(struct page **pages, int npages)
+{
+ int i;
+
+ for (i = 0; i < npages; i++)
+ if (pages[i] != NULL)
+ put_page(pages[i]);
+}
+
+void afu_dma_region_init(struct feature_platform_data *pdata)
+{
+ struct fpga_afu *afu = fpga_pdata_get_private(pdata);
+
+ afu->dma_regions = RB_ROOT;
+}
+
+static long afu_dma_adjust_locked_vm(struct device *dev, long npages, bool incr)
+{
+ unsigned long locked, lock_limit;
+ int ret = 0;
+
+ /* the task is exiting. */
+ if (!current->mm)
+ return 0;
+
+ down_write(¤t->mm->mmap_sem);
+
+ if (incr) {
+ locked = current->mm->locked_vm + npages;
+ lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+
+ if (locked > lock_limit && !capable(CAP_IPC_LOCK))
+ ret = -ENOMEM;
+ else
+ current->mm->locked_vm += npages;
+ } else {
+
+ if (WARN_ON_ONCE(npages > current->mm->locked_vm))
+ npages = current->mm->locked_vm;
+ current->mm->locked_vm -= npages;
+ }
+
+ dev_dbg(dev, "[%d] RLIMIT_MEMLOCK %c%ld %ld/%ld%s\n", current->pid,
+ incr ? '+' : '-',
+ npages << PAGE_SHIFT,
+ current->mm->locked_vm << PAGE_SHIFT,
+ rlimit(RLIMIT_MEMLOCK),
+ ret ? "- execeeded" : "");
+
+ up_write(¤t->mm->mmap_sem);
+
+ return ret;
+}
+
+static long afu_dma_pin_pages(struct feature_platform_data *pdata,
+ struct fpga_afu_dma_region *region)
+{
+ long npages = region->length >> PAGE_SHIFT;
+ struct device *dev = &pdata->dev->dev;
+ long ret, pinned;
+
+ ret = afu_dma_adjust_locked_vm(dev, npages, true);
+ if (ret)
+ return ret;
+
+ region->pages = kcalloc(npages, sizeof(struct page *), GFP_KERNEL);
+ if (!region->pages) {
+ afu_dma_adjust_locked_vm(dev, npages, false);
+ return -ENOMEM;
+ }
+
+ pinned = get_user_pages_fast(region->user_addr, npages, 1,
+ region->pages);
+ if (pinned < 0) {
+ ret = pinned;
+ goto err_put_pages;
+ } else if (pinned != npages) {
+ ret = -EFAULT;
+ goto err;
+ }
+
+ dev_dbg(dev, "%ld pages pinned\n", pinned);
+
+ return 0;
+
+err_put_pages:
+ put_all_pages(region->pages, pinned);
+err:
+ kfree(region->pages);
+ afu_dma_adjust_locked_vm(dev, npages, false);
+ return ret;
+}
+
+static void afu_dma_unpin_pages(struct feature_platform_data *pdata,
+ struct fpga_afu_dma_region *region)
+{
+ long npages = region->length >> PAGE_SHIFT;
+ struct device *dev = &pdata->dev->dev;
+
+ put_all_pages(region->pages, npages);
+ kfree(region->pages);
+ afu_dma_adjust_locked_vm(dev, npages, false);
+
+ dev_dbg(dev, "%ld pages unpinned\n", npages);
+}
+
+static bool afu_dma_check_continuous_pages(struct fpga_afu_dma_region *region)
+{
+ int npages = region->length >> PAGE_SHIFT;
+ int i;
+
+ for (i = 0; i < npages - 1; i++)
+ if (page_to_pfn(region->pages[i]) + 1 !=
+ page_to_pfn(region->pages[i+1]))
+ return false;
+
+ return true;
+}
+
+static bool dma_region_check_iova(struct fpga_afu_dma_region *region,
+ u64 iova, u64 size)
+{
+ if (!size && region->iova != iova)
+ return false;
+
+ return (region->iova <= iova) &&
+ (region->length + region->iova >= iova + size);
+}
+
+/* Need to be called with pdata->lock held */
+static int afu_dma_region_add(struct feature_platform_data *pdata,
+ struct fpga_afu_dma_region *region)
+{
+ struct fpga_afu *afu = fpga_pdata_get_private(pdata);
+ struct rb_node **new, *parent = NULL;
+
+ dev_dbg(&pdata->dev->dev, "add region (iova = %llx)\n",
+ (unsigned long long)region->iova);
+
+ new = &(afu->dma_regions.rb_node);
+
+ while (*new) {
+ struct fpga_afu_dma_region *this;
+
+ this = container_of(*new, struct fpga_afu_dma_region, node);
+
+ parent = *new;
+
+ if (dma_region_check_iova(this, region->iova, region->length))
+ return -EEXIST;
+
+ if (region->iova < this->iova)
+ new = &((*new)->rb_left);
+ else if (region->iova > this->iova)
+ new = &((*new)->rb_right);
+ else
+ return -EEXIST;
+ }
+
+ rb_link_node(®ion->node, parent, new);
+ rb_insert_color(®ion->node, &afu->dma_regions);
+
+ return 0;
+}
+
+/* Need to be called with pdata->lock held */
+static void afu_dma_region_remove(struct feature_platform_data *pdata,
+ struct fpga_afu_dma_region *region)
+{
+ struct fpga_afu *afu;
+
+ dev_dbg(&pdata->dev->dev, "del region (iova = %llx)\n",
+ (unsigned long long)region->iova);
+
+ afu = fpga_pdata_get_private(pdata);
+ rb_erase(®ion->node, &afu->dma_regions);
+}
+
+/* Need to be called with pdata->lock held */
+void afu_dma_region_destroy(struct feature_platform_data *pdata)
+{
+ struct fpga_afu *afu = fpga_pdata_get_private(pdata);
+ struct rb_node *node = rb_first(&afu->dma_regions);
+ struct fpga_afu_dma_region *region;
+
+ while (node) {
+ region = container_of(node, struct fpga_afu_dma_region, node);
+
+ dev_dbg(&pdata->dev->dev, "del region (iova = %llx)\n",
+ (unsigned long long)region->iova);
+
+ rb_erase(node, &afu->dma_regions);
+
+ if (region->iova)
+ dma_unmap_page(fpga_pdata_to_pcidev(pdata),
+ region->iova, region->length,
+ DMA_BIDIRECTIONAL);
+
+ if (region->pages)
+ afu_dma_unpin_pages(pdata, region);
+
+ node = rb_next(node);
+ kfree(region);
+ }
+}
+
+/*
+ * It finds the dma region from the rbtree based on @iova and @size:
+ * - if @size == 0, it finds the dma region which starts from @iova
+ * - otherwise, it finds the dma region which fully contains
+ * [@iova, @iova+size)
+ * If nothing is matched returns NULL.
+ *
+ * Need to be called with pdata->lock held.
+ */
+struct fpga_afu_dma_region *
+afu_dma_region_find(struct feature_platform_data *pdata, u64 iova, u64 size)
+{
+ struct fpga_afu *afu = fpga_pdata_get_private(pdata);
+ struct rb_node *node = afu->dma_regions.rb_node;
+ struct device *dev = &pdata->dev->dev;
+
+ while (node) {
+ struct fpga_afu_dma_region *region;
+
+ region = container_of(node, struct fpga_afu_dma_region, node);
+
+ if (dma_region_check_iova(region, iova, size)) {
+ dev_dbg(dev, "find region (iova = %llx)\n",
+ (unsigned long long)region->iova);
+ return region;
+ }
+
+ if (iova < region->iova)
+ node = node->rb_left;
+ else if (iova > region->iova)
+ node = node->rb_right;
+ else
+ /* the iova region is not fully covered. */
+ break;
+ }
+
+ dev_dbg(dev, "region with iova %llx and size %llx is not found\n",
+ (unsigned long long)iova, (unsigned long long)size);
+ return NULL;
+}
+
+static struct fpga_afu_dma_region *
+afu_dma_region_find_iova(struct feature_platform_data *pdata, u64 iova)
+{
+ return afu_dma_region_find(pdata, iova, 0);
+}
+
+long afu_dma_map_region(struct feature_platform_data *pdata,
+ u64 user_addr, u64 length, u64 *iova)
+{
+ struct fpga_afu_dma_region *region;
+ int ret;
+
+ /*
+ * Check Inputs, only accept page-aligned user memory region with
+ * valid length.
+ */
+ if (!PAGE_ALIGNED(user_addr) || !PAGE_ALIGNED(length) || !length)
+ return -EINVAL;
+
+ /* Check overflow */
+ if (user_addr + length < user_addr)
+ return -EINVAL;
+
+ if (!access_ok(VERIFY_WRITE, user_addr, length))
+ return -EINVAL;
+
+ region = kzalloc(sizeof(*region), GFP_KERNEL);
+ if (!region)
+ return -ENOMEM;
+
+ region->user_addr = user_addr;
+ region->length = length;
+
+ /* Pin the user memory region */
+ ret = afu_dma_pin_pages(pdata, region);
+ if (ret) {
+ dev_err(&pdata->dev->dev, "fail to pin memory region\n");
+ goto free_region;
+ }
+
+ /* Only accept continuous pages, return error if no */
+ if (!afu_dma_check_continuous_pages(region)) {
+ dev_err(&pdata->dev->dev, "pages are not continuous\n");
+ ret = -EINVAL;
+ goto unpin_pages;
+ }
+
+ /* As pages are continuous then start to do DMA mapping */
+ region->iova = dma_map_page(fpga_pdata_to_pcidev(pdata),
+ region->pages[0], 0,
+ region->length,
+ DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(&pdata->dev->dev, region->iova)) {
+ dev_err(&pdata->dev->dev, "fail to map dma mapping\n");
+ ret = -EFAULT;
+ goto unpin_pages;
+ }
+
+ *iova = region->iova;
+
+ mutex_lock(&pdata->lock);
+ ret = afu_dma_region_add(pdata, region);
+ mutex_unlock(&pdata->lock);
+ if (ret) {
+ dev_err(&pdata->dev->dev, "fail to add dma region\n");
+ goto unmap_dma;
+ }
+
+ return 0;
+
+unmap_dma:
+ dma_unmap_page(fpga_pdata_to_pcidev(pdata),
+ region->iova, region->length, DMA_BIDIRECTIONAL);
+unpin_pages:
+ afu_dma_unpin_pages(pdata, region);
+free_region:
+ kfree(region);
+ return ret;
+}
+
+long afu_dma_unmap_region(struct feature_platform_data *pdata, u64 iova)
+{
+ struct fpga_afu_dma_region *region;
+
+ mutex_lock(&pdata->lock);
+ region = afu_dma_region_find_iova(pdata, iova);
+ if (!region) {
+ mutex_unlock(&pdata->lock);
+ return -EINVAL;
+ }
+
+ if (region->in_use) {
+ mutex_unlock(&pdata->lock);
+ return -EBUSY;
+ }
+
+ afu_dma_region_remove(pdata, region);
+ mutex_unlock(&pdata->lock);
+
+ dma_unmap_page(fpga_pdata_to_pcidev(pdata),
+ region->iova, region->length, DMA_BIDIRECTIONAL);
+ afu_dma_unpin_pages(pdata, region);
+ kfree(region);
+
+ return 0;
+}
diff --git a/drivers/fpga/intel/afu-main.c b/drivers/fpga/intel/afu-main.c
index db2aec3..782ff81 100644
--- a/drivers/fpga/intel/afu-main.c
+++ b/drivers/fpga/intel/afu-main.c
@@ -177,7 +177,11 @@ static int afu_release(struct inode *inode, struct file *filp)
dev_dbg(&pdev->dev, "Device File Release\n");
- fpga_port_reset(pdev);
+ mutex_lock(&pdata->lock);
+ __fpga_port_reset(pdev);
+ afu_dma_region_destroy(pdata);
+ mutex_unlock(&pdata->lock);
+
feature_dev_use_end(pdata);
return 0;
}
@@ -247,6 +251,55 @@ afu_ioctl_get_region_info(struct feature_platform_data *pdata, void __user *arg)
return 0;
}
+static long
+afu_ioctl_dma_map(struct feature_platform_data *pdata, void __user *arg)
+{
+ struct fpga_port_dma_map map;
+ unsigned long minsz;
+ long ret;
+
+ minsz = offsetofend(struct fpga_port_dma_map, iova);
+
+ if (copy_from_user(&map, arg, minsz))
+ return -EFAULT;
+
+ if (map.argsz < minsz || map.flags)
+ return -EINVAL;
+
+ ret = afu_dma_map_region(pdata, map.user_addr, map.length, &map.iova);
+ if (ret)
+ return ret;
+
+ if (copy_to_user(arg, &map, sizeof(map))) {
+ afu_dma_unmap_region(pdata, map.iova);
+ return -EFAULT;
+ }
+
+ dev_dbg(&pdata->dev->dev, "dma map: ua=%llx, len=%llx, iova=%llx\n",
+ (unsigned long long)map.user_addr,
+ (unsigned long long)map.length,
+ (unsigned long long)map.iova);
+
+ return 0;
+}
+
+static long
+afu_ioctl_dma_unmap(struct feature_platform_data *pdata, void __user *arg)
+{
+ struct fpga_port_dma_unmap unmap;
+ unsigned long minsz;
+
+ minsz = offsetofend(struct fpga_port_dma_unmap, iova);
+
+ if (copy_from_user(&unmap, arg, minsz))
+ return -EFAULT;
+
+ if (unmap.argsz < minsz || unmap.flags)
+ return -EINVAL;
+
+ return afu_dma_unmap_region(pdata, unmap.iova);
+}
+
static long afu_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct platform_device *pdev = filp->private_data;
@@ -265,6 +318,10 @@ static long afu_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return afu_ioctl_get_info(pdata, (void __user *)arg);
case FPGA_PORT_GET_REGION_INFO:
return afu_ioctl_get_region_info(pdata, (void __user *)arg);
+ case FPGA_PORT_DMA_MAP:
+ return afu_ioctl_dma_map(pdata, (void __user *)arg);
+ case FPGA_PORT_DMA_UNMAP:
+ return afu_ioctl_dma_unmap(pdata, (void __user *)arg);
default:
/*
* Let sub-feature's ioctl function to handle the cmd
@@ -339,6 +396,7 @@ static int afu_dev_init(struct platform_device *pdev)
mutex_lock(&pdata->lock);
fpga_pdata_set_private(pdata, afu);
afu_region_init(pdata);
+ afu_dma_region_init(pdata);
mutex_unlock(&pdata->lock);
return 0;
}
@@ -351,6 +409,7 @@ static int afu_dev_destroy(struct platform_device *pdev)
mutex_lock(&pdata->lock);
afu = fpga_pdata_get_private(pdata);
afu_region_destroy(pdata);
+ afu_dma_region_destroy(pdata);
fpga_pdata_set_private(pdata, NULL);
mutex_unlock(&pdata->lock);
diff --git a/drivers/fpga/intel/afu.h b/drivers/fpga/intel/afu.h
index fca4dbc..fb46bd3 100644
--- a/drivers/fpga/intel/afu.h
+++ b/drivers/fpga/intel/afu.h
@@ -32,11 +32,21 @@ struct fpga_afu_region {
struct list_head node;
};
+struct fpga_afu_dma_region {
+ u64 user_addr;
+ u64 length;
+ u64 iova;
+ struct page **pages;
+ struct rb_node node;
+ bool in_use;
+};
+
struct fpga_afu {
u64 region_cur_offset;
int num_regions;
u8 num_umsgs;
struct list_head regions;
+ struct rb_root dma_regions;
struct feature_platform_data *pdata;
};
@@ -51,4 +61,12 @@ int afu_get_region_by_offset(struct feature_platform_data *pdata,
u64 offset, u64 size,
struct fpga_afu_region *pregion);
+void afu_dma_region_init(struct feature_platform_data *pdata);
+void afu_dma_region_destroy(struct feature_platform_data *pdata);
+long afu_dma_map_region(struct feature_platform_data *pdata,
+ u64 user_addr, u64 length, u64 *iova);
+long afu_dma_unmap_region(struct feature_platform_data *pdata, u64 iova);
+struct fpga_afu_dma_region *afu_dma_region_find(
+ struct feature_platform_data *pdata, u64 iova, u64 size);
+
#endif
diff --git a/include/uapi/linux/intel-fpga.h b/include/uapi/linux/intel-fpga.h
index 86a5168..b584381 100644
--- a/include/uapi/linux/intel-fpga.h
+++ b/include/uapi/linux/intel-fpga.h
@@ -113,6 +113,43 @@ struct fpga_port_region_info {
#define FPGA_PORT_GET_REGION_INFO _IO(FPGA_MAGIC, PORT_BASE + 2)
+/**
+ * FPGA_PORT_DMA_MAP - _IOWR(FPGA_MAGIC, PORT_BASE + 3,
+ * struct fpga_port_dma_map)
+ *
+ * Map the dma memory per user_addr and length which are provided by caller.
+ * Driver fills the iova in provided struct afu_port_dma_map.
+ * This interface only accepts page-size aligned user memory for dma mapping.
+ * Return: 0 on success, -errno on failure.
+ */
+struct fpga_port_dma_map {
+ /* Input */
+ __u32 argsz; /* Structure length */
+ __u32 flags; /* Zero for now */
+ __u64 user_addr; /* Process virtual address */
+ __u64 length; /* Length of mapping (bytes)*/
+ /* Output */
+ __u64 iova; /* IO virtual address */
+};
+
+#define FPGA_PORT_DMA_MAP _IO(FPGA_MAGIC, PORT_BASE + 3)
+
+/**
+ * FPGA_PORT_DMA_UNMAP - _IOW(FPGA_MAGIC, PORT_BASE + 4,
+ * struct fpga_port_dma_unmap)
+ *
+ * Unmap the dma memory per iova provided by caller.
+ * Return: 0 on success, -errno on failure.
+ */
+struct fpga_port_dma_unmap {
+ /* Input */
+ __u32 argsz; /* Structure length */
+ __u32 flags; /* Zero for now */
+ __u64 iova; /* IO virtual address */
+};
+
+#define FPGA_PORT_DMA_UNMAP _IO(FPGA_MAGIC, PORT_BASE + 4)
+
/* IOCTLs for FME file descriptor */
/**
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Wu Hao <hao.wu@intel.com> |
|---|---|
| Date | 2017-03-30 14:20 +0200 |
| Subject | [PATCH 07/16] fpga: intel: add feature device infrastructure |
| Message-ID | <tqHdx-69w-45@gated-at.bofh.it> |
| In reply to | #1613003 |
From: Xiao Guangrong <guangrong.xiao@linux.intel.com>
This patch abstracts the common operations of the sub features, and defines
the feature_ops data structure, including init, uinit and ioctl function
pointers. And this patch adds some common helper functions for FME and AFU
drivers, e.g feature_dev_use_begin/end which are used to ensure exclusive
usage of the feature device file.
Signed-off-by: Tim Whisonant <tim.whisonant@intel.com>
Signed-off-by: Enno Luebbers <enno.luebbers@intel.com>
Signed-off-by: Shiva Rao <shiva.rao@intel.com>
Signed-off-by: Christopher Rauer <christopher.rauer@intel.com>
Signed-off-by: Kang Luwei <luwei.kang@intel.com>
Signed-off-by: Zhang Yi <yi.z.zhang@intel.com>
Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
Signed-off-by: Wu Hao <hao.wu@intel.com>
---
drivers/fpga/intel/feature-dev.c | 66 +++++++++++++++++++++++++++++++++++++
drivers/fpga/intel/feature-dev.h | 71 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 137 insertions(+)
diff --git a/drivers/fpga/intel/feature-dev.c b/drivers/fpga/intel/feature-dev.c
index ada6548..d729db8 100644
--- a/drivers/fpga/intel/feature-dev.c
+++ b/drivers/fpga/intel/feature-dev.c
@@ -59,6 +59,72 @@ int port_feature_num(void)
return PORT_FEATURE_ID_MAX;
}
+int fme_feature_to_resource_index(int feature_id)
+{
+ WARN_ON(feature_id >= FME_FEATURE_ID_MAX);
+ return feature_id;
+}
+
+void fpga_dev_feature_uinit(struct platform_device *pdev)
+{
+ struct feature *feature;
+ struct feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+
+ fpga_dev_for_each_feature(pdata, feature)
+ if (feature->ops) {
+ feature->ops->uinit(pdev, feature);
+ feature->ops = NULL;
+ }
+}
+EXPORT_SYMBOL_GPL(fpga_dev_feature_uinit);
+
+static int
+feature_instance_init(struct platform_device *pdev,
+ struct feature_platform_data *pdata,
+ struct feature *feature, struct feature_driver *drv)
+{
+ int ret;
+
+ WARN_ON(!feature->ioaddr);
+
+ ret = drv->ops->init(pdev, feature);
+ if (ret)
+ return ret;
+
+ feature->ops = drv->ops;
+ return ret;
+}
+
+int fpga_dev_feature_init(struct platform_device *pdev,
+ struct feature_driver *feature_drvs)
+{
+ struct feature *feature;
+ struct feature_driver *drv = feature_drvs;
+ struct feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ int ret;
+
+ while (drv->ops) {
+ fpga_dev_for_each_feature(pdata, feature) {
+ /* skip the feature which is not initialized. */
+ if (!feature->name)
+ continue;
+
+ if (!strcmp(drv->name, feature->name)) {
+ ret = feature_instance_init(pdev, pdata,
+ feature, drv);
+ if (ret)
+ goto exit;
+ }
+ }
+ drv++;
+ }
+ return 0;
+exit:
+ fpga_dev_feature_uinit(pdev);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_dev_feature_init);
+
struct fpga_chardev_info {
const char *name;
dev_t devt;
diff --git a/drivers/fpga/intel/feature-dev.h b/drivers/fpga/intel/feature-dev.h
index 38531f8..9d39b94 100644
--- a/drivers/fpga/intel/feature-dev.h
+++ b/drivers/fpga/intel/feature-dev.h
@@ -207,12 +207,20 @@ struct feature_port_stp {
#pragma pack()
+struct feature_driver {
+ const char *name;
+ struct feature_ops *ops;
+};
+
struct feature {
const char *name;
int resource_index;
void __iomem *ioaddr;
+ struct feature_ops *ops;
};
+#define DEV_STATUS_IN_USE 0
+
struct feature_platform_data {
/* list the feature dev to cci_drvdata->port_dev_list. */
struct list_head node;
@@ -220,6 +228,9 @@ struct feature_platform_data {
struct cdev cdev;
struct platform_device *dev;
unsigned int disable_count; /* count for port disable */
+ unsigned long dev_status;
+
+ void *private; /* ptr to feature dev private data */
struct platform_device *(*fpga_for_each_port)(struct platform_device *,
void *, int (*match)(struct platform_device *, void *));
@@ -228,6 +239,38 @@ struct feature_platform_data {
struct feature features[0];
};
+static inline int feature_dev_use_begin(struct feature_platform_data *pdata)
+{
+ /* Test and set IN_USE flags to ensure file is exclusively used */
+ if (test_and_set_bit_lock(DEV_STATUS_IN_USE, &pdata->dev_status))
+ return -EBUSY;
+
+ return 0;
+}
+
+static inline void feature_dev_use_end(struct feature_platform_data *pdata)
+{
+ clear_bit_unlock(DEV_STATUS_IN_USE, &pdata->dev_status);
+}
+
+static inline void
+fpga_pdata_set_private(struct feature_platform_data *pdata, void *private)
+{
+ pdata->private = private;
+}
+
+static inline void *fpga_pdata_get_private(struct feature_platform_data *pdata)
+{
+ return pdata->private;
+}
+
+struct feature_ops {
+ int (*init)(struct platform_device *pdev, struct feature *feature);
+ void (*uinit)(struct platform_device *pdev, struct feature *feature);
+ long (*ioctl)(struct platform_device *pdev, struct feature *feature,
+ unsigned int cmd, unsigned long arg);
+};
+
enum fme_feature_id {
FME_FEATURE_ID_HEADER = 0x0,
FME_FEATURE_ID_THERMAL_MGMT = 0x1,
@@ -261,6 +304,10 @@ int feature_platform_data_size(int num);
struct feature_platform_data *
feature_platform_data_alloc_and_init(struct platform_device *dev, int num);
+void fpga_dev_feature_uinit(struct platform_device *pdev);
+int fpga_dev_feature_init(struct platform_device *pdev,
+ struct feature_driver *feature_drvs);
+
enum fpga_devt_type {
FPGA_DEVT_FME,
FPGA_DEVT_PORT,
@@ -330,6 +377,15 @@ static inline int fpga_port_reset(struct platform_device *pdev)
return ret;
}
+static inline
+struct platform_device *fpga_inode_to_feature_dev(struct inode *inode)
+{
+ struct feature_platform_data *pdata;
+
+ pdata = container_of(inode->i_cdev, struct feature_platform_data, cdev);
+ return pdata->dev;
+}
+
static inline void __iomem *
get_feature_ioaddr_by_index(struct device *dev, int index)
{
@@ -338,12 +394,27 @@ get_feature_ioaddr_by_index(struct device *dev, int index)
return pdata->features[index].ioaddr;
}
+static inline bool is_feature_present(struct device *dev, int index)
+{
+ return !!get_feature_ioaddr_by_index(dev, index);
+}
+
static inline struct device *
fpga_feature_dev_to_pcidev(struct platform_device *dev)
{
return dev->dev.parent->parent;
}
+static inline struct device *
+fpga_pdata_to_pcidev(struct feature_platform_data *pdata)
+{
+ return fpga_feature_dev_to_pcidev(pdata->dev);
+}
+
+#define fpga_dev_for_each_feature(pdata, feature) \
+ for ((feature) = (pdata)->features; \
+ (feature) < (pdata)->features + (pdata)->num; (feature)++)
+
/*
* Wait register's _field to be changed to the given value (_expect's _field)
* by polling with given interval and timeout.
--
2.7.4
[toc] | [prev] | [next] | [standalone]
Page 1 of 4 [1] 2 3 4 Next page →
Back to top | Article view | linux.kernel
csiph-web