diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/irq_work.c | 31 |
1 files changed, 10 insertions, 21 deletions
diff --git a/kernel/irq_work.c b/kernel/irq_work.c index 64eddd59ed83..c9d7478e4889 100644 --- a/kernel/irq_work.c +++ b/kernel/irq_work.c | |||
@@ -63,12 +63,20 @@ void __weak arch_irq_work_raise(void) | |||
63 | } | 63 | } |
64 | 64 | ||
65 | /* | 65 | /* |
66 | * Queue the entry and raise the IPI if needed. | 66 | * Enqueue the irq_work @entry unless it's already pending |
67 | * somewhere. | ||
68 | * | ||
69 | * Can be re-enqueued while the callback is still in progress. | ||
67 | */ | 70 | */ |
68 | static void __irq_work_queue(struct irq_work *work) | 71 | void irq_work_queue(struct irq_work *work) |
69 | { | 72 | { |
70 | bool empty; | 73 | bool empty; |
71 | 74 | ||
75 | /* Only queue if not already pending */ | ||
76 | if (!irq_work_claim(work)) | ||
77 | return; | ||
78 | |||
79 | /* Queue the entry and raise the IPI if needed. */ | ||
72 | preempt_disable(); | 80 | preempt_disable(); |
73 | 81 | ||
74 | empty = llist_add(&work->llnode, &__get_cpu_var(irq_work_list)); | 82 | empty = llist_add(&work->llnode, &__get_cpu_var(irq_work_list)); |
@@ -78,25 +86,6 @@ static void __irq_work_queue(struct irq_work *work) | |||
78 | 86 | ||
79 | preempt_enable(); | 87 | preempt_enable(); |
80 | } | 88 | } |
81 | |||
82 | /* | ||
83 | * Enqueue the irq_work @entry, returns true on success, failure when the | ||
84 | * @entry was already enqueued by someone else. | ||
85 | * | ||
86 | * Can be re-enqueued while the callback is still in progress. | ||
87 | */ | ||
88 | bool irq_work_queue(struct irq_work *work) | ||
89 | { | ||
90 | if (!irq_work_claim(work)) { | ||
91 | /* | ||
92 | * Already enqueued, can't do! | ||
93 | */ | ||
94 | return false; | ||
95 | } | ||
96 | |||
97 | __irq_work_queue(work); | ||
98 | return true; | ||
99 | } | ||
100 | EXPORT_SYMBOL_GPL(irq_work_queue); | 89 | EXPORT_SYMBOL_GPL(irq_work_queue); |
101 | 90 | ||
102 | /* | 91 | /* |