aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlastair D'Silva <alastair@d-silva.org>2019-03-27 01:31:30 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2019-05-02 12:55:01 -0400
commit1ba2143606a10f1c2e7308bc7abd940a6381cffd (patch)
treedfed0c2661682dc85bf48621f8ca36a08633bdee
parentb696d28283e2e030cdc9ece7a4eb0a93b4c474fd (diff)
ocxl: Split pci.c
In preparation for making core code available for external drivers, move the core code out of pci.c and into core.c Signed-off-by: Alastair D'Silva <alastair@d-silva.org> Acked-by: Frederic Barrat <fbarrat@linux.ibm.com> Acked-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--drivers/misc/ocxl/Makefile1
-rw-r--r--drivers/misc/ocxl/core.c517
-rw-r--r--drivers/misc/ocxl/ocxl_internal.h5
-rw-r--r--drivers/misc/ocxl/pci.c519
4 files changed, 524 insertions, 518 deletions
diff --git a/drivers/misc/ocxl/Makefile b/drivers/misc/ocxl/Makefile
index 5229dcda8297..bc4e39bfda7b 100644
--- a/drivers/misc/ocxl/Makefile
+++ b/drivers/misc/ocxl/Makefile
@@ -3,6 +3,7 @@ ccflags-$(CONFIG_PPC_WERROR) += -Werror
3 3
4ocxl-y += main.o pci.o config.o file.o pasid.o 4ocxl-y += main.o pci.o config.o file.o pasid.o
5ocxl-y += link.o context.o afu_irq.o sysfs.o trace.o 5ocxl-y += link.o context.o afu_irq.o sysfs.o trace.o
6ocxl-y += core.o
6obj-$(CONFIG_OCXL) += ocxl.o 7obj-$(CONFIG_OCXL) += ocxl.o
7 8
8# For tracepoints to include our trace.h from tracepoint infrastructure: 9# For tracepoints to include our trace.h from tracepoint infrastructure:
diff --git a/drivers/misc/ocxl/core.c b/drivers/misc/ocxl/core.c
new file mode 100644
index 000000000000..1a4411b72d35
--- /dev/null
+++ b/drivers/misc/ocxl/core.c
@@ -0,0 +1,517 @@
1// SPDX-License-Identifier: GPL-2.0+
2// Copyright 2019 IBM Corp.
3#include <linux/idr.h>
4#include "ocxl_internal.h"
5
6static struct ocxl_fn *ocxl_fn_get(struct ocxl_fn *fn)
7{
8 return (get_device(&fn->dev) == NULL) ? NULL : fn;
9}
10
11static void ocxl_fn_put(struct ocxl_fn *fn)
12{
13 put_device(&fn->dev);
14}
15
16struct ocxl_afu *ocxl_afu_get(struct ocxl_afu *afu)
17{
18 return (get_device(&afu->dev) == NULL) ? NULL : afu;
19}
20
21void ocxl_afu_put(struct ocxl_afu *afu)
22{
23 put_device(&afu->dev);
24}
25
26static struct ocxl_afu *alloc_afu(struct ocxl_fn *fn)
27{
28 struct ocxl_afu *afu;
29
30 afu = kzalloc(sizeof(struct ocxl_afu), GFP_KERNEL);
31 if (!afu)
32 return NULL;
33
34 mutex_init(&afu->contexts_lock);
35 mutex_init(&afu->afu_control_lock);
36 idr_init(&afu->contexts_idr);
37 afu->fn = fn;
38 ocxl_fn_get(fn);
39 return afu;
40}
41
42static void free_afu(struct ocxl_afu *afu)
43{
44 idr_destroy(&afu->contexts_idr);
45 ocxl_fn_put(afu->fn);
46 kfree(afu);
47}
48
49static void free_afu_dev(struct device *dev)
50{
51 struct ocxl_afu *afu = to_ocxl_afu(dev);
52
53 ocxl_unregister_afu(afu);
54 free_afu(afu);
55}
56
57static int set_afu_device(struct ocxl_afu *afu, const char *location)
58{
59 struct ocxl_fn *fn = afu->fn;
60 int rc;
61
62 afu->dev.parent = &fn->dev;
63 afu->dev.release = free_afu_dev;
64 rc = dev_set_name(&afu->dev, "%s.%s.%hhu", afu->config.name, location,
65 afu->config.idx);
66 return rc;
67}
68
69static int assign_afu_actag(struct ocxl_afu *afu, struct pci_dev *dev)
70{
71 struct ocxl_fn *fn = afu->fn;
72 int actag_count, actag_offset;
73
74 /*
75 * if there were not enough actags for the function, each afu
76 * reduces its count as well
77 */
78 actag_count = afu->config.actag_supported *
79 fn->actag_enabled / fn->actag_supported;
80 actag_offset = ocxl_actag_afu_alloc(fn, actag_count);
81 if (actag_offset < 0) {
82 dev_err(&afu->dev, "Can't allocate %d actags for AFU: %d\n",
83 actag_count, actag_offset);
84 return actag_offset;
85 }
86 afu->actag_base = fn->actag_base + actag_offset;
87 afu->actag_enabled = actag_count;
88
89 ocxl_config_set_afu_actag(dev, afu->config.dvsec_afu_control_pos,
90 afu->actag_base, afu->actag_enabled);
91 dev_dbg(&afu->dev, "actag base=%d enabled=%d\n",
92 afu->actag_base, afu->actag_enabled);
93 return 0;
94}
95
96static void reclaim_afu_actag(struct ocxl_afu *afu)
97{
98 struct ocxl_fn *fn = afu->fn;
99 int start_offset, size;
100
101 start_offset = afu->actag_base - fn->actag_base;
102 size = afu->actag_enabled;
103 ocxl_actag_afu_free(afu->fn, start_offset, size);
104}
105
106static int assign_afu_pasid(struct ocxl_afu *afu, struct pci_dev *dev)
107{
108 struct ocxl_fn *fn = afu->fn;
109 int pasid_count, pasid_offset;
110
111 /*
112 * We only support the case where the function configuration
113 * requested enough PASIDs to cover all AFUs.
114 */
115 pasid_count = 1 << afu->config.pasid_supported_log;
116 pasid_offset = ocxl_pasid_afu_alloc(fn, pasid_count);
117 if (pasid_offset < 0) {
118 dev_err(&afu->dev, "Can't allocate %d PASIDs for AFU: %d\n",
119 pasid_count, pasid_offset);
120 return pasid_offset;
121 }
122 afu->pasid_base = fn->pasid_base + pasid_offset;
123 afu->pasid_count = 0;
124 afu->pasid_max = pasid_count;
125
126 ocxl_config_set_afu_pasid(dev, afu->config.dvsec_afu_control_pos,
127 afu->pasid_base,
128 afu->config.pasid_supported_log);
129 dev_dbg(&afu->dev, "PASID base=%d, enabled=%d\n",
130 afu->pasid_base, pasid_count);
131 return 0;
132}
133
134static void reclaim_afu_pasid(struct ocxl_afu *afu)
135{
136 struct ocxl_fn *fn = afu->fn;
137 int start_offset, size;
138
139 start_offset = afu->pasid_base - fn->pasid_base;
140 size = 1 << afu->config.pasid_supported_log;
141 ocxl_pasid_afu_free(afu->fn, start_offset, size);
142}
143
144static int reserve_fn_bar(struct ocxl_fn *fn, int bar)
145{
146 struct pci_dev *dev = to_pci_dev(fn->dev.parent);
147 int rc, idx;
148
149 if (bar != 0 && bar != 2 && bar != 4)
150 return -EINVAL;
151
152 idx = bar >> 1;
153 if (fn->bar_used[idx]++ == 0) {
154 rc = pci_request_region(dev, bar, "ocxl");
155 if (rc)
156 return rc;
157 }
158 return 0;
159}
160
161static void release_fn_bar(struct ocxl_fn *fn, int bar)
162{
163 struct pci_dev *dev = to_pci_dev(fn->dev.parent);
164 int idx;
165
166 if (bar != 0 && bar != 2 && bar != 4)
167 return;
168
169 idx = bar >> 1;
170 if (--fn->bar_used[idx] == 0)
171 pci_release_region(dev, bar);
172 WARN_ON(fn->bar_used[idx] < 0);
173}
174
175static int map_mmio_areas(struct ocxl_afu *afu, struct pci_dev *dev)
176{
177 int rc;
178
179 rc = reserve_fn_bar(afu->fn, afu->config.global_mmio_bar);
180 if (rc)
181 return rc;
182
183 rc = reserve_fn_bar(afu->fn, afu->config.pp_mmio_bar);
184 if (rc) {
185 release_fn_bar(afu->fn, afu->config.global_mmio_bar);
186 return rc;
187 }
188
189 afu->global_mmio_start =
190 pci_resource_start(dev, afu->config.global_mmio_bar) +
191 afu->config.global_mmio_offset;
192 afu->pp_mmio_start =
193 pci_resource_start(dev, afu->config.pp_mmio_bar) +
194 afu->config.pp_mmio_offset;
195
196 afu->global_mmio_ptr = ioremap(afu->global_mmio_start,
197 afu->config.global_mmio_size);
198 if (!afu->global_mmio_ptr) {
199 release_fn_bar(afu->fn, afu->config.pp_mmio_bar);
200 release_fn_bar(afu->fn, afu->config.global_mmio_bar);
201 dev_err(&dev->dev, "Error mapping global mmio area\n");
202 return -ENOMEM;
203 }
204
205 /*
206 * Leave an empty page between the per-process mmio area and
207 * the AFU interrupt mappings
208 */
209 afu->irq_base_offset = afu->config.pp_mmio_stride + PAGE_SIZE;
210 return 0;
211}
212
213static void unmap_mmio_areas(struct ocxl_afu *afu)
214{
215 if (afu->global_mmio_ptr) {
216 iounmap(afu->global_mmio_ptr);
217 afu->global_mmio_ptr = NULL;
218 }
219 afu->global_mmio_start = 0;
220 afu->pp_mmio_start = 0;
221 release_fn_bar(afu->fn, afu->config.pp_mmio_bar);
222 release_fn_bar(afu->fn, afu->config.global_mmio_bar);
223}
224
225static int configure_afu(struct ocxl_afu *afu, u8 afu_idx, struct pci_dev *dev)
226{
227 int rc;
228
229 rc = ocxl_config_read_afu(dev, &afu->fn->config, &afu->config, afu_idx);
230 if (rc)
231 return rc;
232
233 rc = set_afu_device(afu, dev_name(&dev->dev));
234 if (rc)
235 return rc;
236
237 rc = assign_afu_actag(afu, dev);
238 if (rc)
239 return rc;
240
241 rc = assign_afu_pasid(afu, dev);
242 if (rc) {
243 reclaim_afu_actag(afu);
244 return rc;
245 }
246
247 rc = map_mmio_areas(afu, dev);
248 if (rc) {
249 reclaim_afu_pasid(afu);
250 reclaim_afu_actag(afu);
251 return rc;
252 }
253 return 0;
254}
255
256static void deconfigure_afu(struct ocxl_afu *afu)
257{
258 unmap_mmio_areas(afu);
259 reclaim_afu_pasid(afu);
260 reclaim_afu_actag(afu);
261}
262
263static int activate_afu(struct pci_dev *dev, struct ocxl_afu *afu)
264{
265 int rc;
266
267 ocxl_config_set_afu_state(dev, afu->config.dvsec_afu_control_pos, 1);
268 /*
269 * Char device creation is the last step, as processes can
270 * call our driver immediately, so all our inits must be finished.
271 */
272 rc = ocxl_create_cdev(afu);
273 if (rc)
274 return rc;
275 return 0;
276}
277
278static void deactivate_afu(struct ocxl_afu *afu)
279{
280 struct pci_dev *dev = to_pci_dev(afu->fn->dev.parent);
281
282 ocxl_destroy_cdev(afu);
283 ocxl_config_set_afu_state(dev, afu->config.dvsec_afu_control_pos, 0);
284}
285
286int init_afu(struct pci_dev *dev, struct ocxl_fn *fn, u8 afu_idx)
287{
288 int rc;
289 struct ocxl_afu *afu;
290
291 afu = alloc_afu(fn);
292 if (!afu)
293 return -ENOMEM;
294
295 rc = configure_afu(afu, afu_idx, dev);
296 if (rc) {
297 free_afu(afu);
298 return rc;
299 }
300
301 rc = ocxl_register_afu(afu);
302 if (rc)
303 goto err;
304
305 rc = ocxl_sysfs_add_afu(afu);
306 if (rc)
307 goto err;
308
309 rc = activate_afu(dev, afu);
310 if (rc)
311 goto err_sys;
312
313 list_add_tail(&afu->list, &fn->afu_list);
314 return 0;
315
316err_sys:
317 ocxl_sysfs_remove_afu(afu);
318err:
319 deconfigure_afu(afu);
320 device_unregister(&afu->dev);
321 return rc;
322}
323
324void remove_afu(struct ocxl_afu *afu)
325{
326 list_del(&afu->list);
327 ocxl_context_detach_all(afu);
328 deactivate_afu(afu);
329 ocxl_sysfs_remove_afu(afu);
330 deconfigure_afu(afu);
331 device_unregister(&afu->dev);
332}
333
334static struct ocxl_fn *alloc_function(struct pci_dev *dev)
335{
336 struct ocxl_fn *fn;
337
338 fn = kzalloc(sizeof(struct ocxl_fn), GFP_KERNEL);
339 if (!fn)
340 return NULL;
341
342 INIT_LIST_HEAD(&fn->afu_list);
343 INIT_LIST_HEAD(&fn->pasid_list);
344 INIT_LIST_HEAD(&fn->actag_list);
345 return fn;
346}
347
348static void free_function(struct ocxl_fn *fn)
349{
350 WARN_ON(!list_empty(&fn->afu_list));
351 WARN_ON(!list_empty(&fn->pasid_list));
352 kfree(fn);
353}
354
355static void free_function_dev(struct device *dev)
356{
357 struct ocxl_fn *fn = to_ocxl_function(dev);
358
359 free_function(fn);
360}
361
362static int set_function_device(struct ocxl_fn *fn, struct pci_dev *dev)
363{
364 int rc;
365
366 fn->dev.parent = &dev->dev;
367 fn->dev.release = free_function_dev;
368 rc = dev_set_name(&fn->dev, "ocxlfn.%s", dev_name(&dev->dev));
369 if (rc)
370 return rc;
371 pci_set_drvdata(dev, fn);
372 return 0;
373}
374
375static int assign_function_actag(struct ocxl_fn *fn)
376{
377 struct pci_dev *dev = to_pci_dev(fn->dev.parent);
378 u16 base, enabled, supported;
379 int rc;
380
381 rc = ocxl_config_get_actag_info(dev, &base, &enabled, &supported);
382 if (rc)
383 return rc;
384
385 fn->actag_base = base;
386 fn->actag_enabled = enabled;
387 fn->actag_supported = supported;
388
389 ocxl_config_set_actag(dev, fn->config.dvsec_function_pos,
390 fn->actag_base, fn->actag_enabled);
391 dev_dbg(&fn->dev, "actag range starting at %d, enabled %d\n",
392 fn->actag_base, fn->actag_enabled);
393 return 0;
394}
395
396static int set_function_pasid(struct ocxl_fn *fn)
397{
398 struct pci_dev *dev = to_pci_dev(fn->dev.parent);
399 int rc, desired_count, max_count;
400
401 /* A function may not require any PASID */
402 if (fn->config.max_pasid_log < 0)
403 return 0;
404
405 rc = ocxl_config_get_pasid_info(dev, &max_count);
406 if (rc)
407 return rc;
408
409 desired_count = 1 << fn->config.max_pasid_log;
410
411 if (desired_count > max_count) {
412 dev_err(&fn->dev,
413 "Function requires more PASIDs than is available (%d vs. %d)\n",
414 desired_count, max_count);
415 return -ENOSPC;
416 }
417
418 fn->pasid_base = 0;
419 return 0;
420}
421
422static int configure_function(struct ocxl_fn *fn, struct pci_dev *dev)
423{
424 int rc;
425
426 rc = pci_enable_device(dev);
427 if (rc) {
428 dev_err(&dev->dev, "pci_enable_device failed: %d\n", rc);
429 return rc;
430 }
431
432 /*
433 * Once it has been confirmed to work on our hardware, we
434 * should reset the function, to force the adapter to restart
435 * from scratch.
436 * A function reset would also reset all its AFUs.
437 *
438 * Some hints for implementation:
439 *
440 * - there's not status bit to know when the reset is done. We
441 * should try reading the config space to know when it's
442 * done.
443 * - probably something like:
444 * Reset
445 * wait 100ms
446 * issue config read
447 * allow device up to 1 sec to return success on config
448 * read before declaring it broken
449 *
450 * Some shared logic on the card (CFG, TLX) won't be reset, so
451 * there's no guarantee that it will be enough.
452 */
453 rc = ocxl_config_read_function(dev, &fn->config);
454 if (rc)
455 return rc;
456
457 rc = set_function_device(fn, dev);
458 if (rc)
459 return rc;
460
461 rc = assign_function_actag(fn);
462 if (rc)
463 return rc;
464
465 rc = set_function_pasid(fn);
466 if (rc)
467 return rc;
468
469 rc = ocxl_link_setup(dev, 0, &fn->link);
470 if (rc)
471 return rc;
472
473 rc = ocxl_config_set_TL(dev, fn->config.dvsec_tl_pos);
474 if (rc) {
475 ocxl_link_release(dev, fn->link);
476 return rc;
477 }
478 return 0;
479}
480
481static void deconfigure_function(struct ocxl_fn *fn)
482{
483 struct pci_dev *dev = to_pci_dev(fn->dev.parent);
484
485 ocxl_link_release(dev, fn->link);
486 pci_disable_device(dev);
487}
488
489struct ocxl_fn *init_function(struct pci_dev *dev)
490{
491 struct ocxl_fn *fn;
492 int rc;
493
494 fn = alloc_function(dev);
495 if (!fn)
496 return ERR_PTR(-ENOMEM);
497
498 rc = configure_function(fn, dev);
499 if (rc) {
500 free_function(fn);
501 return ERR_PTR(rc);
502 }
503
504 rc = device_register(&fn->dev);
505 if (rc) {
506 deconfigure_function(fn);
507 put_device(&fn->dev);
508 return ERR_PTR(rc);
509 }
510 return fn;
511}
512
513void remove_function(struct ocxl_fn *fn)
514{
515 deconfigure_function(fn);
516 device_unregister(&fn->dev);
517}
diff --git a/drivers/misc/ocxl/ocxl_internal.h b/drivers/misc/ocxl/ocxl_internal.h
index 06fd98c989c8..81086534dab5 100644
--- a/drivers/misc/ocxl/ocxl_internal.h
+++ b/drivers/misc/ocxl/ocxl_internal.h
@@ -150,4 +150,9 @@ int ocxl_afu_irq_set_fd(struct ocxl_context *ctx, u64 irq_offset,
150 int eventfd); 150 int eventfd);
151u64 ocxl_afu_irq_get_addr(struct ocxl_context *ctx, u64 irq_offset); 151u64 ocxl_afu_irq_get_addr(struct ocxl_context *ctx, u64 irq_offset);
152 152
153struct ocxl_fn *init_function(struct pci_dev *dev);
154void remove_function(struct ocxl_fn *fn);
155int init_afu(struct pci_dev *dev, struct ocxl_fn *fn, u8 afu_idx);
156void remove_afu(struct ocxl_afu *afu);
157
153#endif /* _OCXL_INTERNAL_H_ */ 158#endif /* _OCXL_INTERNAL_H_ */
diff --git a/drivers/misc/ocxl/pci.c b/drivers/misc/ocxl/pci.c
index 21f425472a82..4ed7cb1a667f 100644
--- a/drivers/misc/ocxl/pci.c
+++ b/drivers/misc/ocxl/pci.c
@@ -1,9 +1,6 @@
1// SPDX-License-Identifier: GPL-2.0+ 1// SPDX-License-Identifier: GPL-2.0+
2// Copyright 2017 IBM Corp. 2// Copyright 2019 IBM Corp.
3#include <linux/module.h> 3#include <linux/module.h>
4#include <linux/pci.h>
5#include <linux/idr.h>
6#include <asm/pnv-ocxl.h>
7#include "ocxl_internal.h" 4#include "ocxl_internal.h"
8 5
9/* 6/*
@@ -17,520 +14,6 @@ static const struct pci_device_id ocxl_pci_tbl[] = {
17}; 14};
18MODULE_DEVICE_TABLE(pci, ocxl_pci_tbl); 15MODULE_DEVICE_TABLE(pci, ocxl_pci_tbl);
19 16
20
21static struct ocxl_fn *ocxl_fn_get(struct ocxl_fn *fn)
22{
23 return (get_device(&fn->dev) == NULL) ? NULL : fn;
24}
25
26static void ocxl_fn_put(struct ocxl_fn *fn)
27{
28 put_device(&fn->dev);
29}
30
31struct ocxl_afu *ocxl_afu_get(struct ocxl_afu *afu)
32{
33 return (get_device(&afu->dev) == NULL) ? NULL : afu;
34}
35
36void ocxl_afu_put(struct ocxl_afu *afu)
37{
38 put_device(&afu->dev);
39}
40
41static struct ocxl_afu *alloc_afu(struct ocxl_fn *fn)
42{
43 struct ocxl_afu *afu;
44
45 afu = kzalloc(sizeof(struct ocxl_afu), GFP_KERNEL);
46 if (!afu)
47 return NULL;
48
49 mutex_init(&afu->contexts_lock);
50 mutex_init(&afu->afu_control_lock);
51 idr_init(&afu->contexts_idr);
52 afu->fn = fn;
53 ocxl_fn_get(fn);
54 return afu;
55}
56
57static void free_afu(struct ocxl_afu *afu)
58{
59 idr_destroy(&afu->contexts_idr);
60 ocxl_fn_put(afu->fn);
61 kfree(afu);
62}
63
64static void free_afu_dev(struct device *dev)
65{
66 struct ocxl_afu *afu = to_ocxl_afu(dev);
67
68 ocxl_unregister_afu(afu);
69 free_afu(afu);
70}
71
72static int set_afu_device(struct ocxl_afu *afu, const char *location)
73{
74 struct ocxl_fn *fn = afu->fn;
75 int rc;
76
77 afu->dev.parent = &fn->dev;
78 afu->dev.release = free_afu_dev;
79 rc = dev_set_name(&afu->dev, "%s.%s.%hhu", afu->config.name, location,
80 afu->config.idx);
81 return rc;
82}
83
84static int assign_afu_actag(struct ocxl_afu *afu, struct pci_dev *dev)
85{
86 struct ocxl_fn *fn = afu->fn;
87 int actag_count, actag_offset;
88
89 /*
90 * if there were not enough actags for the function, each afu
91 * reduces its count as well
92 */
93 actag_count = afu->config.actag_supported *
94 fn->actag_enabled / fn->actag_supported;
95 actag_offset = ocxl_actag_afu_alloc(fn, actag_count);
96 if (actag_offset < 0) {
97 dev_err(&afu->dev, "Can't allocate %d actags for AFU: %d\n",
98 actag_count, actag_offset);
99 return actag_offset;
100 }
101 afu->actag_base = fn->actag_base + actag_offset;
102 afu->actag_enabled = actag_count;
103
104 ocxl_config_set_afu_actag(dev, afu->config.dvsec_afu_control_pos,
105 afu->actag_base, afu->actag_enabled);
106 dev_dbg(&afu->dev, "actag base=%d enabled=%d\n",
107 afu->actag_base, afu->actag_enabled);
108 return 0;
109}
110
111static void reclaim_afu_actag(struct ocxl_afu *afu)
112{
113 struct ocxl_fn *fn = afu->fn;
114 int start_offset, size;
115
116 start_offset = afu->actag_base - fn->actag_base;
117 size = afu->actag_enabled;
118 ocxl_actag_afu_free(afu->fn, start_offset, size);
119}
120
121static int assign_afu_pasid(struct ocxl_afu *afu, struct pci_dev *dev)
122{
123 struct ocxl_fn *fn = afu->fn;
124 int pasid_count, pasid_offset;
125
126 /*
127 * We only support the case where the function configuration
128 * requested enough PASIDs to cover all AFUs.
129 */
130 pasid_count = 1 << afu->config.pasid_supported_log;
131 pasid_offset = ocxl_pasid_afu_alloc(fn, pasid_count);
132 if (pasid_offset < 0) {
133 dev_err(&afu->dev, "Can't allocate %d PASIDs for AFU: %d\n",
134 pasid_count, pasid_offset);
135 return pasid_offset;
136 }
137 afu->pasid_base = fn->pasid_base + pasid_offset;
138 afu->pasid_count = 0;
139 afu->pasid_max = pasid_count;
140
141 ocxl_config_set_afu_pasid(dev, afu->config.dvsec_afu_control_pos,
142 afu->pasid_base,
143 afu->config.pasid_supported_log);
144 dev_dbg(&afu->dev, "PASID base=%d, enabled=%d\n",
145 afu->pasid_base, pasid_count);
146 return 0;
147}
148
149static void reclaim_afu_pasid(struct ocxl_afu *afu)
150{
151 struct ocxl_fn *fn = afu->fn;
152 int start_offset, size;
153
154 start_offset = afu->pasid_base - fn->pasid_base;
155 size = 1 << afu->config.pasid_supported_log;
156 ocxl_pasid_afu_free(afu->fn, start_offset, size);
157}
158
159static int reserve_fn_bar(struct ocxl_fn *fn, int bar)
160{
161 struct pci_dev *dev = to_pci_dev(fn->dev.parent);
162 int rc, idx;
163
164 if (bar != 0 && bar != 2 && bar != 4)
165 return -EINVAL;
166
167 idx = bar >> 1;
168 if (fn->bar_used[idx]++ == 0) {
169 rc = pci_request_region(dev, bar, "ocxl");
170 if (rc)
171 return rc;
172 }
173 return 0;
174}
175
176static void release_fn_bar(struct ocxl_fn *fn, int bar)
177{
178 struct pci_dev *dev = to_pci_dev(fn->dev.parent);
179 int idx;
180
181 if (bar != 0 && bar != 2 && bar != 4)
182 return;
183
184 idx = bar >> 1;
185 if (--fn->bar_used[idx] == 0)
186 pci_release_region(dev, bar);
187 WARN_ON(fn->bar_used[idx] < 0);
188}
189
190static int map_mmio_areas(struct ocxl_afu *afu, struct pci_dev *dev)
191{
192 int rc;
193
194 rc = reserve_fn_bar(afu->fn, afu->config.global_mmio_bar);
195 if (rc)
196 return rc;
197
198 rc = reserve_fn_bar(afu->fn, afu->config.pp_mmio_bar);
199 if (rc) {
200 release_fn_bar(afu->fn, afu->config.global_mmio_bar);
201 return rc;
202 }
203
204 afu->global_mmio_start =
205 pci_resource_start(dev, afu->config.global_mmio_bar) +
206 afu->config.global_mmio_offset;
207 afu->pp_mmio_start =
208 pci_resource_start(dev, afu->config.pp_mmio_bar) +
209 afu->config.pp_mmio_offset;
210
211 afu->global_mmio_ptr = ioremap(afu->global_mmio_start,
212 afu->config.global_mmio_size);
213 if (!afu->global_mmio_ptr) {
214 release_fn_bar(afu->fn, afu->config.pp_mmio_bar);
215 release_fn_bar(afu->fn, afu->config.global_mmio_bar);
216 dev_err(&dev->dev, "Error mapping global mmio area\n");
217 return -ENOMEM;
218 }
219
220 /*
221 * Leave an empty page between the per-process mmio area and
222 * the AFU interrupt mappings
223 */
224 afu->irq_base_offset = afu->config.pp_mmio_stride + PAGE_SIZE;
225 return 0;
226}
227
228static void unmap_mmio_areas(struct ocxl_afu *afu)
229{
230 if (afu->global_mmio_ptr) {
231 iounmap(afu->global_mmio_ptr);
232 afu->global_mmio_ptr = NULL;
233 }
234 afu->global_mmio_start = 0;
235 afu->pp_mmio_start = 0;
236 release_fn_bar(afu->fn, afu->config.pp_mmio_bar);
237 release_fn_bar(afu->fn, afu->config.global_mmio_bar);
238}
239
240static int configure_afu(struct ocxl_afu *afu, u8 afu_idx, struct pci_dev *dev)
241{
242 int rc;
243
244 rc = ocxl_config_read_afu(dev, &afu->fn->config, &afu->config, afu_idx);
245 if (rc)
246 return rc;
247
248 rc = set_afu_device(afu, dev_name(&dev->dev));
249 if (rc)
250 return rc;
251
252 rc = assign_afu_actag(afu, dev);
253 if (rc)
254 return rc;
255
256 rc = assign_afu_pasid(afu, dev);
257 if (rc) {
258 reclaim_afu_actag(afu);
259 return rc;
260 }
261
262 rc = map_mmio_areas(afu, dev);
263 if (rc) {
264 reclaim_afu_pasid(afu);
265 reclaim_afu_actag(afu);
266 return rc;
267 }
268 return 0;
269}
270
271static void deconfigure_afu(struct ocxl_afu *afu)
272{
273 unmap_mmio_areas(afu);
274 reclaim_afu_pasid(afu);
275 reclaim_afu_actag(afu);
276}
277
278static int activate_afu(struct pci_dev *dev, struct ocxl_afu *afu)
279{
280 int rc;
281
282 ocxl_config_set_afu_state(dev, afu->config.dvsec_afu_control_pos, 1);
283 /*
284 * Char device creation is the last step, as processes can
285 * call our driver immediately, so all our inits must be finished.
286 */
287 rc = ocxl_create_cdev(afu);
288 if (rc)
289 return rc;
290 return 0;
291}
292
293static void deactivate_afu(struct ocxl_afu *afu)
294{
295 struct pci_dev *dev = to_pci_dev(afu->fn->dev.parent);
296
297 ocxl_destroy_cdev(afu);
298 ocxl_config_set_afu_state(dev, afu->config.dvsec_afu_control_pos, 0);
299}
300
301static int init_afu(struct pci_dev *dev, struct ocxl_fn *fn, u8 afu_idx)
302{
303 int rc;
304 struct ocxl_afu *afu;
305
306 afu = alloc_afu(fn);
307 if (!afu)
308 return -ENOMEM;
309
310 rc = configure_afu(afu, afu_idx, dev);
311 if (rc) {
312 free_afu(afu);
313 return rc;
314 }
315
316 rc = ocxl_register_afu(afu);
317 if (rc)
318 goto err;
319
320 rc = ocxl_sysfs_add_afu(afu);
321 if (rc)
322 goto err;
323
324 rc = activate_afu(dev, afu);
325 if (rc)
326 goto err_sys;
327
328 list_add_tail(&afu->list, &fn->afu_list);
329 return 0;
330
331err_sys:
332 ocxl_sysfs_remove_afu(afu);
333err:
334 deconfigure_afu(afu);
335 device_unregister(&afu->dev);
336 return rc;
337}
338
339static void remove_afu(struct ocxl_afu *afu)
340{
341 list_del(&afu->list);
342 ocxl_context_detach_all(afu);
343 deactivate_afu(afu);
344 ocxl_sysfs_remove_afu(afu);
345 deconfigure_afu(afu);
346 device_unregister(&afu->dev);
347}
348
349static struct ocxl_fn *alloc_function(struct pci_dev *dev)
350{
351 struct ocxl_fn *fn;
352
353 fn = kzalloc(sizeof(struct ocxl_fn), GFP_KERNEL);
354 if (!fn)
355 return NULL;
356
357 INIT_LIST_HEAD(&fn->afu_list);
358 INIT_LIST_HEAD(&fn->pasid_list);
359 INIT_LIST_HEAD(&fn->actag_list);
360 return fn;
361}
362
363static void free_function(struct ocxl_fn *fn)
364{
365 WARN_ON(!list_empty(&fn->afu_list));
366 WARN_ON(!list_empty(&fn->pasid_list));
367 kfree(fn);
368}
369
370static void free_function_dev(struct device *dev)
371{
372 struct ocxl_fn *fn = to_ocxl_function(dev);
373
374 free_function(fn);
375}
376
377static int set_function_device(struct ocxl_fn *fn, struct pci_dev *dev)
378{
379 int rc;
380
381 fn->dev.parent = &dev->dev;
382 fn->dev.release = free_function_dev;
383 rc = dev_set_name(&fn->dev, "ocxlfn.%s", dev_name(&dev->dev));
384 if (rc)
385 return rc;
386 pci_set_drvdata(dev, fn);
387 return 0;
388}
389
390static int assign_function_actag(struct ocxl_fn *fn)
391{
392 struct pci_dev *dev = to_pci_dev(fn->dev.parent);
393 u16 base, enabled, supported;
394 int rc;
395
396 rc = ocxl_config_get_actag_info(dev, &base, &enabled, &supported);
397 if (rc)
398 return rc;
399
400 fn->actag_base = base;
401 fn->actag_enabled = enabled;
402 fn->actag_supported = supported;
403
404 ocxl_config_set_actag(dev, fn->config.dvsec_function_pos,
405 fn->actag_base, fn->actag_enabled);
406 dev_dbg(&fn->dev, "actag range starting at %d, enabled %d\n",
407 fn->actag_base, fn->actag_enabled);
408 return 0;
409}
410
411static int set_function_pasid(struct ocxl_fn *fn)
412{
413 struct pci_dev *dev = to_pci_dev(fn->dev.parent);
414 int rc, desired_count, max_count;
415
416 /* A function may not require any PASID */
417 if (fn->config.max_pasid_log < 0)
418 return 0;
419
420 rc = ocxl_config_get_pasid_info(dev, &max_count);
421 if (rc)
422 return rc;
423
424 desired_count = 1 << fn->config.max_pasid_log;
425
426 if (desired_count > max_count) {
427 dev_err(&fn->dev,
428 "Function requires more PASIDs than is available (%d vs. %d)\n",
429 desired_count, max_count);
430 return -ENOSPC;
431 }
432
433 fn->pasid_base = 0;
434 return 0;
435}
436
437static int configure_function(struct ocxl_fn *fn, struct pci_dev *dev)
438{
439 int rc;
440
441 rc = pci_enable_device(dev);
442 if (rc) {
443 dev_err(&dev->dev, "pci_enable_device failed: %d\n", rc);
444 return rc;
445 }
446
447 /*
448 * Once it has been confirmed to work on our hardware, we
449 * should reset the function, to force the adapter to restart
450 * from scratch.
451 * A function reset would also reset all its AFUs.
452 *
453 * Some hints for implementation:
454 *
455 * - there's not status bit to know when the reset is done. We
456 * should try reading the config space to know when it's
457 * done.
458 * - probably something like:
459 * Reset
460 * wait 100ms
461 * issue config read
462 * allow device up to 1 sec to return success on config
463 * read before declaring it broken
464 *
465 * Some shared logic on the card (CFG, TLX) won't be reset, so
466 * there's no guarantee that it will be enough.
467 */
468 rc = ocxl_config_read_function(dev, &fn->config);
469 if (rc)
470 return rc;
471
472 rc = set_function_device(fn, dev);
473 if (rc)
474 return rc;
475
476 rc = assign_function_actag(fn);
477 if (rc)
478 return rc;
479
480 rc = set_function_pasid(fn);
481 if (rc)
482 return rc;
483
484 rc = ocxl_link_setup(dev, 0, &fn->link);
485 if (rc)
486 return rc;
487
488 rc = ocxl_config_set_TL(dev, fn->config.dvsec_tl_pos);
489 if (rc) {
490 ocxl_link_release(dev, fn->link);
491 return rc;
492 }
493 return 0;
494}
495
496static void deconfigure_function(struct ocxl_fn *fn)
497{
498 struct pci_dev *dev = to_pci_dev(fn->dev.parent);
499
500 ocxl_link_release(dev, fn->link);
501 pci_disable_device(dev);
502}
503
504static struct ocxl_fn *init_function(struct pci_dev *dev)
505{
506 struct ocxl_fn *fn;
507 int rc;
508
509 fn = alloc_function(dev);
510 if (!fn)
511 return ERR_PTR(-ENOMEM);
512
513 rc = configure_function(fn, dev);
514 if (rc) {
515 free_function(fn);
516 return ERR_PTR(rc);
517 }
518
519 rc = device_register(&fn->dev);
520 if (rc) {
521 deconfigure_function(fn);
522 put_device(&fn->dev);
523 return ERR_PTR(rc);
524 }
525 return fn;
526}
527
528static void remove_function(struct ocxl_fn *fn)
529{
530 deconfigure_function(fn);
531 device_unregister(&fn->dev);
532}
533
534static int ocxl_probe(struct pci_dev *dev, const struct pci_device_id *id) 17static int ocxl_probe(struct pci_dev *dev, const struct pci_device_id *id)
535{ 18{
536 int rc, afu_count = 0; 19 int rc, afu_count = 0;