aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWu Hao <hao.wu@intel.com>2018-06-29 20:53:32 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-07-15 07:55:47 -0400
commite4664c0ee4ac44993c62d10b048ab0a960691da5 (patch)
treef40f47fa0c5ddadc371ff4772479c9b4a8306149
parent47c1b19c160fe1641469c145dba78fbbe48b996a (diff)
fpga: dfl: afu: add header sub feature support
The port header register set is always present for port, it is mainly for capability, control and status of the ports that AFU connected to. This patch implements header sub feature support. Below user interfaces are created by this patch. Sysfs interface: * /sys/class/fpga_region/<regionX>/<dfl-port.x>/id Read-only. Port ID. Ioctl interface: * DFL_FPGA_PORT_RESET Reset the FPGA Port and its AFU. 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> Acked-by: Alan Tull <atull@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--Documentation/ABI/testing/sysfs-platform-dfl-port7
-rw-r--r--drivers/fpga/dfl-afu-main.c79
-rw-r--r--include/uapi/linux/fpga-dfl.h17
3 files changed, 102 insertions, 1 deletions
diff --git a/Documentation/ABI/testing/sysfs-platform-dfl-port b/Documentation/ABI/testing/sysfs-platform-dfl-port
new file mode 100644
index 000000000000..cb91165f5397
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-dfl-port
@@ -0,0 +1,7 @@
1What: /sys/bus/platform/devices/dfl-port.0/id
2Date: June 2018
3KernelVersion: 4.19
4Contact: Wu Hao <hao.wu@intel.com>
5Description: Read-only. It returns id of this port. One DFL FPGA device
6 may have more than one port. Userspace could use this id to
7 distinguish different ports under same FPGA device.
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index a38d6a825e7e..d36b3e9f3984 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -16,6 +16,7 @@
16 16
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/fpga-dfl.h>
19 20
20#include "dfl.h" 21#include "dfl.h"
21 22
@@ -87,6 +88,41 @@ static int port_disable(struct platform_device *pdev)
87 return 0; 88 return 0;
88} 89}
89 90
91/*
92 * This function resets the FPGA Port and its accelerator (AFU) by function
93 * __port_disable and __port_enable (set port soft reset bit and then clear
94 * it). Userspace can do Port reset at any time, e.g. during DMA or Partial
95 * Reconfiguration. But it should never cause any system level issue, only
96 * functional failure (e.g. DMA or PR operation failure) and be recoverable
97 * from the failure.
98 *
99 * Note: the accelerator (AFU) is not accessible when its port is in reset
100 * (disabled). Any attempts on MMIO access to AFU while in reset, will
101 * result errors reported via port error reporting sub feature (if present).
102 */
103static int __port_reset(struct platform_device *pdev)
104{
105 int ret;
106
107 ret = port_disable(pdev);
108 if (!ret)
109 port_enable(pdev);
110
111 return ret;
112}
113
114static int port_reset(struct platform_device *pdev)
115{
116 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
117 int ret;
118
119 mutex_lock(&pdata->lock);
120 ret = __port_reset(pdev);
121 mutex_unlock(&pdata->lock);
122
123 return ret;
124}
125
90static int port_get_id(struct platform_device *pdev) 126static int port_get_id(struct platform_device *pdev)
91{ 127{
92 void __iomem *base; 128 void __iomem *base;
@@ -96,23 +132,63 @@ static int port_get_id(struct platform_device *pdev)
96 return FIELD_GET(PORT_CAP_PORT_NUM, readq(base + PORT_HDR_CAP)); 132 return FIELD_GET(PORT_CAP_PORT_NUM, readq(base + PORT_HDR_CAP));
97} 133}
98 134
135static ssize_t
136id_show(struct device *dev, struct device_attribute *attr, char *buf)
137{
138 int id = port_get_id(to_platform_device(dev));
139
140 return scnprintf(buf, PAGE_SIZE, "%d\n", id);
141}
142static DEVICE_ATTR_RO(id);
143
144static const struct attribute *port_hdr_attrs[] = {
145 &dev_attr_id.attr,
146 NULL,
147};
148
99static int port_hdr_init(struct platform_device *pdev, 149static int port_hdr_init(struct platform_device *pdev,
100 struct dfl_feature *feature) 150 struct dfl_feature *feature)
101{ 151{
102 dev_dbg(&pdev->dev, "PORT HDR Init.\n"); 152 dev_dbg(&pdev->dev, "PORT HDR Init.\n");
103 153
104 return 0; 154 port_reset(pdev);
155
156 return sysfs_create_files(&pdev->dev.kobj, port_hdr_attrs);
105} 157}
106 158
107static void port_hdr_uinit(struct platform_device *pdev, 159static void port_hdr_uinit(struct platform_device *pdev,
108 struct dfl_feature *feature) 160 struct dfl_feature *feature)
109{ 161{
110 dev_dbg(&pdev->dev, "PORT HDR UInit.\n"); 162 dev_dbg(&pdev->dev, "PORT HDR UInit.\n");
163
164 sysfs_remove_files(&pdev->dev.kobj, port_hdr_attrs);
165}
166
167static long
168port_hdr_ioctl(struct platform_device *pdev, struct dfl_feature *feature,
169 unsigned int cmd, unsigned long arg)
170{
171 long ret;
172
173 switch (cmd) {
174 case DFL_FPGA_PORT_RESET:
175 if (!arg)
176 ret = port_reset(pdev);
177 else
178 ret = -EINVAL;
179 break;
180 default:
181 dev_dbg(&pdev->dev, "%x cmd not handled", cmd);
182 ret = -ENODEV;
183 }
184
185 return ret;
111} 186}
112 187
113static const struct dfl_feature_ops port_hdr_ops = { 188static const struct dfl_feature_ops port_hdr_ops = {
114 .init = port_hdr_init, 189 .init = port_hdr_init,
115 .uinit = port_hdr_uinit, 190 .uinit = port_hdr_uinit,
191 .ioctl = port_hdr_ioctl,
116}; 192};
117 193
118static struct dfl_feature_driver port_feature_drvs[] = { 194static struct dfl_feature_driver port_feature_drvs[] = {
@@ -154,6 +230,7 @@ static int afu_release(struct inode *inode, struct file *filp)
154 230
155 pdata = dev_get_platdata(&pdev->dev); 231 pdata = dev_get_platdata(&pdev->dev);
156 232
233 port_reset(pdev);
157 dfl_feature_dev_use_end(pdata); 234 dfl_feature_dev_use_end(pdata);
158 235
159 return 0; 236 return 0;
diff --git a/include/uapi/linux/fpga-dfl.h b/include/uapi/linux/fpga-dfl.h
index 9666af85a8f5..e6b4dd26cc68 100644
--- a/include/uapi/linux/fpga-dfl.h
+++ b/include/uapi/linux/fpga-dfl.h
@@ -29,8 +29,11 @@
29#define DFL_FPGA_MAGIC 0xB6 29#define DFL_FPGA_MAGIC 0xB6
30 30
31#define DFL_FPGA_BASE 0 31#define DFL_FPGA_BASE 0
32#define DFL_PORT_BASE 0x40
32#define DFL_FME_BASE 0x80 33#define DFL_FME_BASE 0x80
33 34
35/* Common IOCTLs for both FME and AFU file descriptor */
36
34/** 37/**
35 * DFL_FPGA_GET_API_VERSION - _IO(DFL_FPGA_MAGIC, DFL_FPGA_BASE + 0) 38 * DFL_FPGA_GET_API_VERSION - _IO(DFL_FPGA_MAGIC, DFL_FPGA_BASE + 0)
36 * 39 *
@@ -49,6 +52,20 @@
49 52
50#define DFL_FPGA_CHECK_EXTENSION _IO(DFL_FPGA_MAGIC, DFL_FPGA_BASE + 1) 53#define DFL_FPGA_CHECK_EXTENSION _IO(DFL_FPGA_MAGIC, DFL_FPGA_BASE + 1)
51 54
55/* IOCTLs for AFU file descriptor */
56
57/**
58 * DFL_FPGA_PORT_RESET - _IO(DFL_FPGA_MAGIC, DFL_PORT_BASE + 0)
59 *
60 * Reset the FPGA Port and its AFU. No parameters are supported.
61 * Userspace can do Port reset at any time, e.g. during DMA or PR. But
62 * it should never cause any system level issue, only functional failure
63 * (e.g. DMA or PR operation failure) and be recoverable from the failure.
64 * Return: 0 on success, -errno of failure
65 */
66
67#define DFL_FPGA_PORT_RESET _IO(DFL_FPGA_MAGIC, DFL_PORT_BASE + 0)
68
52/* IOCTLs for FME file descriptor */ 69/* IOCTLs for FME file descriptor */
53 70
54/** 71/**