diff options
author | Moritz Fischer <mdf@kernel.org> | 2019-09-03 22:35:07 -0400 |
---|---|---|
committer | Moritz Fischer <mdf@kernel.org> | 2019-09-03 22:35:07 -0400 |
commit | af9ca4b0bd0502bb134f18d394a613be371d2352 (patch) | |
tree | 37b1159d4456e223981dddde4795f2061c83d14c /drivers/fpga | |
parent | cbb4a74478e9eef0f8ef437e95ef7645008988f7 (diff) | |
parent | 99097a214b0c15f7595ac8f2788662f3941c1992 (diff) |
Merge branch 'char-misc-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc into fpga-dfl-for-5.4
Diffstat (limited to 'drivers/fpga')
-rw-r--r-- | drivers/fpga/Kconfig | 1 | ||||
-rw-r--r-- | drivers/fpga/altera-ps-spi.c | 11 | ||||
-rw-r--r-- | drivers/fpga/dfl-afu-main.c | 165 | ||||
-rw-r--r-- | drivers/fpga/dfl-fme-main.c | 108 | ||||
-rw-r--r-- | drivers/fpga/dfl-fme-pr.c | 7 | ||||
-rw-r--r-- | drivers/fpga/dfl-fme.h | 3 | ||||
-rw-r--r-- | drivers/fpga/dfl-pci.c | 36 | ||||
-rw-r--r-- | drivers/fpga/dfl.c | 216 | ||||
-rw-r--r-- | drivers/fpga/dfl.h | 43 |
9 files changed, 549 insertions, 41 deletions
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index f50956ec1300..73c779e920ed 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig | |||
@@ -40,6 +40,7 @@ config ALTERA_PR_IP_CORE_PLAT | |||
40 | config FPGA_MGR_ALTERA_PS_SPI | 40 | config FPGA_MGR_ALTERA_PS_SPI |
41 | tristate "Altera FPGA Passive Serial over SPI" | 41 | tristate "Altera FPGA Passive Serial over SPI" |
42 | depends on SPI | 42 | depends on SPI |
43 | select BITREVERSE | ||
43 | help | 44 | help |
44 | FPGA manager driver support for Altera Arria/Cyclone/Stratix | 45 | FPGA manager driver support for Altera Arria/Cyclone/Stratix |
45 | using the passive serial interface over SPI. | 46 | using the passive serial interface over SPI. |
diff --git a/drivers/fpga/altera-ps-spi.c b/drivers/fpga/altera-ps-spi.c index a13f224303c6..0221dee8dd4c 100644 --- a/drivers/fpga/altera-ps-spi.c +++ b/drivers/fpga/altera-ps-spi.c | |||
@@ -210,7 +210,7 @@ static int altera_ps_write_complete(struct fpga_manager *mgr, | |||
210 | return -EIO; | 210 | return -EIO; |
211 | } | 211 | } |
212 | 212 | ||
213 | if (!IS_ERR(conf->confd)) { | 213 | if (conf->confd) { |
214 | if (!gpiod_get_raw_value_cansleep(conf->confd)) { | 214 | if (!gpiod_get_raw_value_cansleep(conf->confd)) { |
215 | dev_err(&mgr->dev, "CONF_DONE is inactive!\n"); | 215 | dev_err(&mgr->dev, "CONF_DONE is inactive!\n"); |
216 | return -EIO; | 216 | return -EIO; |
@@ -289,10 +289,13 @@ static int altera_ps_probe(struct spi_device *spi) | |||
289 | return PTR_ERR(conf->status); | 289 | return PTR_ERR(conf->status); |
290 | } | 290 | } |
291 | 291 | ||
292 | conf->confd = devm_gpiod_get(&spi->dev, "confd", GPIOD_IN); | 292 | conf->confd = devm_gpiod_get_optional(&spi->dev, "confd", GPIOD_IN); |
293 | if (IS_ERR(conf->confd)) { | 293 | if (IS_ERR(conf->confd)) { |
294 | dev_warn(&spi->dev, "Not using confd gpio: %ld\n", | 294 | dev_err(&spi->dev, "Failed to get confd gpio: %ld\n", |
295 | PTR_ERR(conf->confd)); | 295 | PTR_ERR(conf->confd)); |
296 | return PTR_ERR(conf->confd); | ||
297 | } else if (!conf->confd) { | ||
298 | dev_warn(&spi->dev, "Not using confd gpio"); | ||
296 | } | 299 | } |
297 | 300 | ||
298 | /* Register manager with unique name */ | 301 | /* Register manager with unique name */ |
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c index 02baa6a227c0..e50c45ed40ac 100644 --- a/drivers/fpga/dfl-afu-main.c +++ b/drivers/fpga/dfl-afu-main.c | |||
@@ -141,10 +141,148 @@ id_show(struct device *dev, struct device_attribute *attr, char *buf) | |||
141 | } | 141 | } |
142 | static DEVICE_ATTR_RO(id); | 142 | static DEVICE_ATTR_RO(id); |
143 | 143 | ||
144 | static const struct attribute *port_hdr_attrs[] = { | 144 | static ssize_t |
145 | ltr_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
146 | { | ||
147 | struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); | ||
148 | void __iomem *base; | ||
149 | u64 v; | ||
150 | |||
151 | base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); | ||
152 | |||
153 | mutex_lock(&pdata->lock); | ||
154 | v = readq(base + PORT_HDR_CTRL); | ||
155 | mutex_unlock(&pdata->lock); | ||
156 | |||
157 | return sprintf(buf, "%x\n", (u8)FIELD_GET(PORT_CTRL_LATENCY, v)); | ||
158 | } | ||
159 | |||
160 | static ssize_t | ||
161 | ltr_store(struct device *dev, struct device_attribute *attr, | ||
162 | const char *buf, size_t count) | ||
163 | { | ||
164 | struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); | ||
165 | void __iomem *base; | ||
166 | bool ltr; | ||
167 | u64 v; | ||
168 | |||
169 | if (kstrtobool(buf, <r)) | ||
170 | return -EINVAL; | ||
171 | |||
172 | base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); | ||
173 | |||
174 | mutex_lock(&pdata->lock); | ||
175 | v = readq(base + PORT_HDR_CTRL); | ||
176 | v &= ~PORT_CTRL_LATENCY; | ||
177 | v |= FIELD_PREP(PORT_CTRL_LATENCY, ltr ? 1 : 0); | ||
178 | writeq(v, base + PORT_HDR_CTRL); | ||
179 | mutex_unlock(&pdata->lock); | ||
180 | |||
181 | return count; | ||
182 | } | ||
183 | static DEVICE_ATTR_RW(ltr); | ||
184 | |||
185 | static ssize_t | ||
186 | ap1_event_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
187 | { | ||
188 | struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); | ||
189 | void __iomem *base; | ||
190 | u64 v; | ||
191 | |||
192 | base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); | ||
193 | |||
194 | mutex_lock(&pdata->lock); | ||
195 | v = readq(base + PORT_HDR_STS); | ||
196 | mutex_unlock(&pdata->lock); | ||
197 | |||
198 | return sprintf(buf, "%x\n", (u8)FIELD_GET(PORT_STS_AP1_EVT, v)); | ||
199 | } | ||
200 | |||
201 | static ssize_t | ||
202 | ap1_event_store(struct device *dev, struct device_attribute *attr, | ||
203 | const char *buf, size_t count) | ||
204 | { | ||
205 | struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); | ||
206 | void __iomem *base; | ||
207 | bool clear; | ||
208 | |||
209 | if (kstrtobool(buf, &clear) || !clear) | ||
210 | return -EINVAL; | ||
211 | |||
212 | base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); | ||
213 | |||
214 | mutex_lock(&pdata->lock); | ||
215 | writeq(PORT_STS_AP1_EVT, base + PORT_HDR_STS); | ||
216 | mutex_unlock(&pdata->lock); | ||
217 | |||
218 | return count; | ||
219 | } | ||
220 | static DEVICE_ATTR_RW(ap1_event); | ||
221 | |||
222 | static ssize_t | ||
223 | ap2_event_show(struct device *dev, struct device_attribute *attr, | ||
224 | char *buf) | ||
225 | { | ||
226 | struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); | ||
227 | void __iomem *base; | ||
228 | u64 v; | ||
229 | |||
230 | base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); | ||
231 | |||
232 | mutex_lock(&pdata->lock); | ||
233 | v = readq(base + PORT_HDR_STS); | ||
234 | mutex_unlock(&pdata->lock); | ||
235 | |||
236 | return sprintf(buf, "%x\n", (u8)FIELD_GET(PORT_STS_AP2_EVT, v)); | ||
237 | } | ||
238 | |||
239 | static ssize_t | ||
240 | ap2_event_store(struct device *dev, struct device_attribute *attr, | ||
241 | const char *buf, size_t count) | ||
242 | { | ||
243 | struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); | ||
244 | void __iomem *base; | ||
245 | bool clear; | ||
246 | |||
247 | if (kstrtobool(buf, &clear) || !clear) | ||
248 | return -EINVAL; | ||
249 | |||
250 | base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); | ||
251 | |||
252 | mutex_lock(&pdata->lock); | ||
253 | writeq(PORT_STS_AP2_EVT, base + PORT_HDR_STS); | ||
254 | mutex_unlock(&pdata->lock); | ||
255 | |||
256 | return count; | ||
257 | } | ||
258 | static DEVICE_ATTR_RW(ap2_event); | ||
259 | |||
260 | static ssize_t | ||
261 | power_state_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
262 | { | ||
263 | struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); | ||
264 | void __iomem *base; | ||
265 | u64 v; | ||
266 | |||
267 | base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); | ||
268 | |||
269 | mutex_lock(&pdata->lock); | ||
270 | v = readq(base + PORT_HDR_STS); | ||
271 | mutex_unlock(&pdata->lock); | ||
272 | |||
273 | return sprintf(buf, "0x%x\n", (u8)FIELD_GET(PORT_STS_PWR_STATE, v)); | ||
274 | } | ||
275 | static DEVICE_ATTR_RO(power_state); | ||
276 | |||
277 | static struct attribute *port_hdr_attrs[] = { | ||
145 | &dev_attr_id.attr, | 278 | &dev_attr_id.attr, |
279 | &dev_attr_ltr.attr, | ||
280 | &dev_attr_ap1_event.attr, | ||
281 | &dev_attr_ap2_event.attr, | ||
282 | &dev_attr_power_state.attr, | ||
146 | NULL, | 283 | NULL, |
147 | }; | 284 | }; |
285 | ATTRIBUTE_GROUPS(port_hdr); | ||
148 | 286 | ||
149 | static int port_hdr_init(struct platform_device *pdev, | 287 | static int port_hdr_init(struct platform_device *pdev, |
150 | struct dfl_feature *feature) | 288 | struct dfl_feature *feature) |
@@ -153,7 +291,7 @@ static int port_hdr_init(struct platform_device *pdev, | |||
153 | 291 | ||
154 | port_reset(pdev); | 292 | port_reset(pdev); |
155 | 293 | ||
156 | return sysfs_create_files(&pdev->dev.kobj, port_hdr_attrs); | 294 | return device_add_groups(&pdev->dev, port_hdr_groups); |
157 | } | 295 | } |
158 | 296 | ||
159 | static void port_hdr_uinit(struct platform_device *pdev, | 297 | static void port_hdr_uinit(struct platform_device *pdev, |
@@ -161,7 +299,7 @@ static void port_hdr_uinit(struct platform_device *pdev, | |||
161 | { | 299 | { |
162 | dev_dbg(&pdev->dev, "PORT HDR UInit.\n"); | 300 | dev_dbg(&pdev->dev, "PORT HDR UInit.\n"); |
163 | 301 | ||
164 | sysfs_remove_files(&pdev->dev.kobj, port_hdr_attrs); | 302 | device_remove_groups(&pdev->dev, port_hdr_groups); |
165 | } | 303 | } |
166 | 304 | ||
167 | static long | 305 | static long |
@@ -185,6 +323,11 @@ port_hdr_ioctl(struct platform_device *pdev, struct dfl_feature *feature, | |||
185 | return ret; | 323 | return ret; |
186 | } | 324 | } |
187 | 325 | ||
326 | static const struct dfl_feature_id port_hdr_id_table[] = { | ||
327 | {.id = PORT_FEATURE_ID_HEADER,}, | ||
328 | {0,} | ||
329 | }; | ||
330 | |||
188 | static const struct dfl_feature_ops port_hdr_ops = { | 331 | static const struct dfl_feature_ops port_hdr_ops = { |
189 | .init = port_hdr_init, | 332 | .init = port_hdr_init, |
190 | .uinit = port_hdr_uinit, | 333 | .uinit = port_hdr_uinit, |
@@ -214,10 +357,11 @@ afu_id_show(struct device *dev, struct device_attribute *attr, char *buf) | |||
214 | } | 357 | } |
215 | static DEVICE_ATTR_RO(afu_id); | 358 | static DEVICE_ATTR_RO(afu_id); |
216 | 359 | ||
217 | static const struct attribute *port_afu_attrs[] = { | 360 | static struct attribute *port_afu_attrs[] = { |
218 | &dev_attr_afu_id.attr, | 361 | &dev_attr_afu_id.attr, |
219 | NULL | 362 | NULL |
220 | }; | 363 | }; |
364 | ATTRIBUTE_GROUPS(port_afu); | ||
221 | 365 | ||
222 | static int port_afu_init(struct platform_device *pdev, | 366 | static int port_afu_init(struct platform_device *pdev, |
223 | struct dfl_feature *feature) | 367 | struct dfl_feature *feature) |
@@ -234,7 +378,7 @@ static int port_afu_init(struct platform_device *pdev, | |||
234 | if (ret) | 378 | if (ret) |
235 | return ret; | 379 | return ret; |
236 | 380 | ||
237 | return sysfs_create_files(&pdev->dev.kobj, port_afu_attrs); | 381 | return device_add_groups(&pdev->dev, port_afu_groups); |
238 | } | 382 | } |
239 | 383 | ||
240 | static void port_afu_uinit(struct platform_device *pdev, | 384 | static void port_afu_uinit(struct platform_device *pdev, |
@@ -242,9 +386,14 @@ static void port_afu_uinit(struct platform_device *pdev, | |||
242 | { | 386 | { |
243 | dev_dbg(&pdev->dev, "PORT AFU UInit.\n"); | 387 | dev_dbg(&pdev->dev, "PORT AFU UInit.\n"); |
244 | 388 | ||
245 | sysfs_remove_files(&pdev->dev.kobj, port_afu_attrs); | 389 | device_remove_groups(&pdev->dev, port_afu_groups); |
246 | } | 390 | } |
247 | 391 | ||
392 | static const struct dfl_feature_id port_afu_id_table[] = { | ||
393 | {.id = PORT_FEATURE_ID_AFU,}, | ||
394 | {0,} | ||
395 | }; | ||
396 | |||
248 | static const struct dfl_feature_ops port_afu_ops = { | 397 | static const struct dfl_feature_ops port_afu_ops = { |
249 | .init = port_afu_init, | 398 | .init = port_afu_init, |
250 | .uinit = port_afu_uinit, | 399 | .uinit = port_afu_uinit, |
@@ -252,11 +401,11 @@ static const struct dfl_feature_ops port_afu_ops = { | |||
252 | 401 | ||
253 | static struct dfl_feature_driver port_feature_drvs[] = { | 402 | static struct dfl_feature_driver port_feature_drvs[] = { |
254 | { | 403 | { |
255 | .id = PORT_FEATURE_ID_HEADER, | 404 | .id_table = port_hdr_id_table, |
256 | .ops = &port_hdr_ops, | 405 | .ops = &port_hdr_ops, |
257 | }, | 406 | }, |
258 | { | 407 | { |
259 | .id = PORT_FEATURE_ID_AFU, | 408 | .id_table = port_afu_id_table, |
260 | .ops = &port_afu_ops, | 409 | .ops = &port_afu_ops, |
261 | }, | 410 | }, |
262 | { | 411 | { |
diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c index 086ad2420ade..f033f1cfd3ed 100644 --- a/drivers/fpga/dfl-fme-main.c +++ b/drivers/fpga/dfl-fme-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/uaccess.h> | ||
19 | #include <linux/fpga-dfl.h> | 20 | #include <linux/fpga-dfl.h> |
20 | 21 | ||
21 | #include "dfl.h" | 22 | #include "dfl.h" |
@@ -72,12 +73,61 @@ static ssize_t bitstream_metadata_show(struct device *dev, | |||
72 | } | 73 | } |
73 | static DEVICE_ATTR_RO(bitstream_metadata); | 74 | static DEVICE_ATTR_RO(bitstream_metadata); |
74 | 75 | ||
75 | static const struct attribute *fme_hdr_attrs[] = { | 76 | static ssize_t cache_size_show(struct device *dev, |
77 | struct device_attribute *attr, char *buf) | ||
78 | { | ||
79 | void __iomem *base; | ||
80 | u64 v; | ||
81 | |||
82 | base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER); | ||
83 | |||
84 | v = readq(base + FME_HDR_CAP); | ||
85 | |||
86 | return sprintf(buf, "%u\n", | ||
87 | (unsigned int)FIELD_GET(FME_CAP_CACHE_SIZE, v)); | ||
88 | } | ||
89 | static DEVICE_ATTR_RO(cache_size); | ||
90 | |||
91 | static ssize_t fabric_version_show(struct device *dev, | ||
92 | struct device_attribute *attr, char *buf) | ||
93 | { | ||
94 | void __iomem *base; | ||
95 | u64 v; | ||
96 | |||
97 | base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER); | ||
98 | |||
99 | v = readq(base + FME_HDR_CAP); | ||
100 | |||
101 | return sprintf(buf, "%u\n", | ||
102 | (unsigned int)FIELD_GET(FME_CAP_FABRIC_VERID, v)); | ||
103 | } | ||
104 | static DEVICE_ATTR_RO(fabric_version); | ||
105 | |||
106 | static ssize_t socket_id_show(struct device *dev, | ||
107 | struct device_attribute *attr, char *buf) | ||
108 | { | ||
109 | void __iomem *base; | ||
110 | u64 v; | ||
111 | |||
112 | base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER); | ||
113 | |||
114 | v = readq(base + FME_HDR_CAP); | ||
115 | |||
116 | return sprintf(buf, "%u\n", | ||
117 | (unsigned int)FIELD_GET(FME_CAP_SOCKET_ID, v)); | ||
118 | } | ||
119 | static DEVICE_ATTR_RO(socket_id); | ||
120 | |||
121 | static struct attribute *fme_hdr_attrs[] = { | ||
76 | &dev_attr_ports_num.attr, | 122 | &dev_attr_ports_num.attr, |
77 | &dev_attr_bitstream_id.attr, | 123 | &dev_attr_bitstream_id.attr, |
78 | &dev_attr_bitstream_metadata.attr, | 124 | &dev_attr_bitstream_metadata.attr, |
125 | &dev_attr_cache_size.attr, | ||
126 | &dev_attr_fabric_version.attr, | ||
127 | &dev_attr_socket_id.attr, | ||
79 | NULL, | 128 | NULL, |
80 | }; | 129 | }; |
130 | ATTRIBUTE_GROUPS(fme_hdr); | ||
81 | 131 | ||
82 | static int fme_hdr_init(struct platform_device *pdev, | 132 | static int fme_hdr_init(struct platform_device *pdev, |
83 | struct dfl_feature *feature) | 133 | struct dfl_feature *feature) |
@@ -89,7 +139,7 @@ static int fme_hdr_init(struct platform_device *pdev, | |||
89 | dev_dbg(&pdev->dev, "FME cap %llx.\n", | 139 | dev_dbg(&pdev->dev, "FME cap %llx.\n", |
90 | (unsigned long long)readq(base + FME_HDR_CAP)); | 140 | (unsigned long long)readq(base + FME_HDR_CAP)); |
91 | 141 | ||
92 | ret = sysfs_create_files(&pdev->dev.kobj, fme_hdr_attrs); | 142 | ret = device_add_groups(&pdev->dev, fme_hdr_groups); |
93 | if (ret) | 143 | if (ret) |
94 | return ret; | 144 | return ret; |
95 | 145 | ||
@@ -100,22 +150,68 @@ static void fme_hdr_uinit(struct platform_device *pdev, | |||
100 | struct dfl_feature *feature) | 150 | struct dfl_feature *feature) |
101 | { | 151 | { |
102 | dev_dbg(&pdev->dev, "FME HDR UInit.\n"); | 152 | dev_dbg(&pdev->dev, "FME HDR UInit.\n"); |
103 | sysfs_remove_files(&pdev->dev.kobj, fme_hdr_attrs); | 153 | device_remove_groups(&pdev->dev, fme_hdr_groups); |
154 | } | ||
155 | |||
156 | static long fme_hdr_ioctl_release_port(struct dfl_feature_platform_data *pdata, | ||
157 | unsigned long arg) | ||
158 | { | ||
159 | struct dfl_fpga_cdev *cdev = pdata->dfl_cdev; | ||
160 | int port_id; | ||
161 | |||
162 | if (get_user(port_id, (int __user *)arg)) | ||
163 | return -EFAULT; | ||
164 | |||
165 | return dfl_fpga_cdev_release_port(cdev, port_id); | ||
166 | } | ||
167 | |||
168 | static long fme_hdr_ioctl_assign_port(struct dfl_feature_platform_data *pdata, | ||
169 | unsigned long arg) | ||
170 | { | ||
171 | struct dfl_fpga_cdev *cdev = pdata->dfl_cdev; | ||
172 | int port_id; | ||
173 | |||
174 | if (get_user(port_id, (int __user *)arg)) | ||
175 | return -EFAULT; | ||
176 | |||
177 | return dfl_fpga_cdev_assign_port(cdev, port_id); | ||
104 | } | 178 | } |
105 | 179 | ||
180 | static long fme_hdr_ioctl(struct platform_device *pdev, | ||
181 | struct dfl_feature *feature, | ||
182 | unsigned int cmd, unsigned long arg) | ||
183 | { | ||
184 | struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); | ||
185 | |||
186 | switch (cmd) { | ||
187 | case DFL_FPGA_FME_PORT_RELEASE: | ||
188 | return fme_hdr_ioctl_release_port(pdata, arg); | ||
189 | case DFL_FPGA_FME_PORT_ASSIGN: | ||
190 | return fme_hdr_ioctl_assign_port(pdata, arg); | ||
191 | } | ||
192 | |||
193 | return -ENODEV; | ||
194 | } | ||
195 | |||
196 | static const struct dfl_feature_id fme_hdr_id_table[] = { | ||
197 | {.id = FME_FEATURE_ID_HEADER,}, | ||
198 | {0,} | ||
199 | }; | ||
200 | |||
106 | static const struct dfl_feature_ops fme_hdr_ops = { | 201 | static const struct dfl_feature_ops fme_hdr_ops = { |
107 | .init = fme_hdr_init, | 202 | .init = fme_hdr_init, |
108 | .uinit = fme_hdr_uinit, | 203 | .uinit = fme_hdr_uinit, |
204 | .ioctl = fme_hdr_ioctl, | ||
109 | }; | 205 | }; |
110 | 206 | ||
111 | static struct dfl_feature_driver fme_feature_drvs[] = { | 207 | static struct dfl_feature_driver fme_feature_drvs[] = { |
112 | { | 208 | { |
113 | .id = FME_FEATURE_ID_HEADER, | 209 | .id_table = fme_hdr_id_table, |
114 | .ops = &fme_hdr_ops, | 210 | .ops = &fme_hdr_ops, |
115 | }, | 211 | }, |
116 | { | 212 | { |
117 | .id = FME_FEATURE_ID_PR_MGMT, | 213 | .id_table = fme_pr_mgmt_id_table, |
118 | .ops = &pr_mgmt_ops, | 214 | .ops = &fme_pr_mgmt_ops, |
119 | }, | 215 | }, |
120 | { | 216 | { |
121 | .ops = NULL, | 217 | .ops = NULL, |
diff --git a/drivers/fpga/dfl-fme-pr.c b/drivers/fpga/dfl-fme-pr.c index 3c71dc3faaf5..a233a53db708 100644 --- a/drivers/fpga/dfl-fme-pr.c +++ b/drivers/fpga/dfl-fme-pr.c | |||
@@ -470,7 +470,12 @@ static long fme_pr_ioctl(struct platform_device *pdev, | |||
470 | return ret; | 470 | return ret; |
471 | } | 471 | } |
472 | 472 | ||
473 | const struct dfl_feature_ops pr_mgmt_ops = { | 473 | const struct dfl_feature_id fme_pr_mgmt_id_table[] = { |
474 | {.id = FME_FEATURE_ID_PR_MGMT,}, | ||
475 | {0} | ||
476 | }; | ||
477 | |||
478 | const struct dfl_feature_ops fme_pr_mgmt_ops = { | ||
474 | .init = pr_mgmt_init, | 479 | .init = pr_mgmt_init, |
475 | .uinit = pr_mgmt_uinit, | 480 | .uinit = pr_mgmt_uinit, |
476 | .ioctl = fme_pr_ioctl, | 481 | .ioctl = fme_pr_ioctl, |
diff --git a/drivers/fpga/dfl-fme.h b/drivers/fpga/dfl-fme.h index 5394a216c5c0..e4131e857dae 100644 --- a/drivers/fpga/dfl-fme.h +++ b/drivers/fpga/dfl-fme.h | |||
@@ -33,6 +33,7 @@ struct dfl_fme { | |||
33 | struct dfl_feature_platform_data *pdata; | 33 | struct dfl_feature_platform_data *pdata; |
34 | }; | 34 | }; |
35 | 35 | ||
36 | extern const struct dfl_feature_ops pr_mgmt_ops; | 36 | extern const struct dfl_feature_ops fme_pr_mgmt_ops; |
37 | extern const struct dfl_feature_id fme_pr_mgmt_id_table[]; | ||
37 | 38 | ||
38 | #endif /* __DFL_FME_H */ | 39 | #endif /* __DFL_FME_H */ |
diff --git a/drivers/fpga/dfl-pci.c b/drivers/fpga/dfl-pci.c index 66b5720582bb..89ca292236ad 100644 --- a/drivers/fpga/dfl-pci.c +++ b/drivers/fpga/dfl-pci.c | |||
@@ -223,8 +223,43 @@ disable_error_report_exit: | |||
223 | return ret; | 223 | return ret; |
224 | } | 224 | } |
225 | 225 | ||
226 | static int cci_pci_sriov_configure(struct pci_dev *pcidev, int num_vfs) | ||
227 | { | ||
228 | struct cci_drvdata *drvdata = pci_get_drvdata(pcidev); | ||
229 | struct dfl_fpga_cdev *cdev = drvdata->cdev; | ||
230 | int ret = 0; | ||
231 | |||
232 | if (!num_vfs) { | ||
233 | /* | ||
234 | * disable SRIOV and then put released ports back to default | ||
235 | * PF access mode. | ||
236 | */ | ||
237 | pci_disable_sriov(pcidev); | ||
238 | |||
239 | dfl_fpga_cdev_config_ports_pf(cdev); | ||
240 | |||
241 | } else { | ||
242 | /* | ||
243 | * before enable SRIOV, put released ports into VF access mode | ||
244 | * first of all. | ||
245 | */ | ||
246 | ret = dfl_fpga_cdev_config_ports_vf(cdev, num_vfs); | ||
247 | if (ret) | ||
248 | return ret; | ||
249 | |||
250 | ret = pci_enable_sriov(pcidev, num_vfs); | ||
251 | if (ret) | ||
252 | dfl_fpga_cdev_config_ports_pf(cdev); | ||
253 | } | ||
254 | |||
255 | return ret; | ||
256 | } | ||
257 | |||
226 | static void cci_pci_remove(struct pci_dev *pcidev) | 258 | static void cci_pci_remove(struct pci_dev *pcidev) |
227 | { | 259 | { |
260 | if (dev_is_pf(&pcidev->dev)) | ||
261 | cci_pci_sriov_configure(pcidev, 0); | ||
262 | |||
228 | cci_remove_feature_devs(pcidev); | 263 | cci_remove_feature_devs(pcidev); |
229 | pci_disable_pcie_error_reporting(pcidev); | 264 | pci_disable_pcie_error_reporting(pcidev); |
230 | } | 265 | } |
@@ -234,6 +269,7 @@ static struct pci_driver cci_pci_driver = { | |||
234 | .id_table = cci_pcie_id_tbl, | 269 | .id_table = cci_pcie_id_tbl, |
235 | .probe = cci_pci_probe, | 270 | .probe = cci_pci_probe, |
236 | .remove = cci_pci_remove, | 271 | .remove = cci_pci_remove, |
272 | .sriov_configure = cci_pci_sriov_configure, | ||
237 | }; | 273 | }; |
238 | 274 | ||
239 | module_pci_driver(cci_pci_driver); | 275 | module_pci_driver(cci_pci_driver); |
diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c index 4b66aaa32b5a..c0512afc4ed7 100644 --- a/drivers/fpga/dfl.c +++ b/drivers/fpga/dfl.c | |||
@@ -231,16 +231,20 @@ EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_del); | |||
231 | */ | 231 | */ |
232 | int dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id) | 232 | int dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id) |
233 | { | 233 | { |
234 | struct dfl_fpga_port_ops *port_ops = dfl_fpga_port_ops_get(pdev); | 234 | struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); |
235 | int port_id; | 235 | struct dfl_fpga_port_ops *port_ops; |
236 | |||
237 | if (pdata->id != FEATURE_DEV_ID_UNUSED) | ||
238 | return pdata->id == *(int *)pport_id; | ||
236 | 239 | ||
240 | port_ops = dfl_fpga_port_ops_get(pdev); | ||
237 | if (!port_ops || !port_ops->get_id) | 241 | if (!port_ops || !port_ops->get_id) |
238 | return 0; | 242 | return 0; |
239 | 243 | ||
240 | port_id = port_ops->get_id(pdev); | 244 | pdata->id = port_ops->get_id(pdev); |
241 | dfl_fpga_port_ops_put(port_ops); | 245 | dfl_fpga_port_ops_put(port_ops); |
242 | 246 | ||
243 | return port_id == *(int *)pport_id; | 247 | return pdata->id == *(int *)pport_id; |
244 | } | 248 | } |
245 | EXPORT_SYMBOL_GPL(dfl_fpga_check_port_id); | 249 | EXPORT_SYMBOL_GPL(dfl_fpga_check_port_id); |
246 | 250 | ||
@@ -255,7 +259,8 @@ void dfl_fpga_dev_feature_uinit(struct platform_device *pdev) | |||
255 | 259 | ||
256 | dfl_fpga_dev_for_each_feature(pdata, feature) | 260 | dfl_fpga_dev_for_each_feature(pdata, feature) |
257 | if (feature->ops) { | 261 | if (feature->ops) { |
258 | feature->ops->uinit(pdev, feature); | 262 | if (feature->ops->uinit) |
263 | feature->ops->uinit(pdev, feature); | ||
259 | feature->ops = NULL; | 264 | feature->ops = NULL; |
260 | } | 265 | } |
261 | } | 266 | } |
@@ -277,6 +282,21 @@ static int dfl_feature_instance_init(struct platform_device *pdev, | |||
277 | return ret; | 282 | return ret; |
278 | } | 283 | } |
279 | 284 | ||
285 | static bool dfl_feature_drv_match(struct dfl_feature *feature, | ||
286 | struct dfl_feature_driver *driver) | ||
287 | { | ||
288 | const struct dfl_feature_id *ids = driver->id_table; | ||
289 | |||
290 | if (ids) { | ||
291 | while (ids->id) { | ||
292 | if (ids->id == feature->id) | ||
293 | return true; | ||
294 | ids++; | ||
295 | } | ||
296 | } | ||
297 | return false; | ||
298 | } | ||
299 | |||
280 | /** | 300 | /** |
281 | * dfl_fpga_dev_feature_init - init for sub features of dfl feature device | 301 | * dfl_fpga_dev_feature_init - init for sub features of dfl feature device |
282 | * @pdev: feature device. | 302 | * @pdev: feature device. |
@@ -297,8 +317,7 @@ int dfl_fpga_dev_feature_init(struct platform_device *pdev, | |||
297 | 317 | ||
298 | while (drv->ops) { | 318 | while (drv->ops) { |
299 | dfl_fpga_dev_for_each_feature(pdata, feature) { | 319 | dfl_fpga_dev_for_each_feature(pdata, feature) { |
300 | /* match feature and drv using id */ | 320 | if (dfl_feature_drv_match(feature, drv)) { |
301 | if (feature->id == drv->id) { | ||
302 | ret = dfl_feature_instance_init(pdev, pdata, | 321 | ret = dfl_feature_instance_init(pdev, pdata, |
303 | feature, drv); | 322 | feature, drv); |
304 | if (ret) | 323 | if (ret) |
@@ -474,6 +493,7 @@ static int build_info_commit_dev(struct build_feature_devs_info *binfo) | |||
474 | pdata->dev = fdev; | 493 | pdata->dev = fdev; |
475 | pdata->num = binfo->feature_num; | 494 | pdata->num = binfo->feature_num; |
476 | pdata->dfl_cdev = binfo->cdev; | 495 | pdata->dfl_cdev = binfo->cdev; |
496 | pdata->id = FEATURE_DEV_ID_UNUSED; | ||
477 | mutex_init(&pdata->lock); | 497 | mutex_init(&pdata->lock); |
478 | lockdep_set_class_and_name(&pdata->lock, &dfl_pdata_keys[type], | 498 | lockdep_set_class_and_name(&pdata->lock, &dfl_pdata_keys[type], |
479 | dfl_pdata_key_strings[type]); | 499 | dfl_pdata_key_strings[type]); |
@@ -973,25 +993,27 @@ void dfl_fpga_feature_devs_remove(struct dfl_fpga_cdev *cdev) | |||
973 | { | 993 | { |
974 | struct dfl_feature_platform_data *pdata, *ptmp; | 994 | struct dfl_feature_platform_data *pdata, *ptmp; |
975 | 995 | ||
976 | remove_feature_devs(cdev); | ||
977 | |||
978 | mutex_lock(&cdev->lock); | 996 | mutex_lock(&cdev->lock); |
979 | if (cdev->fme_dev) { | 997 | if (cdev->fme_dev) |
980 | /* the fme should be unregistered. */ | ||
981 | WARN_ON(device_is_registered(cdev->fme_dev)); | ||
982 | put_device(cdev->fme_dev); | 998 | put_device(cdev->fme_dev); |
983 | } | ||
984 | 999 | ||
985 | list_for_each_entry_safe(pdata, ptmp, &cdev->port_dev_list, node) { | 1000 | list_for_each_entry_safe(pdata, ptmp, &cdev->port_dev_list, node) { |
986 | struct platform_device *port_dev = pdata->dev; | 1001 | struct platform_device *port_dev = pdata->dev; |
987 | 1002 | ||
988 | /* the port should be unregistered. */ | 1003 | /* remove released ports */ |
989 | WARN_ON(device_is_registered(&port_dev->dev)); | 1004 | if (!device_is_registered(&port_dev->dev)) { |
1005 | dfl_id_free(feature_dev_id_type(port_dev), | ||
1006 | port_dev->id); | ||
1007 | platform_device_put(port_dev); | ||
1008 | } | ||
1009 | |||
990 | list_del(&pdata->node); | 1010 | list_del(&pdata->node); |
991 | put_device(&port_dev->dev); | 1011 | put_device(&port_dev->dev); |
992 | } | 1012 | } |
993 | mutex_unlock(&cdev->lock); | 1013 | mutex_unlock(&cdev->lock); |
994 | 1014 | ||
1015 | remove_feature_devs(cdev); | ||
1016 | |||
995 | fpga_region_unregister(cdev->region); | 1017 | fpga_region_unregister(cdev->region); |
996 | devm_kfree(cdev->parent, cdev); | 1018 | devm_kfree(cdev->parent, cdev); |
997 | } | 1019 | } |
@@ -1042,6 +1064,170 @@ static int __init dfl_fpga_init(void) | |||
1042 | return ret; | 1064 | return ret; |
1043 | } | 1065 | } |
1044 | 1066 | ||
1067 | /** | ||
1068 | * dfl_fpga_cdev_release_port - release a port platform device | ||
1069 | * | ||
1070 | * @cdev: parent container device. | ||
1071 | * @port_id: id of the port platform device. | ||
1072 | * | ||
1073 | * This function allows user to release a port platform device. This is a | ||
1074 | * mandatory step before turn a port from PF into VF for SRIOV support. | ||
1075 | * | ||
1076 | * Return: 0 on success, negative error code otherwise. | ||
1077 | */ | ||
1078 | int dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id) | ||
1079 | { | ||
1080 | struct platform_device *port_pdev; | ||
1081 | int ret = -ENODEV; | ||
1082 | |||
1083 | mutex_lock(&cdev->lock); | ||
1084 | port_pdev = __dfl_fpga_cdev_find_port(cdev, &port_id, | ||
1085 | dfl_fpga_check_port_id); | ||
1086 | if (!port_pdev) | ||
1087 | goto unlock_exit; | ||
1088 | |||
1089 | if (!device_is_registered(&port_pdev->dev)) { | ||
1090 | ret = -EBUSY; | ||
1091 | goto put_dev_exit; | ||
1092 | } | ||
1093 | |||
1094 | ret = dfl_feature_dev_use_begin(dev_get_platdata(&port_pdev->dev)); | ||
1095 | if (ret) | ||
1096 | goto put_dev_exit; | ||
1097 | |||
1098 | platform_device_del(port_pdev); | ||
1099 | cdev->released_port_num++; | ||
1100 | put_dev_exit: | ||
1101 | put_device(&port_pdev->dev); | ||
1102 | unlock_exit: | ||
1103 | mutex_unlock(&cdev->lock); | ||
1104 | return ret; | ||
1105 | } | ||
1106 | EXPORT_SYMBOL_GPL(dfl_fpga_cdev_release_port); | ||
1107 | |||
1108 | /** | ||
1109 | * dfl_fpga_cdev_assign_port - assign a port platform device back | ||
1110 | * | ||
1111 | * @cdev: parent container device. | ||
1112 | * @port_id: id of the port platform device. | ||
1113 | * | ||
1114 | * This function allows user to assign a port platform device back. This is | ||
1115 | * a mandatory step after disable SRIOV support. | ||
1116 | * | ||
1117 | * Return: 0 on success, negative error code otherwise. | ||
1118 | */ | ||
1119 | int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id) | ||
1120 | { | ||
1121 | struct platform_device *port_pdev; | ||
1122 | int ret = -ENODEV; | ||
1123 | |||
1124 | mutex_lock(&cdev->lock); | ||
1125 | port_pdev = __dfl_fpga_cdev_find_port(cdev, &port_id, | ||
1126 | dfl_fpga_check_port_id); | ||
1127 | if (!port_pdev) | ||
1128 | goto unlock_exit; | ||
1129 | |||
1130 | if (device_is_registered(&port_pdev->dev)) { | ||
1131 | ret = -EBUSY; | ||
1132 | goto put_dev_exit; | ||
1133 | } | ||
1134 | |||
1135 | ret = platform_device_add(port_pdev); | ||
1136 | if (ret) | ||
1137 | goto put_dev_exit; | ||
1138 | |||
1139 | dfl_feature_dev_use_end(dev_get_platdata(&port_pdev->dev)); | ||
1140 | cdev->released_port_num--; | ||
1141 | put_dev_exit: | ||
1142 | put_device(&port_pdev->dev); | ||
1143 | unlock_exit: | ||
1144 | mutex_unlock(&cdev->lock); | ||
1145 | return ret; | ||
1146 | } | ||
1147 | EXPORT_SYMBOL_GPL(dfl_fpga_cdev_assign_port); | ||
1148 | |||
1149 | static void config_port_access_mode(struct device *fme_dev, int port_id, | ||
1150 | bool is_vf) | ||
1151 | { | ||
1152 | void __iomem *base; | ||
1153 | u64 v; | ||
1154 | |||
1155 | base = dfl_get_feature_ioaddr_by_id(fme_dev, FME_FEATURE_ID_HEADER); | ||
1156 | |||
1157 | v = readq(base + FME_HDR_PORT_OFST(port_id)); | ||
1158 | |||
1159 | v &= ~FME_PORT_OFST_ACC_CTRL; | ||
1160 | v |= FIELD_PREP(FME_PORT_OFST_ACC_CTRL, | ||
1161 | is_vf ? FME_PORT_OFST_ACC_VF : FME_PORT_OFST_ACC_PF); | ||
1162 | |||
1163 | writeq(v, base + FME_HDR_PORT_OFST(port_id)); | ||
1164 | } | ||
1165 | |||
1166 | #define config_port_vf_mode(dev, id) config_port_access_mode(dev, id, true) | ||
1167 | #define config_port_pf_mode(dev, id) config_port_access_mode(dev, id, false) | ||
1168 | |||
1169 | /** | ||
1170 | * dfl_fpga_cdev_config_ports_pf - configure ports to PF access mode | ||
1171 | * | ||
1172 | * @cdev: parent container device. | ||
1173 | * | ||
1174 | * This function is needed in sriov configuration routine. It could be used to | ||
1175 | * configure the all released ports from VF access mode to PF. | ||
1176 | */ | ||
1177 | void dfl_fpga_cdev_config_ports_pf(struct dfl_fpga_cdev *cdev) | ||
1178 | { | ||
1179 | struct dfl_feature_platform_data *pdata; | ||
1180 | |||
1181 | mutex_lock(&cdev->lock); | ||
1182 | list_for_each_entry(pdata, &cdev->port_dev_list, node) { | ||
1183 | if (device_is_registered(&pdata->dev->dev)) | ||
1184 | continue; | ||
1185 | |||
1186 | config_port_pf_mode(cdev->fme_dev, pdata->id); | ||
1187 | } | ||
1188 | mutex_unlock(&cdev->lock); | ||
1189 | } | ||
1190 | EXPORT_SYMBOL_GPL(dfl_fpga_cdev_config_ports_pf); | ||
1191 | |||
1192 | /** | ||
1193 | * dfl_fpga_cdev_config_ports_vf - configure ports to VF access mode | ||
1194 | * | ||
1195 | * @cdev: parent container device. | ||
1196 | * @num_vfs: VF device number. | ||
1197 | * | ||
1198 | * This function is needed in sriov configuration routine. It could be used to | ||
1199 | * configure the released ports from PF access mode to VF. | ||
1200 | * | ||
1201 | * Return: 0 on success, negative error code otherwise. | ||
1202 | */ | ||
1203 | int dfl_fpga_cdev_config_ports_vf(struct dfl_fpga_cdev *cdev, int num_vfs) | ||
1204 | { | ||
1205 | struct dfl_feature_platform_data *pdata; | ||
1206 | int ret = 0; | ||
1207 | |||
1208 | mutex_lock(&cdev->lock); | ||
1209 | /* | ||
1210 | * can't turn multiple ports into 1 VF device, only 1 port for 1 VF | ||
1211 | * device, so if released port number doesn't match VF device number, | ||
1212 | * then reject the request with -EINVAL error code. | ||
1213 | */ | ||
1214 | if (cdev->released_port_num != num_vfs) { | ||
1215 | ret = -EINVAL; | ||
1216 | goto done; | ||
1217 | } | ||
1218 | |||
1219 | list_for_each_entry(pdata, &cdev->port_dev_list, node) { | ||
1220 | if (device_is_registered(&pdata->dev->dev)) | ||
1221 | continue; | ||
1222 | |||
1223 | config_port_vf_mode(cdev->fme_dev, pdata->id); | ||
1224 | } | ||
1225 | done: | ||
1226 | mutex_unlock(&cdev->lock); | ||
1227 | return ret; | ||
1228 | } | ||
1229 | EXPORT_SYMBOL_GPL(dfl_fpga_cdev_config_ports_vf); | ||
1230 | |||
1045 | static void __exit dfl_fpga_exit(void) | 1231 | static void __exit dfl_fpga_exit(void) |
1046 | { | 1232 | { |
1047 | dfl_chardev_uinit(); | 1233 | dfl_chardev_uinit(); |
diff --git a/drivers/fpga/dfl.h b/drivers/fpga/dfl.h index a8b869e9e5b7..856ea4ebc445 100644 --- a/drivers/fpga/dfl.h +++ b/drivers/fpga/dfl.h | |||
@@ -30,8 +30,8 @@ | |||
30 | /* plus one for fme device */ | 30 | /* plus one for fme device */ |
31 | #define MAX_DFL_FEATURE_DEV_NUM (MAX_DFL_FPGA_PORT_NUM + 1) | 31 | #define MAX_DFL_FEATURE_DEV_NUM (MAX_DFL_FPGA_PORT_NUM + 1) |
32 | 32 | ||
33 | /* Reserved 0x0 for Header Group Register and 0xff for AFU */ | 33 | /* Reserved 0xfe for Header Group Register and 0xff for AFU */ |
34 | #define FEATURE_ID_FIU_HEADER 0x0 | 34 | #define FEATURE_ID_FIU_HEADER 0xfe |
35 | #define FEATURE_ID_AFU 0xff | 35 | #define FEATURE_ID_AFU 0xff |
36 | 36 | ||
37 | #define FME_FEATURE_ID_HEADER FEATURE_ID_FIU_HEADER | 37 | #define FME_FEATURE_ID_HEADER FEATURE_ID_FIU_HEADER |
@@ -119,6 +119,7 @@ | |||
119 | #define PORT_HDR_NEXT_AFU NEXT_AFU | 119 | #define PORT_HDR_NEXT_AFU NEXT_AFU |
120 | #define PORT_HDR_CAP 0x30 | 120 | #define PORT_HDR_CAP 0x30 |
121 | #define PORT_HDR_CTRL 0x38 | 121 | #define PORT_HDR_CTRL 0x38 |
122 | #define PORT_HDR_STS 0x40 | ||
122 | 123 | ||
123 | /* Port Capability Register Bitfield */ | 124 | /* Port Capability Register Bitfield */ |
124 | #define PORT_CAP_PORT_NUM GENMASK_ULL(1, 0) /* ID of this port */ | 125 | #define PORT_CAP_PORT_NUM GENMASK_ULL(1, 0) /* ID of this port */ |
@@ -130,6 +131,16 @@ | |||
130 | /* Latency tolerance reporting. '1' >= 40us, '0' < 40us.*/ | 131 | /* Latency tolerance reporting. '1' >= 40us, '0' < 40us.*/ |
131 | #define PORT_CTRL_LATENCY BIT_ULL(2) | 132 | #define PORT_CTRL_LATENCY BIT_ULL(2) |
132 | #define PORT_CTRL_SFTRST_ACK BIT_ULL(4) /* HW ack for reset */ | 133 | #define PORT_CTRL_SFTRST_ACK BIT_ULL(4) /* HW ack for reset */ |
134 | |||
135 | /* Port Status Register Bitfield */ | ||
136 | #define PORT_STS_AP2_EVT BIT_ULL(13) /* AP2 event detected */ | ||
137 | #define PORT_STS_AP1_EVT BIT_ULL(12) /* AP1 event detected */ | ||
138 | #define PORT_STS_PWR_STATE GENMASK_ULL(11, 8) /* AFU power states */ | ||
139 | #define PORT_STS_PWR_STATE_NORM 0 | ||
140 | #define PORT_STS_PWR_STATE_AP1 1 /* 50% throttling */ | ||
141 | #define PORT_STS_PWR_STATE_AP2 2 /* 90% throttling */ | ||
142 | #define PORT_STS_PWR_STATE_AP6 6 /* 100% throttling */ | ||
143 | |||
133 | /** | 144 | /** |
134 | * struct dfl_fpga_port_ops - port ops | 145 | * struct dfl_fpga_port_ops - port ops |
135 | * | 146 | * |
@@ -154,13 +165,22 @@ void dfl_fpga_port_ops_put(struct dfl_fpga_port_ops *ops); | |||
154 | int dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id); | 165 | int dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id); |
155 | 166 | ||
156 | /** | 167 | /** |
157 | * struct dfl_feature_driver - sub feature's driver | 168 | * struct dfl_feature_id - dfl private feature id |
158 | * | 169 | * |
159 | * @id: sub feature id. | 170 | * @id: unique dfl private feature id. |
160 | * @ops: ops of this sub feature. | ||
161 | */ | 171 | */ |
162 | struct dfl_feature_driver { | 172 | struct dfl_feature_id { |
163 | u64 id; | 173 | u64 id; |
174 | }; | ||
175 | |||
176 | /** | ||
177 | * struct dfl_feature_driver - dfl private feature driver | ||
178 | * | ||
179 | * @id_table: id_table for dfl private features supported by this driver. | ||
180 | * @ops: ops of this dfl private feature driver. | ||
181 | */ | ||
182 | struct dfl_feature_driver { | ||
183 | const struct dfl_feature_id *id_table; | ||
164 | const struct dfl_feature_ops *ops; | 184 | const struct dfl_feature_ops *ops; |
165 | }; | 185 | }; |
166 | 186 | ||
@@ -183,6 +203,8 @@ struct dfl_feature { | |||
183 | 203 | ||
184 | #define DEV_STATUS_IN_USE 0 | 204 | #define DEV_STATUS_IN_USE 0 |
185 | 205 | ||
206 | #define FEATURE_DEV_ID_UNUSED (-1) | ||
207 | |||
186 | /** | 208 | /** |
187 | * struct dfl_feature_platform_data - platform data for feature devices | 209 | * struct dfl_feature_platform_data - platform data for feature devices |
188 | * | 210 | * |
@@ -191,6 +213,7 @@ struct dfl_feature { | |||
191 | * @cdev: cdev of feature dev. | 213 | * @cdev: cdev of feature dev. |
192 | * @dev: ptr to platform device linked with this platform data. | 214 | * @dev: ptr to platform device linked with this platform data. |
193 | * @dfl_cdev: ptr to container device. | 215 | * @dfl_cdev: ptr to container device. |
216 | * @id: id used for this feature device. | ||
194 | * @disable_count: count for port disable. | 217 | * @disable_count: count for port disable. |
195 | * @num: number for sub features. | 218 | * @num: number for sub features. |
196 | * @dev_status: dev status (e.g. DEV_STATUS_IN_USE). | 219 | * @dev_status: dev status (e.g. DEV_STATUS_IN_USE). |
@@ -203,6 +226,7 @@ struct dfl_feature_platform_data { | |||
203 | struct cdev cdev; | 226 | struct cdev cdev; |
204 | struct platform_device *dev; | 227 | struct platform_device *dev; |
205 | struct dfl_fpga_cdev *dfl_cdev; | 228 | struct dfl_fpga_cdev *dfl_cdev; |
229 | int id; | ||
206 | unsigned int disable_count; | 230 | unsigned int disable_count; |
207 | unsigned long dev_status; | 231 | unsigned long dev_status; |
208 | void *private; | 232 | void *private; |
@@ -373,6 +397,7 @@ void dfl_fpga_enum_info_free(struct dfl_fpga_enum_info *info); | |||
373 | * @fme_dev: FME feature device under this container device. | 397 | * @fme_dev: FME feature device under this container device. |
374 | * @lock: mutex lock to protect the port device list. | 398 | * @lock: mutex lock to protect the port device list. |
375 | * @port_dev_list: list of all port feature devices under this container device. | 399 | * @port_dev_list: list of all port feature devices under this container device. |
400 | * @released_port_num: released port number under this container device. | ||
376 | */ | 401 | */ |
377 | struct dfl_fpga_cdev { | 402 | struct dfl_fpga_cdev { |
378 | struct device *parent; | 403 | struct device *parent; |
@@ -380,6 +405,7 @@ struct dfl_fpga_cdev { | |||
380 | struct device *fme_dev; | 405 | struct device *fme_dev; |
381 | struct mutex lock; | 406 | struct mutex lock; |
382 | struct list_head port_dev_list; | 407 | struct list_head port_dev_list; |
408 | int released_port_num; | ||
383 | }; | 409 | }; |
384 | 410 | ||
385 | struct dfl_fpga_cdev * | 411 | struct dfl_fpga_cdev * |
@@ -407,4 +433,9 @@ dfl_fpga_cdev_find_port(struct dfl_fpga_cdev *cdev, void *data, | |||
407 | 433 | ||
408 | return pdev; | 434 | return pdev; |
409 | } | 435 | } |
436 | |||
437 | int dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id); | ||
438 | int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id); | ||
439 | void dfl_fpga_cdev_config_ports_pf(struct dfl_fpga_cdev *cdev); | ||
440 | int dfl_fpga_cdev_config_ports_vf(struct dfl_fpga_cdev *cdev, int num_vf); | ||
410 | #endif /* __FPGA_DFL_H */ | 441 | #endif /* __FPGA_DFL_H */ |