1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * FPGA Manager Core |
4 | * |
5 | * Copyright (C) 2013-2015 Altera Corporation |
6 | * Copyright (C) 2017 Intel Corporation |
7 | * |
8 | * With code from the mailing list: |
9 | * Copyright (C) 2013 Xilinx, Inc. |
10 | */ |
11 | #include <linux/firmware.h> |
12 | #include <linux/fpga/fpga-mgr.h> |
13 | #include <linux/idr.h> |
14 | #include <linux/module.h> |
15 | #include <linux/of.h> |
16 | #include <linux/mutex.h> |
17 | #include <linux/slab.h> |
18 | #include <linux/scatterlist.h> |
19 | #include <linux/highmem.h> |
20 | |
21 | static DEFINE_IDA(fpga_mgr_ida); |
22 | static const struct class fpga_mgr_class; |
23 | |
24 | struct fpga_mgr_devres { |
25 | struct fpga_manager *mgr; |
26 | }; |
27 | |
28 | static inline void fpga_mgr_fpga_remove(struct fpga_manager *mgr) |
29 | { |
30 | if (mgr->mops->fpga_remove) |
31 | mgr->mops->fpga_remove(mgr); |
32 | } |
33 | |
34 | static inline enum fpga_mgr_states fpga_mgr_state(struct fpga_manager *mgr) |
35 | { |
36 | if (mgr->mops->state) |
37 | return mgr->mops->state(mgr); |
38 | return FPGA_MGR_STATE_UNKNOWN; |
39 | } |
40 | |
41 | static inline u64 fpga_mgr_status(struct fpga_manager *mgr) |
42 | { |
43 | if (mgr->mops->status) |
44 | return mgr->mops->status(mgr); |
45 | return 0; |
46 | } |
47 | |
48 | static inline int fpga_mgr_write(struct fpga_manager *mgr, const char *buf, size_t count) |
49 | { |
50 | if (mgr->mops->write) |
51 | return mgr->mops->write(mgr, buf, count); |
52 | return -EOPNOTSUPP; |
53 | } |
54 | |
55 | /* |
56 | * After all the FPGA image has been written, do the device specific steps to |
57 | * finish and set the FPGA into operating mode. |
58 | */ |
59 | static inline int fpga_mgr_write_complete(struct fpga_manager *mgr, |
60 | struct fpga_image_info *info) |
61 | { |
62 | int ret = 0; |
63 | |
64 | mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE; |
65 | if (mgr->mops->write_complete) |
66 | ret = mgr->mops->write_complete(mgr, info); |
67 | if (ret) { |
68 | dev_err(&mgr->dev, "Error after writing image data to FPGA\n" ); |
69 | mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR; |
70 | return ret; |
71 | } |
72 | mgr->state = FPGA_MGR_STATE_OPERATING; |
73 | |
74 | return 0; |
75 | } |
76 | |
77 | static inline int (struct fpga_manager *mgr, |
78 | struct fpga_image_info *info, |
79 | const char *buf, size_t count) |
80 | { |
81 | if (mgr->mops->parse_header) |
82 | return mgr->mops->parse_header(mgr, info, buf, count); |
83 | return 0; |
84 | } |
85 | |
86 | static inline int fpga_mgr_write_init(struct fpga_manager *mgr, |
87 | struct fpga_image_info *info, |
88 | const char *buf, size_t count) |
89 | { |
90 | if (mgr->mops->write_init) |
91 | return mgr->mops->write_init(mgr, info, buf, count); |
92 | return 0; |
93 | } |
94 | |
95 | static inline int fpga_mgr_write_sg(struct fpga_manager *mgr, |
96 | struct sg_table *sgt) |
97 | { |
98 | if (mgr->mops->write_sg) |
99 | return mgr->mops->write_sg(mgr, sgt); |
100 | return -EOPNOTSUPP; |
101 | } |
102 | |
103 | /** |
104 | * fpga_image_info_alloc - Allocate an FPGA image info struct |
105 | * @dev: owning device |
106 | * |
107 | * Return: struct fpga_image_info or NULL |
108 | */ |
109 | struct fpga_image_info *fpga_image_info_alloc(struct device *dev) |
110 | { |
111 | struct fpga_image_info *info; |
112 | |
113 | get_device(dev); |
114 | |
115 | info = devm_kzalloc(dev, size: sizeof(*info), GFP_KERNEL); |
116 | if (!info) { |
117 | put_device(dev); |
118 | return NULL; |
119 | } |
120 | |
121 | info->dev = dev; |
122 | |
123 | return info; |
124 | } |
125 | EXPORT_SYMBOL_GPL(fpga_image_info_alloc); |
126 | |
127 | /** |
128 | * fpga_image_info_free - Free an FPGA image info struct |
129 | * @info: FPGA image info struct to free |
130 | */ |
131 | void fpga_image_info_free(struct fpga_image_info *info) |
132 | { |
133 | struct device *dev; |
134 | |
135 | if (!info) |
136 | return; |
137 | |
138 | dev = info->dev; |
139 | if (info->firmware_name) |
140 | devm_kfree(dev, p: info->firmware_name); |
141 | |
142 | devm_kfree(dev, p: info); |
143 | put_device(dev); |
144 | } |
145 | EXPORT_SYMBOL_GPL(fpga_image_info_free); |
146 | |
147 | /* |
148 | * Call the low level driver's parse_header function with entire FPGA image |
149 | * buffer on the input. This will set info->header_size and info->data_size. |
150 | */ |
151 | static int (struct fpga_manager *mgr, |
152 | struct fpga_image_info *info, |
153 | const char *buf, size_t count) |
154 | { |
155 | int ret; |
156 | |
157 | mgr->state = FPGA_MGR_STATE_PARSE_HEADER; |
158 | ret = fpga_mgr_parse_header(mgr, info, buf, count); |
159 | |
160 | if (info->header_size + info->data_size > count) { |
161 | dev_err(&mgr->dev, "Bitstream data outruns FPGA image\n" ); |
162 | ret = -EINVAL; |
163 | } |
164 | |
165 | if (ret) { |
166 | dev_err(&mgr->dev, "Error while parsing FPGA image header\n" ); |
167 | mgr->state = FPGA_MGR_STATE_PARSE_HEADER_ERR; |
168 | } |
169 | |
170 | return ret; |
171 | } |
172 | |
173 | /* |
174 | * Call the low level driver's parse_header function with first fragment of |
175 | * scattered FPGA image on the input. If header fits first fragment, |
176 | * parse_header will set info->header_size and info->data_size. If it is not, |
177 | * parse_header will set desired size to info->header_size and -EAGAIN will be |
178 | * returned. |
179 | */ |
180 | static int (struct fpga_manager *mgr, |
181 | struct fpga_image_info *info, |
182 | struct sg_table *sgt) |
183 | { |
184 | struct sg_mapping_iter miter; |
185 | int ret; |
186 | |
187 | mgr->state = FPGA_MGR_STATE_PARSE_HEADER; |
188 | |
189 | sg_miter_start(miter: &miter, sgl: sgt->sgl, nents: sgt->nents, SG_MITER_FROM_SG); |
190 | if (sg_miter_next(miter: &miter) && |
191 | miter.length >= info->header_size) |
192 | ret = fpga_mgr_parse_header(mgr, info, buf: miter.addr, count: miter.length); |
193 | else |
194 | ret = -EAGAIN; |
195 | sg_miter_stop(miter: &miter); |
196 | |
197 | if (ret && ret != -EAGAIN) { |
198 | dev_err(&mgr->dev, "Error while parsing FPGA image header\n" ); |
199 | mgr->state = FPGA_MGR_STATE_PARSE_HEADER_ERR; |
200 | } |
201 | |
202 | return ret; |
203 | } |
204 | |
205 | /* |
206 | * Copy scattered FPGA image fragments to temporary buffer and call the |
207 | * low level driver's parse_header function. This should be called after |
208 | * fpga_mgr_parse_header_sg_first() returned -EAGAIN. In case of success, |
209 | * pointer to the newly allocated image header copy will be returned and |
210 | * its size will be set into *ret_size. Returned buffer needs to be freed. |
211 | */ |
212 | static void *(struct fpga_manager *mgr, |
213 | struct fpga_image_info *info, |
214 | struct sg_table *sgt, size_t *ret_size) |
215 | { |
216 | size_t len, , = 0; |
217 | char *new_buf, *buf = NULL; |
218 | int ret; |
219 | |
220 | do { |
221 | new_header_size = info->header_size; |
222 | if (new_header_size <= header_size) { |
223 | dev_err(&mgr->dev, "Requested invalid header size\n" ); |
224 | ret = -EFAULT; |
225 | break; |
226 | } |
227 | |
228 | new_buf = krealloc(objp: buf, new_size: new_header_size, GFP_KERNEL); |
229 | if (!new_buf) { |
230 | ret = -ENOMEM; |
231 | break; |
232 | } |
233 | |
234 | buf = new_buf; |
235 | |
236 | len = sg_pcopy_to_buffer(sgl: sgt->sgl, nents: sgt->nents, |
237 | buf: buf + header_size, |
238 | buflen: new_header_size - header_size, |
239 | skip: header_size); |
240 | if (len != new_header_size - header_size) { |
241 | ret = -EFAULT; |
242 | break; |
243 | } |
244 | |
245 | header_size = new_header_size; |
246 | ret = fpga_mgr_parse_header(mgr, info, buf, count: header_size); |
247 | } while (ret == -EAGAIN); |
248 | |
249 | if (ret) { |
250 | dev_err(&mgr->dev, "Error while parsing FPGA image header\n" ); |
251 | mgr->state = FPGA_MGR_STATE_PARSE_HEADER_ERR; |
252 | kfree(objp: buf); |
253 | buf = ERR_PTR(error: ret); |
254 | } |
255 | |
256 | *ret_size = header_size; |
257 | |
258 | return buf; |
259 | } |
260 | |
261 | /* |
262 | * Call the low level driver's write_init function. This will do the |
263 | * device-specific things to get the FPGA into the state where it is ready to |
264 | * receive an FPGA image. The low level driver gets to see at least first |
265 | * info->header_size bytes in the buffer. If info->header_size is 0, |
266 | * write_init will not get any bytes of image buffer. |
267 | */ |
268 | static int fpga_mgr_write_init_buf(struct fpga_manager *mgr, |
269 | struct fpga_image_info *info, |
270 | const char *buf, size_t count) |
271 | { |
272 | size_t = info->header_size; |
273 | int ret; |
274 | |
275 | mgr->state = FPGA_MGR_STATE_WRITE_INIT; |
276 | |
277 | if (header_size > count) |
278 | ret = -EINVAL; |
279 | else if (!header_size) |
280 | ret = fpga_mgr_write_init(mgr, info, NULL, count: 0); |
281 | else |
282 | ret = fpga_mgr_write_init(mgr, info, buf, count); |
283 | |
284 | if (ret) { |
285 | dev_err(&mgr->dev, "Error preparing FPGA for writing\n" ); |
286 | mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR; |
287 | return ret; |
288 | } |
289 | |
290 | return 0; |
291 | } |
292 | |
293 | static int fpga_mgr_prepare_sg(struct fpga_manager *mgr, |
294 | struct fpga_image_info *info, |
295 | struct sg_table *sgt) |
296 | { |
297 | struct sg_mapping_iter miter; |
298 | size_t len; |
299 | char *buf; |
300 | int ret; |
301 | |
302 | /* Short path. Low level driver don't care about image header. */ |
303 | if (!mgr->mops->initial_header_size && !mgr->mops->parse_header) |
304 | return fpga_mgr_write_init_buf(mgr, info, NULL, count: 0); |
305 | |
306 | /* |
307 | * First try to use miter to map the first fragment to access the |
308 | * header, this is the typical path. |
309 | */ |
310 | ret = fpga_mgr_parse_header_sg_first(mgr, info, sgt); |
311 | /* If 0, header fits first fragment, call write_init on it */ |
312 | if (!ret) { |
313 | sg_miter_start(miter: &miter, sgl: sgt->sgl, nents: sgt->nents, SG_MITER_FROM_SG); |
314 | if (sg_miter_next(miter: &miter)) { |
315 | ret = fpga_mgr_write_init_buf(mgr, info, buf: miter.addr, |
316 | count: miter.length); |
317 | sg_miter_stop(miter: &miter); |
318 | return ret; |
319 | } |
320 | sg_miter_stop(miter: &miter); |
321 | /* |
322 | * If -EAGAIN, more sg buffer is needed, |
323 | * otherwise an error has occurred. |
324 | */ |
325 | } else if (ret != -EAGAIN) { |
326 | return ret; |
327 | } |
328 | |
329 | /* |
330 | * Copy the fragments into temporary memory. |
331 | * Copying is done inside fpga_mgr_parse_header_sg(). |
332 | */ |
333 | buf = fpga_mgr_parse_header_sg(mgr, info, sgt, ret_size: &len); |
334 | if (IS_ERR(ptr: buf)) |
335 | return PTR_ERR(ptr: buf); |
336 | |
337 | ret = fpga_mgr_write_init_buf(mgr, info, buf, count: len); |
338 | |
339 | kfree(objp: buf); |
340 | |
341 | return ret; |
342 | } |
343 | |
344 | /** |
345 | * fpga_mgr_buf_load_sg - load fpga from image in buffer from a scatter list |
346 | * @mgr: fpga manager |
347 | * @info: fpga image specific information |
348 | * @sgt: scatterlist table |
349 | * |
350 | * Step the low level fpga manager through the device-specific steps of getting |
351 | * an FPGA ready to be configured, writing the image to it, then doing whatever |
352 | * post-configuration steps necessary. This code assumes the caller got the |
353 | * mgr pointer from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is |
354 | * not an error code. |
355 | * |
356 | * This is the preferred entry point for FPGA programming, it does not require |
357 | * any contiguous kernel memory. |
358 | * |
359 | * Return: 0 on success, negative error code otherwise. |
360 | */ |
361 | static int fpga_mgr_buf_load_sg(struct fpga_manager *mgr, |
362 | struct fpga_image_info *info, |
363 | struct sg_table *sgt) |
364 | { |
365 | int ret; |
366 | |
367 | ret = fpga_mgr_prepare_sg(mgr, info, sgt); |
368 | if (ret) |
369 | return ret; |
370 | |
371 | /* Write the FPGA image to the FPGA. */ |
372 | mgr->state = FPGA_MGR_STATE_WRITE; |
373 | if (mgr->mops->write_sg) { |
374 | ret = fpga_mgr_write_sg(mgr, sgt); |
375 | } else { |
376 | size_t length, count = 0, data_size = info->data_size; |
377 | struct sg_mapping_iter miter; |
378 | |
379 | sg_miter_start(miter: &miter, sgl: sgt->sgl, nents: sgt->nents, SG_MITER_FROM_SG); |
380 | |
381 | if (mgr->mops->skip_header && |
382 | !sg_miter_skip(miter: &miter, offset: info->header_size)) { |
383 | ret = -EINVAL; |
384 | goto out; |
385 | } |
386 | |
387 | while (sg_miter_next(miter: &miter)) { |
388 | if (data_size) |
389 | length = min(miter.length, data_size - count); |
390 | else |
391 | length = miter.length; |
392 | |
393 | ret = fpga_mgr_write(mgr, buf: miter.addr, count: length); |
394 | if (ret) |
395 | break; |
396 | |
397 | count += length; |
398 | if (data_size && count >= data_size) |
399 | break; |
400 | } |
401 | sg_miter_stop(miter: &miter); |
402 | } |
403 | |
404 | out: |
405 | if (ret) { |
406 | dev_err(&mgr->dev, "Error while writing image data to FPGA\n" ); |
407 | mgr->state = FPGA_MGR_STATE_WRITE_ERR; |
408 | return ret; |
409 | } |
410 | |
411 | return fpga_mgr_write_complete(mgr, info); |
412 | } |
413 | |
414 | static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr, |
415 | struct fpga_image_info *info, |
416 | const char *buf, size_t count) |
417 | { |
418 | int ret; |
419 | |
420 | ret = fpga_mgr_parse_header_mapped(mgr, info, buf, count); |
421 | if (ret) |
422 | return ret; |
423 | |
424 | ret = fpga_mgr_write_init_buf(mgr, info, buf, count); |
425 | if (ret) |
426 | return ret; |
427 | |
428 | if (mgr->mops->skip_header) { |
429 | buf += info->header_size; |
430 | count -= info->header_size; |
431 | } |
432 | |
433 | if (info->data_size) |
434 | count = info->data_size; |
435 | |
436 | /* |
437 | * Write the FPGA image to the FPGA. |
438 | */ |
439 | mgr->state = FPGA_MGR_STATE_WRITE; |
440 | ret = fpga_mgr_write(mgr, buf, count); |
441 | if (ret) { |
442 | dev_err(&mgr->dev, "Error while writing image data to FPGA\n" ); |
443 | mgr->state = FPGA_MGR_STATE_WRITE_ERR; |
444 | return ret; |
445 | } |
446 | |
447 | return fpga_mgr_write_complete(mgr, info); |
448 | } |
449 | |
450 | /** |
451 | * fpga_mgr_buf_load - load fpga from image in buffer |
452 | * @mgr: fpga manager |
453 | * @info: fpga image info |
454 | * @buf: buffer contain fpga image |
455 | * @count: byte count of buf |
456 | * |
457 | * Step the low level fpga manager through the device-specific steps of getting |
458 | * an FPGA ready to be configured, writing the image to it, then doing whatever |
459 | * post-configuration steps necessary. This code assumes the caller got the |
460 | * mgr pointer from of_fpga_mgr_get() and checked that it is not an error code. |
461 | * |
462 | * Return: 0 on success, negative error code otherwise. |
463 | */ |
464 | static int fpga_mgr_buf_load(struct fpga_manager *mgr, |
465 | struct fpga_image_info *info, |
466 | const char *buf, size_t count) |
467 | { |
468 | struct page **pages; |
469 | struct sg_table sgt; |
470 | const void *p; |
471 | int nr_pages; |
472 | int index; |
473 | int rc; |
474 | |
475 | /* |
476 | * This is just a fast path if the caller has already created a |
477 | * contiguous kernel buffer and the driver doesn't require SG, non-SG |
478 | * drivers will still work on the slow path. |
479 | */ |
480 | if (mgr->mops->write) |
481 | return fpga_mgr_buf_load_mapped(mgr, info, buf, count); |
482 | |
483 | /* |
484 | * Convert the linear kernel pointer into a sg_table of pages for use |
485 | * by the driver. |
486 | */ |
487 | nr_pages = DIV_ROUND_UP((unsigned long)buf + count, PAGE_SIZE) - |
488 | (unsigned long)buf / PAGE_SIZE; |
489 | pages = kmalloc_array(n: nr_pages, size: sizeof(struct page *), GFP_KERNEL); |
490 | if (!pages) |
491 | return -ENOMEM; |
492 | |
493 | p = buf - offset_in_page(buf); |
494 | for (index = 0; index < nr_pages; index++) { |
495 | if (is_vmalloc_addr(x: p)) |
496 | pages[index] = vmalloc_to_page(addr: p); |
497 | else |
498 | pages[index] = kmap_to_page(addr: (void *)p); |
499 | if (!pages[index]) { |
500 | kfree(objp: pages); |
501 | return -EFAULT; |
502 | } |
503 | p += PAGE_SIZE; |
504 | } |
505 | |
506 | /* |
507 | * The temporary pages list is used to code share the merging algorithm |
508 | * in sg_alloc_table_from_pages |
509 | */ |
510 | rc = sg_alloc_table_from_pages(sgt: &sgt, pages, n_pages: index, offset_in_page(buf), |
511 | size: count, GFP_KERNEL); |
512 | kfree(objp: pages); |
513 | if (rc) |
514 | return rc; |
515 | |
516 | rc = fpga_mgr_buf_load_sg(mgr, info, sgt: &sgt); |
517 | sg_free_table(&sgt); |
518 | |
519 | return rc; |
520 | } |
521 | |
522 | /** |
523 | * fpga_mgr_firmware_load - request firmware and load to fpga |
524 | * @mgr: fpga manager |
525 | * @info: fpga image specific information |
526 | * @image_name: name of image file on the firmware search path |
527 | * |
528 | * Request an FPGA image using the firmware class, then write out to the FPGA. |
529 | * Update the state before each step to provide info on what step failed if |
530 | * there is a failure. This code assumes the caller got the mgr pointer |
531 | * from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is not an error |
532 | * code. |
533 | * |
534 | * Return: 0 on success, negative error code otherwise. |
535 | */ |
536 | static int fpga_mgr_firmware_load(struct fpga_manager *mgr, |
537 | struct fpga_image_info *info, |
538 | const char *image_name) |
539 | { |
540 | struct device *dev = &mgr->dev; |
541 | const struct firmware *fw; |
542 | int ret; |
543 | |
544 | dev_info(dev, "writing %s to %s\n" , image_name, mgr->name); |
545 | |
546 | mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ; |
547 | |
548 | ret = request_firmware(fw: &fw, name: image_name, device: dev); |
549 | if (ret) { |
550 | mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ_ERR; |
551 | dev_err(dev, "Error requesting firmware %s\n" , image_name); |
552 | return ret; |
553 | } |
554 | |
555 | ret = fpga_mgr_buf_load(mgr, info, buf: fw->data, count: fw->size); |
556 | |
557 | release_firmware(fw); |
558 | |
559 | return ret; |
560 | } |
561 | |
562 | /** |
563 | * fpga_mgr_load - load FPGA from scatter/gather table, buffer, or firmware |
564 | * @mgr: fpga manager |
565 | * @info: fpga image information. |
566 | * |
567 | * Load the FPGA from an image which is indicated in @info. If successful, the |
568 | * FPGA ends up in operating mode. |
569 | * |
570 | * Return: 0 on success, negative error code otherwise. |
571 | */ |
572 | int fpga_mgr_load(struct fpga_manager *mgr, struct fpga_image_info *info) |
573 | { |
574 | info->header_size = mgr->mops->initial_header_size; |
575 | |
576 | if (info->sgt) |
577 | return fpga_mgr_buf_load_sg(mgr, info, sgt: info->sgt); |
578 | if (info->buf && info->count) |
579 | return fpga_mgr_buf_load(mgr, info, buf: info->buf, count: info->count); |
580 | if (info->firmware_name) |
581 | return fpga_mgr_firmware_load(mgr, info, image_name: info->firmware_name); |
582 | return -EINVAL; |
583 | } |
584 | EXPORT_SYMBOL_GPL(fpga_mgr_load); |
585 | |
586 | static const char * const state_str[] = { |
587 | [FPGA_MGR_STATE_UNKNOWN] = "unknown" , |
588 | [FPGA_MGR_STATE_POWER_OFF] = "power off" , |
589 | [FPGA_MGR_STATE_POWER_UP] = "power up" , |
590 | [FPGA_MGR_STATE_RESET] = "reset" , |
591 | |
592 | /* requesting FPGA image from firmware */ |
593 | [FPGA_MGR_STATE_FIRMWARE_REQ] = "firmware request" , |
594 | [FPGA_MGR_STATE_FIRMWARE_REQ_ERR] = "firmware request error" , |
595 | |
596 | /* Parse FPGA image header */ |
597 | [FPGA_MGR_STATE_PARSE_HEADER] = "parse header" , |
598 | [FPGA_MGR_STATE_PARSE_HEADER_ERR] = "parse header error" , |
599 | |
600 | /* Preparing FPGA to receive image */ |
601 | [FPGA_MGR_STATE_WRITE_INIT] = "write init" , |
602 | [FPGA_MGR_STATE_WRITE_INIT_ERR] = "write init error" , |
603 | |
604 | /* Writing image to FPGA */ |
605 | [FPGA_MGR_STATE_WRITE] = "write" , |
606 | [FPGA_MGR_STATE_WRITE_ERR] = "write error" , |
607 | |
608 | /* Finishing configuration after image has been written */ |
609 | [FPGA_MGR_STATE_WRITE_COMPLETE] = "write complete" , |
610 | [FPGA_MGR_STATE_WRITE_COMPLETE_ERR] = "write complete error" , |
611 | |
612 | /* FPGA reports to be in normal operating mode */ |
613 | [FPGA_MGR_STATE_OPERATING] = "operating" , |
614 | }; |
615 | |
616 | static ssize_t name_show(struct device *dev, |
617 | struct device_attribute *attr, char *buf) |
618 | { |
619 | struct fpga_manager *mgr = to_fpga_manager(dev); |
620 | |
621 | return sprintf(buf, fmt: "%s\n" , mgr->name); |
622 | } |
623 | |
624 | static ssize_t state_show(struct device *dev, |
625 | struct device_attribute *attr, char *buf) |
626 | { |
627 | struct fpga_manager *mgr = to_fpga_manager(dev); |
628 | |
629 | return sprintf(buf, fmt: "%s\n" , state_str[mgr->state]); |
630 | } |
631 | |
632 | static ssize_t status_show(struct device *dev, |
633 | struct device_attribute *attr, char *buf) |
634 | { |
635 | struct fpga_manager *mgr = to_fpga_manager(dev); |
636 | u64 status; |
637 | int len = 0; |
638 | |
639 | status = fpga_mgr_status(mgr); |
640 | |
641 | if (status & FPGA_MGR_STATUS_OPERATION_ERR) |
642 | len += sprintf(buf: buf + len, fmt: "reconfig operation error\n" ); |
643 | if (status & FPGA_MGR_STATUS_CRC_ERR) |
644 | len += sprintf(buf: buf + len, fmt: "reconfig CRC error\n" ); |
645 | if (status & FPGA_MGR_STATUS_INCOMPATIBLE_IMAGE_ERR) |
646 | len += sprintf(buf: buf + len, fmt: "reconfig incompatible image\n" ); |
647 | if (status & FPGA_MGR_STATUS_IP_PROTOCOL_ERR) |
648 | len += sprintf(buf: buf + len, fmt: "reconfig IP protocol error\n" ); |
649 | if (status & FPGA_MGR_STATUS_FIFO_OVERFLOW_ERR) |
650 | len += sprintf(buf: buf + len, fmt: "reconfig fifo overflow error\n" ); |
651 | |
652 | return len; |
653 | } |
654 | |
655 | static DEVICE_ATTR_RO(name); |
656 | static DEVICE_ATTR_RO(state); |
657 | static DEVICE_ATTR_RO(status); |
658 | |
659 | static struct attribute *fpga_mgr_attrs[] = { |
660 | &dev_attr_name.attr, |
661 | &dev_attr_state.attr, |
662 | &dev_attr_status.attr, |
663 | NULL, |
664 | }; |
665 | ATTRIBUTE_GROUPS(fpga_mgr); |
666 | |
667 | static struct fpga_manager *__fpga_mgr_get(struct device *dev) |
668 | { |
669 | struct fpga_manager *mgr; |
670 | |
671 | mgr = to_fpga_manager(dev); |
672 | |
673 | if (!try_module_get(module: dev->parent->driver->owner)) |
674 | goto err_dev; |
675 | |
676 | return mgr; |
677 | |
678 | err_dev: |
679 | put_device(dev); |
680 | return ERR_PTR(error: -ENODEV); |
681 | } |
682 | |
683 | static int fpga_mgr_dev_match(struct device *dev, const void *data) |
684 | { |
685 | return dev->parent == data; |
686 | } |
687 | |
688 | /** |
689 | * fpga_mgr_get - Given a device, get a reference to an fpga mgr. |
690 | * @dev: parent device that fpga mgr was registered with |
691 | * |
692 | * Return: fpga manager struct or IS_ERR() condition containing error code. |
693 | */ |
694 | struct fpga_manager *fpga_mgr_get(struct device *dev) |
695 | { |
696 | struct device *mgr_dev = class_find_device(class: &fpga_mgr_class, NULL, data: dev, |
697 | match: fpga_mgr_dev_match); |
698 | if (!mgr_dev) |
699 | return ERR_PTR(error: -ENODEV); |
700 | |
701 | return __fpga_mgr_get(dev: mgr_dev); |
702 | } |
703 | EXPORT_SYMBOL_GPL(fpga_mgr_get); |
704 | |
705 | /** |
706 | * of_fpga_mgr_get - Given a device node, get a reference to an fpga mgr. |
707 | * |
708 | * @node: device node |
709 | * |
710 | * Return: fpga manager struct or IS_ERR() condition containing error code. |
711 | */ |
712 | struct fpga_manager *of_fpga_mgr_get(struct device_node *node) |
713 | { |
714 | struct device *dev; |
715 | |
716 | dev = class_find_device_by_of_node(class: &fpga_mgr_class, np: node); |
717 | if (!dev) |
718 | return ERR_PTR(error: -ENODEV); |
719 | |
720 | return __fpga_mgr_get(dev); |
721 | } |
722 | EXPORT_SYMBOL_GPL(of_fpga_mgr_get); |
723 | |
724 | /** |
725 | * fpga_mgr_put - release a reference to an fpga manager |
726 | * @mgr: fpga manager structure |
727 | */ |
728 | void fpga_mgr_put(struct fpga_manager *mgr) |
729 | { |
730 | module_put(module: mgr->dev.parent->driver->owner); |
731 | put_device(dev: &mgr->dev); |
732 | } |
733 | EXPORT_SYMBOL_GPL(fpga_mgr_put); |
734 | |
735 | /** |
736 | * fpga_mgr_lock - Lock FPGA manager for exclusive use |
737 | * @mgr: fpga manager |
738 | * |
739 | * Given a pointer to FPGA Manager (from fpga_mgr_get() or |
740 | * of_fpga_mgr_put()) attempt to get the mutex. The user should call |
741 | * fpga_mgr_lock() and verify that it returns 0 before attempting to |
742 | * program the FPGA. Likewise, the user should call fpga_mgr_unlock |
743 | * when done programming the FPGA. |
744 | * |
745 | * Return: 0 for success or -EBUSY |
746 | */ |
747 | int fpga_mgr_lock(struct fpga_manager *mgr) |
748 | { |
749 | if (!mutex_trylock(lock: &mgr->ref_mutex)) { |
750 | dev_err(&mgr->dev, "FPGA manager is in use.\n" ); |
751 | return -EBUSY; |
752 | } |
753 | |
754 | return 0; |
755 | } |
756 | EXPORT_SYMBOL_GPL(fpga_mgr_lock); |
757 | |
758 | /** |
759 | * fpga_mgr_unlock - Unlock FPGA manager after done programming |
760 | * @mgr: fpga manager |
761 | */ |
762 | void fpga_mgr_unlock(struct fpga_manager *mgr) |
763 | { |
764 | mutex_unlock(lock: &mgr->ref_mutex); |
765 | } |
766 | EXPORT_SYMBOL_GPL(fpga_mgr_unlock); |
767 | |
768 | /** |
769 | * fpga_mgr_register_full - create and register an FPGA Manager device |
770 | * @parent: fpga manager device from pdev |
771 | * @info: parameters for fpga manager |
772 | * |
773 | * The caller of this function is responsible for calling fpga_mgr_unregister(). |
774 | * Using devm_fpga_mgr_register_full() instead is recommended. |
775 | * |
776 | * Return: pointer to struct fpga_manager pointer or ERR_PTR() |
777 | */ |
778 | struct fpga_manager * |
779 | fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info) |
780 | { |
781 | const struct fpga_manager_ops *mops = info->mops; |
782 | struct fpga_manager *mgr; |
783 | int id, ret; |
784 | |
785 | if (!mops) { |
786 | dev_err(parent, "Attempt to register without fpga_manager_ops\n" ); |
787 | return ERR_PTR(error: -EINVAL); |
788 | } |
789 | |
790 | if (!info->name || !strlen(info->name)) { |
791 | dev_err(parent, "Attempt to register with no name!\n" ); |
792 | return ERR_PTR(error: -EINVAL); |
793 | } |
794 | |
795 | mgr = kzalloc(size: sizeof(*mgr), GFP_KERNEL); |
796 | if (!mgr) |
797 | return ERR_PTR(error: -ENOMEM); |
798 | |
799 | id = ida_alloc(ida: &fpga_mgr_ida, GFP_KERNEL); |
800 | if (id < 0) { |
801 | ret = id; |
802 | goto error_kfree; |
803 | } |
804 | |
805 | mutex_init(&mgr->ref_mutex); |
806 | |
807 | mgr->name = info->name; |
808 | mgr->mops = info->mops; |
809 | mgr->priv = info->priv; |
810 | mgr->compat_id = info->compat_id; |
811 | |
812 | mgr->dev.class = &fpga_mgr_class; |
813 | mgr->dev.groups = mops->groups; |
814 | mgr->dev.parent = parent; |
815 | mgr->dev.of_node = parent->of_node; |
816 | mgr->dev.id = id; |
817 | |
818 | ret = dev_set_name(dev: &mgr->dev, name: "fpga%d" , id); |
819 | if (ret) |
820 | goto error_device; |
821 | |
822 | /* |
823 | * Initialize framework state by requesting low level driver read state |
824 | * from device. FPGA may be in reset mode or may have been programmed |
825 | * by bootloader or EEPROM. |
826 | */ |
827 | mgr->state = fpga_mgr_state(mgr); |
828 | |
829 | ret = device_register(dev: &mgr->dev); |
830 | if (ret) { |
831 | put_device(dev: &mgr->dev); |
832 | return ERR_PTR(error: ret); |
833 | } |
834 | |
835 | return mgr; |
836 | |
837 | error_device: |
838 | ida_free(&fpga_mgr_ida, id); |
839 | error_kfree: |
840 | kfree(objp: mgr); |
841 | |
842 | return ERR_PTR(error: ret); |
843 | } |
844 | EXPORT_SYMBOL_GPL(fpga_mgr_register_full); |
845 | |
846 | /** |
847 | * fpga_mgr_register - create and register an FPGA Manager device |
848 | * @parent: fpga manager device from pdev |
849 | * @name: fpga manager name |
850 | * @mops: pointer to structure of fpga manager ops |
851 | * @priv: fpga manager private data |
852 | * |
853 | * The caller of this function is responsible for calling fpga_mgr_unregister(). |
854 | * Using devm_fpga_mgr_register() instead is recommended. This simple |
855 | * version of the register function should be sufficient for most users. The |
856 | * fpga_mgr_register_full() function is available for users that need to pass |
857 | * additional, optional parameters. |
858 | * |
859 | * Return: pointer to struct fpga_manager pointer or ERR_PTR() |
860 | */ |
861 | struct fpga_manager * |
862 | fpga_mgr_register(struct device *parent, const char *name, |
863 | const struct fpga_manager_ops *mops, void *priv) |
864 | { |
865 | struct fpga_manager_info info = { 0 }; |
866 | |
867 | info.name = name; |
868 | info.mops = mops; |
869 | info.priv = priv; |
870 | |
871 | return fpga_mgr_register_full(parent, &info); |
872 | } |
873 | EXPORT_SYMBOL_GPL(fpga_mgr_register); |
874 | |
875 | /** |
876 | * fpga_mgr_unregister - unregister an FPGA manager |
877 | * @mgr: fpga manager struct |
878 | * |
879 | * This function is intended for use in an FPGA manager driver's remove function. |
880 | */ |
881 | void fpga_mgr_unregister(struct fpga_manager *mgr) |
882 | { |
883 | dev_info(&mgr->dev, "%s %s\n" , __func__, mgr->name); |
884 | |
885 | /* |
886 | * If the low level driver provides a method for putting fpga into |
887 | * a desired state upon unregister, do it. |
888 | */ |
889 | fpga_mgr_fpga_remove(mgr); |
890 | |
891 | device_unregister(dev: &mgr->dev); |
892 | } |
893 | EXPORT_SYMBOL_GPL(fpga_mgr_unregister); |
894 | |
895 | static void devm_fpga_mgr_unregister(struct device *dev, void *res) |
896 | { |
897 | struct fpga_mgr_devres *dr = res; |
898 | |
899 | fpga_mgr_unregister(dr->mgr); |
900 | } |
901 | |
902 | /** |
903 | * devm_fpga_mgr_register_full - resource managed variant of fpga_mgr_register() |
904 | * @parent: fpga manager device from pdev |
905 | * @info: parameters for fpga manager |
906 | * |
907 | * Return: fpga manager pointer on success, negative error code otherwise. |
908 | * |
909 | * This is the devres variant of fpga_mgr_register_full() for which the unregister |
910 | * function will be called automatically when the managing device is detached. |
911 | */ |
912 | struct fpga_manager * |
913 | devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info) |
914 | { |
915 | struct fpga_mgr_devres *dr; |
916 | struct fpga_manager *mgr; |
917 | |
918 | dr = devres_alloc(devm_fpga_mgr_unregister, sizeof(*dr), GFP_KERNEL); |
919 | if (!dr) |
920 | return ERR_PTR(error: -ENOMEM); |
921 | |
922 | mgr = fpga_mgr_register_full(parent, info); |
923 | if (IS_ERR(ptr: mgr)) { |
924 | devres_free(res: dr); |
925 | return mgr; |
926 | } |
927 | |
928 | dr->mgr = mgr; |
929 | devres_add(dev: parent, res: dr); |
930 | |
931 | return mgr; |
932 | } |
933 | EXPORT_SYMBOL_GPL(devm_fpga_mgr_register_full); |
934 | |
935 | /** |
936 | * devm_fpga_mgr_register - resource managed variant of fpga_mgr_register() |
937 | * @parent: fpga manager device from pdev |
938 | * @name: fpga manager name |
939 | * @mops: pointer to structure of fpga manager ops |
940 | * @priv: fpga manager private data |
941 | * |
942 | * Return: fpga manager pointer on success, negative error code otherwise. |
943 | * |
944 | * This is the devres variant of fpga_mgr_register() for which the |
945 | * unregister function will be called automatically when the managing |
946 | * device is detached. |
947 | */ |
948 | struct fpga_manager * |
949 | devm_fpga_mgr_register(struct device *parent, const char *name, |
950 | const struct fpga_manager_ops *mops, void *priv) |
951 | { |
952 | struct fpga_manager_info info = { 0 }; |
953 | |
954 | info.name = name; |
955 | info.mops = mops; |
956 | info.priv = priv; |
957 | |
958 | return devm_fpga_mgr_register_full(parent, &info); |
959 | } |
960 | EXPORT_SYMBOL_GPL(devm_fpga_mgr_register); |
961 | |
962 | static void fpga_mgr_dev_release(struct device *dev) |
963 | { |
964 | struct fpga_manager *mgr = to_fpga_manager(dev); |
965 | |
966 | ida_free(&fpga_mgr_ida, id: mgr->dev.id); |
967 | kfree(objp: mgr); |
968 | } |
969 | |
970 | static const struct class fpga_mgr_class = { |
971 | .name = "fpga_manager" , |
972 | .dev_groups = fpga_mgr_groups, |
973 | .dev_release = fpga_mgr_dev_release, |
974 | }; |
975 | |
976 | static int __init fpga_mgr_class_init(void) |
977 | { |
978 | pr_info("FPGA manager framework\n" ); |
979 | |
980 | return class_register(class: &fpga_mgr_class); |
981 | } |
982 | |
983 | static void __exit fpga_mgr_class_exit(void) |
984 | { |
985 | class_unregister(class: &fpga_mgr_class); |
986 | ida_destroy(ida: &fpga_mgr_ida); |
987 | } |
988 | |
989 | MODULE_AUTHOR("Alan Tull <atull@kernel.org>" ); |
990 | MODULE_DESCRIPTION("FPGA manager framework" ); |
991 | MODULE_LICENSE("GPL v2" ); |
992 | |
993 | subsys_initcall(fpga_mgr_class_init); |
994 | module_exit(fpga_mgr_class_exit); |
995 | |