diff options
author | Hemant Kumar <hemantk@codeaurora.org> | 2016-01-27 20:45:57 -0800 |
---|---|---|
committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 11:03:00 -0700 |
commit | c03ffc42548044e4c28262c03a94a9234eedc153 (patch) | |
tree | 7bff9625cf4583e6931b19f0485cbf7d9d8bb532 | |
parent | 47bb2a3600e473ab700af0d88f44d596d6877724 (diff) |
Revert "kref: Remove kref_put_spinlock_irqsave()"
This reverts commit 3a66d7dca186ebdef9b0bf55e216778fa598062c.
Diag function driver calls kref_put_spinlock_irqsave in
diag_write_complete API. Hence revert the change.
-rw-r--r-- | include/linux/kref.h | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/include/linux/kref.h b/include/linux/kref.h index e15828fd71f1..484604d184be 100644 --- a/include/linux/kref.h +++ b/include/linux/kref.h @@ -19,6 +19,7 @@ #include <linux/atomic.h> #include <linux/kernel.h> #include <linux/mutex.h> +#include <linux/spinlock.h> struct kref { atomic_t refcount; @@ -98,6 +99,38 @@ static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref) return kref_sub(kref, 1, release); } +/** + * kref_put_spinlock_irqsave - decrement refcount for object. + * @kref: object. + * @release: pointer to the function that will clean up the object when the + * last reference to the object is released. + * This pointer is required, and it is not acceptable to pass kfree + * in as this function. + * @lock: lock to take in release case + * + * Behaves identical to kref_put with one exception. If the reference count + * drops to zero, the lock will be taken atomically wrt dropping the reference + * count. The release function has to call spin_unlock() without _irqrestore. + */ +static inline int kref_put_spinlock_irqsave(struct kref *kref, + void (*release)(struct kref *kref), + spinlock_t *lock) +{ + unsigned long flags; + + WARN_ON(release == NULL); + if (atomic_add_unless(&kref->refcount, -1, 1)) + return 0; + spin_lock_irqsave(lock, flags); + if (atomic_dec_and_test(&kref->refcount)) { + release(kref); + local_irq_restore(flags); + return 1; + } + spin_unlock_irqrestore(lock, flags); + return 0; +} + static inline int kref_put_mutex(struct kref *kref, void (*release)(struct kref *kref), struct mutex *lock) |