diff options
Diffstat (limited to 'drivers/fpga/fpga-mgr.c')
-rw-r--r-- | drivers/fpga/fpga-mgr.c | 123 |
1 files changed, 94 insertions, 29 deletions
diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index 188ffefa3cc3..9939d2cbc9a6 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * FPGA Manager Core | 2 | * FPGA Manager Core |
3 | * | 3 | * |
4 | * Copyright (C) 2013-2015 Altera Corporation | 4 | * Copyright (C) 2013-2015 Altera Corporation |
5 | * Copyright (C) 2017 Intel Corporation | ||
5 | * | 6 | * |
6 | * With code from the mailing list: | 7 | * With code from the mailing list: |
7 | * Copyright (C) 2013 Xilinx, Inc. | 8 | * Copyright (C) 2013 Xilinx, Inc. |
@@ -31,6 +32,40 @@ | |||
31 | static DEFINE_IDA(fpga_mgr_ida); | 32 | static DEFINE_IDA(fpga_mgr_ida); |
32 | static struct class *fpga_mgr_class; | 33 | static struct class *fpga_mgr_class; |
33 | 34 | ||
35 | struct fpga_image_info *fpga_image_info_alloc(struct device *dev) | ||
36 | { | ||
37 | struct fpga_image_info *info; | ||
38 | |||
39 | get_device(dev); | ||
40 | |||
41 | info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); | ||
42 | if (!info) { | ||
43 | put_device(dev); | ||
44 | return NULL; | ||
45 | } | ||
46 | |||
47 | info->dev = dev; | ||
48 | |||
49 | return info; | ||
50 | } | ||
51 | EXPORT_SYMBOL_GPL(fpga_image_info_alloc); | ||
52 | |||
53 | void fpga_image_info_free(struct fpga_image_info *info) | ||
54 | { | ||
55 | struct device *dev; | ||
56 | |||
57 | if (!info) | ||
58 | return; | ||
59 | |||
60 | dev = info->dev; | ||
61 | if (info->firmware_name) | ||
62 | devm_kfree(dev, info->firmware_name); | ||
63 | |||
64 | devm_kfree(dev, info); | ||
65 | put_device(dev); | ||
66 | } | ||
67 | EXPORT_SYMBOL_GPL(fpga_image_info_free); | ||
68 | |||
34 | /* | 69 | /* |
35 | * Call the low level driver's write_init function. This will do the | 70 | * Call the low level driver's write_init function. This will do the |
36 | * device-specific things to get the FPGA into the state where it is ready to | 71 | * device-specific things to get the FPGA into the state where it is ready to |
@@ -137,8 +172,9 @@ static int fpga_mgr_write_complete(struct fpga_manager *mgr, | |||
137 | * | 172 | * |
138 | * Return: 0 on success, negative error code otherwise. | 173 | * Return: 0 on success, negative error code otherwise. |
139 | */ | 174 | */ |
140 | int fpga_mgr_buf_load_sg(struct fpga_manager *mgr, struct fpga_image_info *info, | 175 | static int fpga_mgr_buf_load_sg(struct fpga_manager *mgr, |
141 | struct sg_table *sgt) | 176 | struct fpga_image_info *info, |
177 | struct sg_table *sgt) | ||
142 | { | 178 | { |
143 | int ret; | 179 | int ret; |
144 | 180 | ||
@@ -170,7 +206,6 @@ int fpga_mgr_buf_load_sg(struct fpga_manager *mgr, struct fpga_image_info *info, | |||
170 | 206 | ||
171 | return fpga_mgr_write_complete(mgr, info); | 207 | return fpga_mgr_write_complete(mgr, info); |
172 | } | 208 | } |
173 | EXPORT_SYMBOL_GPL(fpga_mgr_buf_load_sg); | ||
174 | 209 | ||
175 | static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr, | 210 | static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr, |
176 | struct fpga_image_info *info, | 211 | struct fpga_image_info *info, |
@@ -210,8 +245,9 @@ static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr, | |||
210 | * | 245 | * |
211 | * Return: 0 on success, negative error code otherwise. | 246 | * Return: 0 on success, negative error code otherwise. |
212 | */ | 247 | */ |
213 | int fpga_mgr_buf_load(struct fpga_manager *mgr, struct fpga_image_info *info, | 248 | static int fpga_mgr_buf_load(struct fpga_manager *mgr, |
214 | const char *buf, size_t count) | 249 | struct fpga_image_info *info, |
250 | const char *buf, size_t count) | ||
215 | { | 251 | { |
216 | struct page **pages; | 252 | struct page **pages; |
217 | struct sg_table sgt; | 253 | struct sg_table sgt; |
@@ -266,7 +302,6 @@ int fpga_mgr_buf_load(struct fpga_manager *mgr, struct fpga_image_info *info, | |||
266 | 302 | ||
267 | return rc; | 303 | return rc; |
268 | } | 304 | } |
269 | EXPORT_SYMBOL_GPL(fpga_mgr_buf_load); | ||
270 | 305 | ||
271 | /** | 306 | /** |
272 | * fpga_mgr_firmware_load - request firmware and load to fpga | 307 | * fpga_mgr_firmware_load - request firmware and load to fpga |
@@ -282,9 +317,9 @@ EXPORT_SYMBOL_GPL(fpga_mgr_buf_load); | |||
282 | * | 317 | * |
283 | * Return: 0 on success, negative error code otherwise. | 318 | * Return: 0 on success, negative error code otherwise. |
284 | */ | 319 | */ |
285 | int fpga_mgr_firmware_load(struct fpga_manager *mgr, | 320 | static int fpga_mgr_firmware_load(struct fpga_manager *mgr, |
286 | struct fpga_image_info *info, | 321 | struct fpga_image_info *info, |
287 | const char *image_name) | 322 | const char *image_name) |
288 | { | 323 | { |
289 | struct device *dev = &mgr->dev; | 324 | struct device *dev = &mgr->dev; |
290 | const struct firmware *fw; | 325 | const struct firmware *fw; |
@@ -307,7 +342,18 @@ int fpga_mgr_firmware_load(struct fpga_manager *mgr, | |||
307 | 342 | ||
308 | return ret; | 343 | return ret; |
309 | } | 344 | } |
310 | EXPORT_SYMBOL_GPL(fpga_mgr_firmware_load); | 345 | |
346 | int fpga_mgr_load(struct fpga_manager *mgr, struct fpga_image_info *info) | ||
347 | { | ||
348 | if (info->sgt) | ||
349 | return fpga_mgr_buf_load_sg(mgr, info, info->sgt); | ||
350 | if (info->buf && info->count) | ||
351 | return fpga_mgr_buf_load(mgr, info, info->buf, info->count); | ||
352 | if (info->firmware_name) | ||
353 | return fpga_mgr_firmware_load(mgr, info, info->firmware_name); | ||
354 | return -EINVAL; | ||
355 | } | ||
356 | EXPORT_SYMBOL_GPL(fpga_mgr_load); | ||
311 | 357 | ||
312 | static const char * const state_str[] = { | 358 | static const char * const state_str[] = { |
313 | [FPGA_MGR_STATE_UNKNOWN] = "unknown", | 359 | [FPGA_MGR_STATE_UNKNOWN] = "unknown", |
@@ -364,28 +410,17 @@ ATTRIBUTE_GROUPS(fpga_mgr); | |||
364 | static struct fpga_manager *__fpga_mgr_get(struct device *dev) | 410 | static struct fpga_manager *__fpga_mgr_get(struct device *dev) |
365 | { | 411 | { |
366 | struct fpga_manager *mgr; | 412 | struct fpga_manager *mgr; |
367 | int ret = -ENODEV; | ||
368 | 413 | ||
369 | mgr = to_fpga_manager(dev); | 414 | mgr = to_fpga_manager(dev); |
370 | if (!mgr) | ||
371 | goto err_dev; | ||
372 | |||
373 | /* Get exclusive use of fpga manager */ | ||
374 | if (!mutex_trylock(&mgr->ref_mutex)) { | ||
375 | ret = -EBUSY; | ||
376 | goto err_dev; | ||
377 | } | ||
378 | 415 | ||
379 | if (!try_module_get(dev->parent->driver->owner)) | 416 | if (!try_module_get(dev->parent->driver->owner)) |
380 | goto err_ll_mod; | 417 | goto err_dev; |
381 | 418 | ||
382 | return mgr; | 419 | return mgr; |
383 | 420 | ||
384 | err_ll_mod: | ||
385 | mutex_unlock(&mgr->ref_mutex); | ||
386 | err_dev: | 421 | err_dev: |
387 | put_device(dev); | 422 | put_device(dev); |
388 | return ERR_PTR(ret); | 423 | return ERR_PTR(-ENODEV); |
389 | } | 424 | } |
390 | 425 | ||
391 | static int fpga_mgr_dev_match(struct device *dev, const void *data) | 426 | static int fpga_mgr_dev_match(struct device *dev, const void *data) |
@@ -394,10 +429,10 @@ static int fpga_mgr_dev_match(struct device *dev, const void *data) | |||
394 | } | 429 | } |
395 | 430 | ||
396 | /** | 431 | /** |
397 | * fpga_mgr_get - get an exclusive reference to a fpga mgr | 432 | * fpga_mgr_get - get a reference to a fpga mgr |
398 | * @dev: parent device that fpga mgr was registered with | 433 | * @dev: parent device that fpga mgr was registered with |
399 | * | 434 | * |
400 | * Given a device, get an exclusive reference to a fpga mgr. | 435 | * Given a device, get a reference to a fpga mgr. |
401 | * | 436 | * |
402 | * Return: fpga manager struct or IS_ERR() condition containing error code. | 437 | * Return: fpga manager struct or IS_ERR() condition containing error code. |
403 | */ | 438 | */ |
@@ -418,10 +453,10 @@ static int fpga_mgr_of_node_match(struct device *dev, const void *data) | |||
418 | } | 453 | } |
419 | 454 | ||
420 | /** | 455 | /** |
421 | * of_fpga_mgr_get - get an exclusive reference to a fpga mgr | 456 | * of_fpga_mgr_get - get a reference to a fpga mgr |
422 | * @node: device node | 457 | * @node: device node |
423 | * | 458 | * |
424 | * Given a device node, get an exclusive reference to a fpga mgr. | 459 | * Given a device node, get a reference to a fpga mgr. |
425 | * | 460 | * |
426 | * Return: fpga manager struct or IS_ERR() condition containing error code. | 461 | * Return: fpga manager struct or IS_ERR() condition containing error code. |
427 | */ | 462 | */ |
@@ -445,12 +480,41 @@ EXPORT_SYMBOL_GPL(of_fpga_mgr_get); | |||
445 | void fpga_mgr_put(struct fpga_manager *mgr) | 480 | void fpga_mgr_put(struct fpga_manager *mgr) |
446 | { | 481 | { |
447 | module_put(mgr->dev.parent->driver->owner); | 482 | module_put(mgr->dev.parent->driver->owner); |
448 | mutex_unlock(&mgr->ref_mutex); | ||
449 | put_device(&mgr->dev); | 483 | put_device(&mgr->dev); |
450 | } | 484 | } |
451 | EXPORT_SYMBOL_GPL(fpga_mgr_put); | 485 | EXPORT_SYMBOL_GPL(fpga_mgr_put); |
452 | 486 | ||
453 | /** | 487 | /** |
488 | * fpga_mgr_lock - Lock FPGA manager for exclusive use | ||
489 | * @mgr: fpga manager | ||
490 | * | ||
491 | * Given a pointer to FPGA Manager (from fpga_mgr_get() or | ||
492 | * of_fpga_mgr_put()) attempt to get the mutex. | ||
493 | * | ||
494 | * Return: 0 for success or -EBUSY | ||
495 | */ | ||
496 | int fpga_mgr_lock(struct fpga_manager *mgr) | ||
497 | { | ||
498 | if (!mutex_trylock(&mgr->ref_mutex)) { | ||
499 | dev_err(&mgr->dev, "FPGA manager is in use.\n"); | ||
500 | return -EBUSY; | ||
501 | } | ||
502 | |||
503 | return 0; | ||
504 | } | ||
505 | EXPORT_SYMBOL_GPL(fpga_mgr_lock); | ||
506 | |||
507 | /** | ||
508 | * fpga_mgr_unlock - Unlock FPGA manager | ||
509 | * @mgr: fpga manager | ||
510 | */ | ||
511 | void fpga_mgr_unlock(struct fpga_manager *mgr) | ||
512 | { | ||
513 | mutex_unlock(&mgr->ref_mutex); | ||
514 | } | ||
515 | EXPORT_SYMBOL_GPL(fpga_mgr_unlock); | ||
516 | |||
517 | /** | ||
454 | * fpga_mgr_register - register a low level fpga manager driver | 518 | * fpga_mgr_register - register a low level fpga manager driver |
455 | * @dev: fpga manager device from pdev | 519 | * @dev: fpga manager device from pdev |
456 | * @name: fpga manager name | 520 | * @name: fpga manager name |
@@ -503,6 +567,7 @@ int fpga_mgr_register(struct device *dev, const char *name, | |||
503 | 567 | ||
504 | device_initialize(&mgr->dev); | 568 | device_initialize(&mgr->dev); |
505 | mgr->dev.class = fpga_mgr_class; | 569 | mgr->dev.class = fpga_mgr_class; |
570 | mgr->dev.groups = mops->groups; | ||
506 | mgr->dev.parent = dev; | 571 | mgr->dev.parent = dev; |
507 | mgr->dev.of_node = dev->of_node; | 572 | mgr->dev.of_node = dev->of_node; |
508 | mgr->dev.id = id; | 573 | mgr->dev.id = id; |
@@ -578,7 +643,7 @@ static void __exit fpga_mgr_class_exit(void) | |||
578 | ida_destroy(&fpga_mgr_ida); | 643 | ida_destroy(&fpga_mgr_ida); |
579 | } | 644 | } |
580 | 645 | ||
581 | MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>"); | 646 | MODULE_AUTHOR("Alan Tull <atull@kernel.org>"); |
582 | MODULE_DESCRIPTION("FPGA manager framework"); | 647 | MODULE_DESCRIPTION("FPGA manager framework"); |
583 | MODULE_LICENSE("GPL v2"); | 648 | MODULE_LICENSE("GPL v2"); |
584 | 649 | ||