Re: [RFC PATCH] boot-time: instrument probes more

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Tim,

On Saturday, 21 December 2024 15:47:54 CET you wrote:
> Hello,
> 
> On Monday, 9 December 2024 at 04:10:04 Bird, Tim <Tim.Bird@xxxxxxxx> wrote:
> > ----
> > Below is the patch that adds the extra instrumentation.  My quick question is, does this look useful?
> > Can it be used to find the more problematic (ie long-duration) probe functions or drivers initializations?
> > 
> 
> Yes, it looks useful to me. While an experienced developer _might_ be able to match
> device names and drivers at a quick glance, that's not the case for everyone, in
> particular on certain SoCs which are modelled at devicetree level with an exceptionally
> high number of "generic" device nodes.
> 
> > ----
> > diff --git a/drivers/base/dd.c b/drivers/base/dd.c
> > index 0c3725c3eefa..5e19079b0a2b 100644
> > --- a/drivers/base/dd.c
> > +++ b/drivers/base/dd.c
> > @@ -28,6 +28,7 @@
> >  #include <linux/pm_runtime.h>
> >  #include <linux/pinctrl/devinfo.h>
> >  #include <linux/slab.h>
> > +#include <linux/kallsyms.h>
> >  
> >  #include "base.h"
> >  #include "power/power.h"
> > @@ -732,8 +733,16 @@ static int really_probe(struct device *dev, struct device_driver *drv)
> >  static int really_probe_debug(struct device *dev, struct device_driver *drv)
> >  {
> >  	ktime_t calltime, rettime;
> > +	char fn_name[KSYM_SYMBOL_LEN];
> > +	unsigned long addr = 0;
> >  	int ret;
> >  
> > +	if (dev->bus->probe)
> > +		addr = (unsigned long)dev->bus->probe;
> > +	else if (drv->probe)
> > +		addr = (unsigned long)drv->probe;
> > +	sprint_symbol_no_offset(fn_name, addr);
> > +
> >  	calltime = ktime_get();
> >  	ret = really_probe(dev, drv);
> >  	rettime = ktime_get();
> > @@ -742,8 +751,8 @@ static int really_probe_debug(struct device *dev, struct device_driver *drv)
> >  	 * CONFIG_DYNAMIC_DEBUG and we want a simple 'initcall_debug' on the
> >  	 * kernel commandline to print this all the time at the debug level.
> >  	 */
> > -	printk(KERN_DEBUG "probe of %s returned %d after %lld usecs\n",
> > -		 dev_name(dev), ret, ktime_us_delta(rettime, calltime));
> > +	printk(KERN_DEBUG "probe %s in driver %s for device %s returned %d after %lld usecs\n",
> > +		 fn_name, drv->name, dev_name(dev), ret, ktime_us_delta(rettime, calltime));
> >  	return ret;
> >  }
> >  
> > diff --git a/drivers/base/platform.c b/drivers/base/platform.c
> > index 76bfcba25003..ae15969c483a 100644
> > --- a/drivers/base/platform.c
> > +++ b/drivers/base/platform.c
> > @@ -32,6 +32,7 @@
> >  #include <linux/types.h>
> >  #include <linux/iommu.h>
> >  #include <linux/dma-map-ops.h>
> > +#include <linux/kallsyms.h>
> >  
> >  #include "base.h"
> >  #include "power/power.h"
> > @@ -1381,6 +1382,9 @@ static int platform_probe(struct device *_dev)
> >  	struct platform_driver *drv = to_platform_driver(_dev->driver);
> >  	struct platform_device *dev = to_platform_device(_dev);
> >  	int ret;
> > +	char fn_name[KSYM_SYMBOL_LEN];
> > +	unsigned long addr = 0;
> > +
> >  
> >  	/*
> >  	 * A driver registered using platform_driver_probe() cannot be bound
> > @@ -1401,6 +1405,13 @@ static int platform_probe(struct device *_dev)
> >  		goto out;
> >  
> >  	if (drv->probe) {
> > +		if (initcall_debug) {
> > +			addr = (unsigned long)drv->probe;
> > +			sprint_symbol_no_offset(fn_name, addr);
> > +
> > +			printk(KERN_DEBUG "platform probe %s is being called\n", fn_name);
> > +		}
> > +
> >  		ret = drv->probe(dev);
> >  		if (ret)
> >  			dev_pm_domain_detach(_dev, true);
> 
> Does this really belong here? Why not add a print inside really_probe_debug(), just
> before the call to really_probe()? That approach would catch all probe types (not just
> platform_probe) while containing the initcall_debug instrumentation inside dd.c
> 

I had some spare time and I tried to write a patch that maintains the format
of the "return" message (because of backward compatibility) while adding the
details you inserted just before the probe in dd.c.

I then used it on the Beagleplay and I can confirm this helps a lot.

Thank you!


Regards,

Francesco

---
 drivers/base/dd.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index f0e4b4aba885..e33ae82064ed 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -28,6 +28,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/pinctrl/devinfo.h>
 #include <linux/slab.h>
+#include <linux/kallsyms.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -732,16 +733,28 @@ static int really_probe(struct device *dev, const struct device_driver *drv)
 static int really_probe_debug(struct device *dev, const struct device_driver *drv)
 {
 	ktime_t calltime, rettime;
+	char fn_name[KSYM_SYMBOL_LEN];
+	unsigned long addr = 0;
 	int ret;
 
-	calltime = ktime_get();
-	ret = really_probe(dev, drv);
-	rettime = ktime_get();
+	if (dev->bus->probe)
+		addr = (unsigned long)dev->bus->probe;
+	else if (drv->probe)
+		addr = (unsigned long)drv->probe;
+	sprint_symbol_no_offset(fn_name, addr);
+
 	/*
-	 * Don't change this to pr_debug() because that requires
+	 * Don't change this or the one below to pr_debug() because that requires
 	 * CONFIG_DYNAMIC_DEBUG and we want a simple 'initcall_debug' on the
 	 * kernel commandline to print this all the time at the debug level.
 	 */
+	printk(KERN_DEBUG "calling probe %s in driver %s for device %s\n",
+	       fn_name, drv->name, dev_name(dev));
+
+	calltime = ktime_get();
+	ret = really_probe(dev, drv);
+	rettime = ktime_get();
+
 	printk(KERN_DEBUG "probe of %s returned %d after %lld usecs\n",
 		 dev_name(dev), ret, ktime_us_delta(rettime, calltime));
 	return ret;
-- 
2.47.1








[Index of Archives]     [Gstreamer Embedded]     [Linux MMC Devel]     [U-Boot V2]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux ARM Kernel]     [Linux OMAP]     [Linux SCSI]

  Powered by Linux