diff options
author | Alistair Popple <alistair@popple.id.au> | 2015-07-03 03:39:12 -0400 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2015-07-06 06:24:36 -0400 |
commit | a8956a7b7232da5f4ce4a305c72a54cc5e4a8307 (patch) | |
tree | fd460edb28a11ac7eb63170a3571163701e88d9d /arch/powerpc | |
parent | aaf6fd5c75eb4aa734ec2062deab371633c3655f (diff) |
powerpc/powernv: Fix opal-elog interrupt handler
The conversion of opal events to a proper irqchip means that handlers
are called until the relevant opal event has been cleared by
processing it. Events that queue work should therefore use a threaded
handler to mask the event until processing is complete.
Signed-off-by: Alistair Popple <alistair@popple.id.au>
Tested-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/platforms/powernv/opal-elog.c | 16 |
1 files changed, 5 insertions, 11 deletions
diff --git a/arch/powerpc/platforms/powernv/opal-elog.c b/arch/powerpc/platforms/powernv/opal-elog.c index 4949ef0d9400..37f959bf392e 100644 --- a/arch/powerpc/platforms/powernv/opal-elog.c +++ b/arch/powerpc/platforms/powernv/opal-elog.c | |||
@@ -237,7 +237,7 @@ static struct elog_obj *create_elog_obj(uint64_t id, size_t size, uint64_t type) | |||
237 | return elog; | 237 | return elog; |
238 | } | 238 | } |
239 | 239 | ||
240 | static void elog_work_fn(struct work_struct *work) | 240 | static irqreturn_t elog_event(int irq, void *data) |
241 | { | 241 | { |
242 | __be64 size; | 242 | __be64 size; |
243 | __be64 id; | 243 | __be64 id; |
@@ -251,7 +251,7 @@ static void elog_work_fn(struct work_struct *work) | |||
251 | rc = opal_get_elog_size(&id, &size, &type); | 251 | rc = opal_get_elog_size(&id, &size, &type); |
252 | if (rc != OPAL_SUCCESS) { | 252 | if (rc != OPAL_SUCCESS) { |
253 | pr_err("ELOG: OPAL log info read failed\n"); | 253 | pr_err("ELOG: OPAL log info read failed\n"); |
254 | return; | 254 | return IRQ_HANDLED; |
255 | } | 255 | } |
256 | 256 | ||
257 | elog_size = be64_to_cpu(size); | 257 | elog_size = be64_to_cpu(size); |
@@ -270,16 +270,10 @@ static void elog_work_fn(struct work_struct *work) | |||
270 | * entries. | 270 | * entries. |
271 | */ | 271 | */ |
272 | if (kset_find_obj(elog_kset, name)) | 272 | if (kset_find_obj(elog_kset, name)) |
273 | return; | 273 | return IRQ_HANDLED; |
274 | 274 | ||
275 | create_elog_obj(log_id, elog_size, elog_type); | 275 | create_elog_obj(log_id, elog_size, elog_type); |
276 | } | ||
277 | |||
278 | static DECLARE_WORK(elog_work, elog_work_fn); | ||
279 | 276 | ||
280 | static irqreturn_t elog_event(int irq, void *data) | ||
281 | { | ||
282 | schedule_work(&elog_work); | ||
283 | return IRQ_HANDLED; | 277 | return IRQ_HANDLED; |
284 | } | 278 | } |
285 | 279 | ||
@@ -304,8 +298,8 @@ int __init opal_elog_init(void) | |||
304 | return irq; | 298 | return irq; |
305 | } | 299 | } |
306 | 300 | ||
307 | rc = request_irq(irq, elog_event, | 301 | rc = request_threaded_irq(irq, NULL, elog_event, |
308 | IRQ_TYPE_LEVEL_HIGH, "opal-elog", NULL); | 302 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "opal-elog", NULL); |
309 | if (rc) { | 303 | if (rc) { |
310 | pr_err("%s: Can't request OPAL event irq (%d)\n", | 304 | pr_err("%s: Can't request OPAL event irq (%d)\n", |
311 | __func__, rc); | 305 | __func__, rc); |