Message ID | 1450472361-426-5-git-send-email-mathieu.poirier@linaro.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Fri, Dec 18, 2015 at 01:59:00PM -0700, Mathieu Poirier wrote: > @@ -415,9 +418,13 @@ struct list_head *coresight_build_path(struct coresight_device *csdev) > */ > void coresight_release_path(struct list_head *path) > { > + struct coresight_device *csdev; > struct coresight_node *nd, *next; > > list_for_each_entry_safe(nd, next, path, link) { > + csdev = nd->csdev; > + > + pm_runtime_put_sync(csdev->dev.parent); > list_del(&nd->link); > kfree(nd); > } This leads to the following splat: BUG: sleeping function called from invalid context at /home/rabin/dev/linux/drivers/base/power/runtime.c:892 in_atomic(): 1, irqs_disabled(): 128, pid: 763, name: perf 2 locks held by perf/763: #0: (&mm->mmap_sem){++++++}, at: [<c012e42c>] vm_munmap+0x2c/0x50 #1: (&event->mmap_mutex){+.+.+.}, at: [<c008248c>] atomic_dec_and_mutex_lock+0x58/0x98 irq event stamp: 63152 hardirqs last enabled at (63151): [<c04f7edc>] _raw_spin_unlock_irqrestore+0x30/0x5c hardirqs last disabled at (63152): [<c04f88e8>] __irq_svc+0x48/0x78 softirqs last enabled at (61242): [<c003a914>] __do_softirq+0x408/0x4fc softirqs last disabled at (61223): [<c003ad50>] irq_exit+0xcc/0x130 CPU: 1 PID: 763 Comm: perf Not tainted 4.4.0-rc5-00224-ge461459-dirty #152 Hardware name: Generic OMAP4 (Flattened Device Tree) [<c00184dc>] (unwind_backtrace) from [<c0014c74>] (show_stack+0x10/0x14) [<c0014c74>] (show_stack) from [<c025c834>] (dump_stack+0x90/0xb8) [<c025c834>] (dump_stack) from [<c02f026c>] (__pm_runtime_idle+0xa4/0xa8) [<c02f026c>] (__pm_runtime_idle) from [<c03e1a08>] (coresight_release_path+0x38/0x7c) [<c03e1a08>] (coresight_release_path) from [<c03e210c>] (free_event_data+0x84/0x9c) [<c03e210c>] (free_event_data) from [<c00f8be8>] (rb_irq_work+0x4c/0xcc) [<c00f8be8>] (rb_irq_work) from [<c00e8860>] (irq_work_run_list+0x7c/0xb4) [<c00e8860>] (irq_work_run_list) from [<c00e88b8>] (irq_work_run+0x20/0x34) [<c00e88b8>] (irq_work_run) from [<c0016dcc>] (handle_IPI+0x1cc/0x334) [<c0016dcc>] (handle_IPI) from [<c0009538>] (gic_handle_irq+0x84/0x88) [<c0009538>] (gic_handle_irq) from [<c04f88f8>] (__irq_svc+0x58/0x78) Exception stack(0xed865e98 to 0xed865ee0) 5e80: 00000001 00000110 5ea0: 00000000 ee2f1080 20000113 c0784808 edbe4e1c b6ae5000 edb882f0 ed9b1e04 5ec0: edb88298 c075648c 00000002 ed865ee8 c008724c c04f7ee0 20000113 ffffffff [<c04f88f8>] (__irq_svc) from [<c04f7ee0>] (_raw_spin_unlock_irqrestore+0x34/0x5c) [<c04f7ee0>] (_raw_spin_unlock_irqrestore) from [<c00e8978>] (irq_work_queue+0xac/0xb4) [<c00e8978>] (irq_work_queue) from [<c00f5020>] (perf_mmap_close+0x370/0x3c8) [<c00f5020>] (perf_mmap_close) from [<c012c560>] (remove_vma+0x40/0x6c) [<c012c560>] (remove_vma) from [<c012e2b4>] (do_munmap+0x210/0x35c) [<c012e2b4>] (do_munmap) from [<c012e43c>] (vm_munmap+0x3c/0x50) [<c012e43c>] (vm_munmap) from [<c0010320>] (ret_fast_syscall+0x0/0x1c) It should presumably be using pm_runtime_put() instead.
On 19 December 2015 at 10:13, Rabin Vincent <rabin@rab.in> wrote: > On Fri, Dec 18, 2015 at 01:59:00PM -0700, Mathieu Poirier wrote: >> @@ -415,9 +418,13 @@ struct list_head *coresight_build_path(struct coresight_device *csdev) >> */ >> void coresight_release_path(struct list_head *path) >> { >> + struct coresight_device *csdev; >> struct coresight_node *nd, *next; >> >> list_for_each_entry_safe(nd, next, path, link) { >> + csdev = nd->csdev; >> + >> + pm_runtime_put_sync(csdev->dev.parent); >> list_del(&nd->link); >> kfree(nd); >> } > > This leads to the following splat: > > BUG: sleeping function called from invalid context at /home/rabin/dev/linux/drivers/base/power/runtime.c:892 > in_atomic(): 1, irqs_disabled(): 128, pid: 763, name: perf > 2 locks held by perf/763: > #0: (&mm->mmap_sem){++++++}, at: [<c012e42c>] vm_munmap+0x2c/0x50 > #1: (&event->mmap_mutex){+.+.+.}, at: [<c008248c>] atomic_dec_and_mutex_lock+0x58/0x98 > irq event stamp: 63152 > hardirqs last enabled at (63151): [<c04f7edc>] _raw_spin_unlock_irqrestore+0x30/0x5c > hardirqs last disabled at (63152): [<c04f88e8>] __irq_svc+0x48/0x78 > softirqs last enabled at (61242): [<c003a914>] __do_softirq+0x408/0x4fc > softirqs last disabled at (61223): [<c003ad50>] irq_exit+0xcc/0x130 > CPU: 1 PID: 763 Comm: perf Not tainted 4.4.0-rc5-00224-ge461459-dirty #152 > Hardware name: Generic OMAP4 (Flattened Device Tree) > [<c00184dc>] (unwind_backtrace) from [<c0014c74>] (show_stack+0x10/0x14) > [<c0014c74>] (show_stack) from [<c025c834>] (dump_stack+0x90/0xb8) > [<c025c834>] (dump_stack) from [<c02f026c>] (__pm_runtime_idle+0xa4/0xa8) > [<c02f026c>] (__pm_runtime_idle) from [<c03e1a08>] (coresight_release_path+0x38/0x7c) > [<c03e1a08>] (coresight_release_path) from [<c03e210c>] (free_event_data+0x84/0x9c) > [<c03e210c>] (free_event_data) from [<c00f8be8>] (rb_irq_work+0x4c/0xcc) > [<c00f8be8>] (rb_irq_work) from [<c00e8860>] (irq_work_run_list+0x7c/0xb4) > [<c00e8860>] (irq_work_run_list) from [<c00e88b8>] (irq_work_run+0x20/0x34) > [<c00e88b8>] (irq_work_run) from [<c0016dcc>] (handle_IPI+0x1cc/0x334) > [<c0016dcc>] (handle_IPI) from [<c0009538>] (gic_handle_irq+0x84/0x88) > [<c0009538>] (gic_handle_irq) from [<c04f88f8>] (__irq_svc+0x58/0x78) > Exception stack(0xed865e98 to 0xed865ee0) > 5e80: 00000001 00000110 > 5ea0: 00000000 ee2f1080 20000113 c0784808 edbe4e1c b6ae5000 edb882f0 ed9b1e04 > 5ec0: edb88298 c075648c 00000002 ed865ee8 c008724c c04f7ee0 20000113 ffffffff > [<c04f88f8>] (__irq_svc) from [<c04f7ee0>] (_raw_spin_unlock_irqrestore+0x34/0x5c) > [<c04f7ee0>] (_raw_spin_unlock_irqrestore) from [<c00e8978>] (irq_work_queue+0xac/0xb4) > [<c00e8978>] (irq_work_queue) from [<c00f5020>] (perf_mmap_close+0x370/0x3c8) > [<c00f5020>] (perf_mmap_close) from [<c012c560>] (remove_vma+0x40/0x6c) > [<c012c560>] (remove_vma) from [<c012e2b4>] (do_munmap+0x210/0x35c) > [<c012e2b4>] (do_munmap) from [<c012e43c>] (vm_munmap+0x3c/0x50) > [<c012e43c>] (vm_munmap) from [<c0010320>] (ret_fast_syscall+0x0/0x1c) > > It should presumably be using pm_runtime_put() instead. That's a first - what platform did you test on? If I send you fixes will you be able to help me with the verification? Thanks, Mathieu
On Wed, Dec 23, 2015 at 09:27:28AM -0700, Mathieu Poirier wrote: > On 19 December 2015 at 10:13, Rabin Vincent <rabin@rab.in> wrote: > > It should presumably be using pm_runtime_put() instead. > > That's a first - what platform did you test on? If I send you fixes > will you be able to help me with the verification? I tested on a Pandaboard (OMAP4), with [1] applied, but you're likely to see this on any platform if you have CONFIG_PM=y and CONFIG_DEBUG_ATOMIC_SLEEP=y. [1] https://github.com/rabinv/linux/commit/omap-coresight
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index 77d0f9c1118d..1301edc44629 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -137,8 +137,6 @@ static int etb_enable(struct coresight_device *csdev) struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); unsigned long flags; - pm_runtime_get_sync(drvdata->dev); - spin_lock_irqsave(&drvdata->spinlock, flags); etb_enable_hw(drvdata); drvdata->enable = true; @@ -247,8 +245,6 @@ static void etb_disable(struct coresight_device *csdev) drvdata->enable = false; spin_unlock_irqrestore(&drvdata->spinlock, flags); - pm_runtime_put(drvdata->dev); - dev_info(drvdata->dev, "ETB disabled\n"); } diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c index 755f6f4d6d79..fae66cb45424 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x.c +++ b/drivers/hwtracing/coresight/coresight-etm3x.c @@ -349,7 +349,6 @@ static int etm_enable(struct coresight_device *csdev) struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); int ret; - pm_runtime_get_sync(csdev->dev.parent); spin_lock(&drvdata->spinlock); /* @@ -373,7 +372,6 @@ static int etm_enable(struct coresight_device *csdev) return 0; err: spin_unlock(&drvdata->spinlock); - pm_runtime_put(csdev->dev.parent); return ret; } @@ -422,7 +420,6 @@ static void etm_disable(struct coresight_device *csdev) spin_unlock(&drvdata->spinlock); put_online_cpus(); - pm_runtime_put(csdev->dev.parent); dev_info(drvdata->dev, "ETM tracing disabled\n"); } diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index a6707642bb23..1c6e32dd6e49 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -72,7 +72,6 @@ static int etm4_trace_id(struct coresight_device *csdev) if (!drvdata->enable) return drvdata->trcid; - pm_runtime_get_sync(drvdata->dev); spin_lock_irqsave(&drvdata->spinlock, flags); CS_UNLOCK(drvdata->base); @@ -81,7 +80,6 @@ static int etm4_trace_id(struct coresight_device *csdev) CS_LOCK(drvdata->base); spin_unlock_irqrestore(&drvdata->spinlock, flags); - pm_runtime_put(drvdata->dev); return trace_id; } @@ -187,7 +185,6 @@ static int etm4_enable(struct coresight_device *csdev) struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); int ret; - pm_runtime_get_sync(drvdata->dev); spin_lock(&drvdata->spinlock); /* @@ -207,7 +204,6 @@ static int etm4_enable(struct coresight_device *csdev) return 0; err: spin_unlock(&drvdata->spinlock); - pm_runtime_put(drvdata->dev); return ret; } @@ -256,8 +252,6 @@ static void etm4_disable(struct coresight_device *csdev) spin_unlock(&drvdata->spinlock); put_online_cpus(); - pm_runtime_put(drvdata->dev); - dev_info(drvdata->dev, "ETM tracing disabled\n"); } diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index 2e36bde7fcb4..a47bba361833 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -69,7 +69,6 @@ static int funnel_enable(struct coresight_device *csdev, int inport, { struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - pm_runtime_get_sync(drvdata->dev); funnel_enable_hw(drvdata, inport); dev_info(drvdata->dev, "FUNNEL inport %d enabled\n", inport); @@ -95,7 +94,6 @@ static void funnel_disable(struct coresight_device *csdev, int inport, struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); funnel_disable_hw(drvdata, inport); - pm_runtime_put(drvdata->dev); dev_info(drvdata->dev, "FUNNEL inport %d disabled\n", inport); } diff --git a/drivers/hwtracing/coresight/coresight-replicator-qcom.c b/drivers/hwtracing/coresight/coresight-replicator-qcom.c index 584059e9e866..8149087e8966 100644 --- a/drivers/hwtracing/coresight/coresight-replicator-qcom.c +++ b/drivers/hwtracing/coresight/coresight-replicator-qcom.c @@ -48,8 +48,6 @@ static int replicator_enable(struct coresight_device *csdev, int inport, { struct replicator_state *drvdata = dev_get_drvdata(csdev->dev.parent); - pm_runtime_get_sync(drvdata->dev); - CS_UNLOCK(drvdata->base); /* @@ -86,8 +84,6 @@ static void replicator_disable(struct coresight_device *csdev, int inport, CS_LOCK(drvdata->base); - pm_runtime_put(drvdata->dev); - dev_info(drvdata->dev, "REPLICATOR disabled\n"); } diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index 963ac197c253..a0fbb2e05389 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -41,7 +41,6 @@ static int replicator_enable(struct coresight_device *csdev, int inport, { struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - pm_runtime_get_sync(drvdata->dev); dev_info(drvdata->dev, "REPLICATOR enabled\n"); return 0; } @@ -51,7 +50,6 @@ static void replicator_disable(struct coresight_device *csdev, int inport, { struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - pm_runtime_put(drvdata->dev); dev_info(drvdata->dev, "REPLICATOR disabled\n"); } diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index a57c7ec1661f..5e2a71767870 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -242,12 +242,9 @@ static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode) { unsigned long flags; - pm_runtime_get_sync(drvdata->dev); - spin_lock_irqsave(&drvdata->spinlock, flags); if (drvdata->reading) { spin_unlock_irqrestore(&drvdata->spinlock, flags); - pm_runtime_put(drvdata->dev); return -EBUSY; } @@ -381,8 +378,6 @@ out: drvdata->enable = false; spin_unlock_irqrestore(&drvdata->spinlock, flags); - pm_runtime_put(drvdata->dev); - dev_info(drvdata->dev, "TMC disabled\n"); } diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index 7214efd10db5..e19b86e61c38 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -74,7 +74,6 @@ static int tpiu_enable(struct coresight_device *csdev) { struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - pm_runtime_get_sync(csdev->dev.parent); tpiu_enable_hw(drvdata); dev_info(drvdata->dev, "TPIU enabled\n"); @@ -98,7 +97,6 @@ static void tpiu_disable(struct coresight_device *csdev) struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); tpiu_disable_hw(drvdata); - pm_runtime_put(csdev->dev.parent); dev_info(drvdata->dev, "TPIU disabled\n"); } diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index b488af14a143..d053e5940fbf 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -24,6 +24,7 @@ #include <linux/coresight.h> #include <linux/of_platform.h> #include <linux/delay.h> +#include <linux/pm_runtime.h> #include "coresight-priv.h" @@ -376,7 +377,8 @@ out: /* * A path from this element to a sink has been found. The elements * leading to the sink are already enqueued, all that is left to do - * is add a node for this element. + * is tell the PM runtime core we need this element and add a node + * for it. */ node = kzalloc(sizeof(struct coresight_node), GFP_KERNEL); if (!node) @@ -384,6 +386,7 @@ out: node->csdev = csdev; list_add(&node->link, path); + pm_runtime_get_sync(csdev->dev.parent); return 0; } @@ -415,9 +418,13 @@ struct list_head *coresight_build_path(struct coresight_device *csdev) */ void coresight_release_path(struct list_head *path) { + struct coresight_device *csdev; struct coresight_node *nd, *next; list_for_each_entry_safe(nd, next, path, link) { + csdev = nd->csdev; + + pm_runtime_put_sync(csdev->dev.parent); list_del(&nd->link); kfree(nd); }