aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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/**