diff options
author | Baolin Wang <baolin.wang@linaro.org> | 2018-06-22 04:09:00 -0400 |
---|---|---|
committer | Bjorn Andersson <bjorn.andersson@linaro.org> | 2018-06-26 16:46:23 -0400 |
commit | c102780acdbc22e5f664cfaf760eaccffbd6c385 (patch) | |
tree | 50c616d48090d5fd83c23efbfbb1b7e3c4af1a51 | |
parent | 4f1acd758b08d93306d13010c74d38dd8d9f5768 (diff) |
hwspinlock: Add devm_xxx() APIs to register/unregister one hwlock controller
This patch introduces devm_hwspin_lock_register() and devm_hwspin_lock_unregister()
interfaces to help to register or unregister one hardware spinlock controller, that
will help to simplify the cleanup code for hwspinlock drivers.
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
-rw-r--r-- | drivers/hwspinlock/hwspinlock_core.c | 82 | ||||
-rw-r--r-- | include/linux/hwspinlock.h | 6 |
2 files changed, 88 insertions, 0 deletions
diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c index d542b6fbf0f2..ba27465c9d9b 100644 --- a/drivers/hwspinlock/hwspinlock_core.c +++ b/drivers/hwspinlock/hwspinlock_core.c | |||
@@ -529,6 +529,88 @@ int hwspin_lock_unregister(struct hwspinlock_device *bank) | |||
529 | } | 529 | } |
530 | EXPORT_SYMBOL_GPL(hwspin_lock_unregister); | 530 | EXPORT_SYMBOL_GPL(hwspin_lock_unregister); |
531 | 531 | ||
532 | static void devm_hwspin_lock_unreg(struct device *dev, void *res) | ||
533 | { | ||
534 | hwspin_lock_unregister(*(struct hwspinlock_device **)res); | ||
535 | } | ||
536 | |||
537 | static int devm_hwspin_lock_device_match(struct device *dev, void *res, | ||
538 | void *data) | ||
539 | { | ||
540 | struct hwspinlock_device **bank = res; | ||
541 | |||
542 | if (WARN_ON(!bank || !*bank)) | ||
543 | return 0; | ||
544 | |||
545 | return *bank == data; | ||
546 | } | ||
547 | |||
548 | /** | ||
549 | * devm_hwspin_lock_unregister() - unregister an hw spinlock device for | ||
550 | * a managed device | ||
551 | * @dev: the backing device | ||
552 | * @bank: the hwspinlock device, which usually provides numerous hw locks | ||
553 | * | ||
554 | * This function should be called from the underlying platform-specific | ||
555 | * implementation, to unregister an existing (and unused) hwspinlock. | ||
556 | * | ||
557 | * Should be called from a process context (might sleep) | ||
558 | * | ||
559 | * Returns 0 on success, or an appropriate error code on failure | ||
560 | */ | ||
561 | int devm_hwspin_lock_unregister(struct device *dev, | ||
562 | struct hwspinlock_device *bank) | ||
563 | { | ||
564 | int ret; | ||
565 | |||
566 | ret = devres_release(dev, devm_hwspin_lock_unreg, | ||
567 | devm_hwspin_lock_device_match, bank); | ||
568 | WARN_ON(ret); | ||
569 | |||
570 | return ret; | ||
571 | } | ||
572 | EXPORT_SYMBOL_GPL(devm_hwspin_lock_unregister); | ||
573 | |||
574 | /** | ||
575 | * devm_hwspin_lock_register() - register a new hw spinlock device for | ||
576 | * a managed device | ||
577 | * @dev: the backing device | ||
578 | * @bank: the hwspinlock device, which usually provides numerous hw locks | ||
579 | * @ops: hwspinlock handlers for this device | ||
580 | * @base_id: id of the first hardware spinlock in this bank | ||
581 | * @num_locks: number of hwspinlocks provided by this device | ||
582 | * | ||
583 | * This function should be called from the underlying platform-specific | ||
584 | * implementation, to register a new hwspinlock device instance. | ||
585 | * | ||
586 | * Should be called from a process context (might sleep) | ||
587 | * | ||
588 | * Returns 0 on success, or an appropriate error code on failure | ||
589 | */ | ||
590 | int devm_hwspin_lock_register(struct device *dev, | ||
591 | struct hwspinlock_device *bank, | ||
592 | const struct hwspinlock_ops *ops, | ||
593 | int base_id, int num_locks) | ||
594 | { | ||
595 | struct hwspinlock_device **ptr; | ||
596 | int ret; | ||
597 | |||
598 | ptr = devres_alloc(devm_hwspin_lock_unreg, sizeof(*ptr), GFP_KERNEL); | ||
599 | if (!ptr) | ||
600 | return -ENOMEM; | ||
601 | |||
602 | ret = hwspin_lock_register(bank, dev, ops, base_id, num_locks); | ||
603 | if (!ret) { | ||
604 | *ptr = bank; | ||
605 | devres_add(dev, ptr); | ||
606 | } else { | ||
607 | devres_free(ptr); | ||
608 | } | ||
609 | |||
610 | return ret; | ||
611 | } | ||
612 | EXPORT_SYMBOL_GPL(devm_hwspin_lock_register); | ||
613 | |||
532 | /** | 614 | /** |
533 | * __hwspin_lock_request() - tag an hwspinlock as used and power it up | 615 | * __hwspin_lock_request() - tag an hwspinlock as used and power it up |
534 | * | 616 | * |
diff --git a/include/linux/hwspinlock.h b/include/linux/hwspinlock.h index dfd05938a3cb..94064cce6962 100644 --- a/include/linux/hwspinlock.h +++ b/include/linux/hwspinlock.h | |||
@@ -71,6 +71,12 @@ int devm_hwspin_lock_free(struct device *dev, struct hwspinlock *hwlock); | |||
71 | struct hwspinlock *devm_hwspin_lock_request(struct device *dev); | 71 | struct hwspinlock *devm_hwspin_lock_request(struct device *dev); |
72 | struct hwspinlock *devm_hwspin_lock_request_specific(struct device *dev, | 72 | struct hwspinlock *devm_hwspin_lock_request_specific(struct device *dev, |
73 | unsigned int id); | 73 | unsigned int id); |
74 | int devm_hwspin_lock_unregister(struct device *dev, | ||
75 | struct hwspinlock_device *bank); | ||
76 | int devm_hwspin_lock_register(struct device *dev, | ||
77 | struct hwspinlock_device *bank, | ||
78 | const struct hwspinlock_ops *ops, | ||
79 | int base_id, int num_locks); | ||
74 | 80 | ||
75 | #else /* !CONFIG_HWSPINLOCK */ | 81 | #else /* !CONFIG_HWSPINLOCK */ |
76 | 82 | ||