Skip to contentSkip to conversation

sysfs, device-tree: aid for debugging device tree boot problems

PATCH In review Frank Rowand 3 participants 7 messages Apr 23, 2014 – Apr 28, 2014

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 sysfs, device-tree: aid for debugging device tree boot problems

Create some infrastructure to aid trouble shooting device tree related boot issues.

Add a %driver_name file to each device tree node sysfs directory which has had a driver bound to it. This allows detecting device tree nodes which failed to be bound to any driver.

Examples of using the %driver_name file (note that /proc/device-tree is a link to the base of the device tree sysfs tree):

1) To find list of device tree nodes with no driver:

  # A few false positives may be reported.  For example,
  #   node_full_path of "." is the board.
  #
  # output is: node_full_path compatible_string
  #
  cd /proc/device-tree
  for k in `find . -type d`; do
     if [[ -f ${k}/compatible && ! -f ${k}/%driver_name ]] ; then
        if [[ "`cat ${k}/compatible`" != "simple-bus" ]] ; then
           echo `echo ${k} | sed -e 's|./||'` `cat ${k}/compatible`
        fi
     fi
  done | sort

2) To find list of device tree nodes with a bound driver:

  # output is:  node_full_path driver_name
  #
  cd /proc/device-tree
  for k in `find . -name %driver_name` ; do
     echo `echo ${k} | sed -e 's|./||' -e 's|/%driver_name$||'` `cat ${k}`
  done | sort

3) To find list of device tree nodes with a bound driver:

  # output is:  driver_name node_full_path
  #
  cd /proc/device-tree
  for k in `find . -name %driver_name` ; do
     echo `cat ${k}` `echo ${k} | sed -e 's|./||' -e 's|/%driver_name$||'`
  done | sort

---

 Documentation/ABI/testing/sysfs-firmware-ofw |   17 +++++++-
 drivers/base/dd.c                            |    5 ++
 drivers/of/base.c                            |   55 +++++++++++++++++++++++++++
 include/linux/of.h                           |    9 ++++
 4 files changed, 85 insertions(+), 1 deletion(-)
drivers/base/dd.c +5 -0
Index: b/drivers/base/dd.c
===================================================================
@@ -25,6 +25,7 @@
 #include <linux/kthread.h>
 #include <linux/wait.h>
 #include <linux/async.h>
+#include <linux/of.h>
 #include <linux/pm_runtime.h>
 #include <linux/pinctrl/devinfo.h>
 
@@ -194,6 +195,8 @@ static void driver_bound(struct device *
 
 	klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);
 
+	of_notify_driver_bound(dev);
+
 	/*
 	 * Make sure the device is no longer in one of the deferred lists and
 	 * kick off retrying all pending devices
@@ -505,6 +508,8 @@ static void __device_release_driver(stru
 
 		pm_runtime_put_sync(dev);
 
+		of_notify_driver_released(dev);
+
 		if (dev->bus && dev->bus->remove)
 			dev->bus->remove(dev);
 		else if (drv->remove)
drivers/of/base.c +55 -0

68 lines not on this page · raw message

include/linux/of.h +9 -0
Index: b/include/linux/of.h
===================================================================
@@ -60,6 +60,7 @@ struct device_node {
 	struct	kobject kobj;
 	unsigned long _flags;
 	void	*data;
+	struct device *bound_dev;
 #if defined(CONFIG_SPARC)
 	const char *path_component_name;
 	unsigned int unique_id;
@@ -347,6 +348,9 @@ const char *of_prop_next_string(struct p
 
 int of_device_is_stdout_path(struct device_node *dn);
 
+void of_notify_driver_bound(struct device *dev);
+void of_notify_driver_released(struct device *dev);
+
 #else /* CONFIG_OF */
 
 static inline const char* of_node_full_name(struct device_node *np)
@@ -571,6 +575,11 @@ static inline const char *of_prop_next_s
 
 #define of_match_ptr(_ptr)	NULL
 #define of_match_node(_matches, _node)	NULL
+
+void of_notify_driver_bound(struct device *dev) { }
+
+void of_notify_driver_released(struct device *dev) { }
+
 #endif /* CONFIG_OF */
 
 #if defined(CONFIG_OF) && defined(CONFIG_NUMA)
Documentation/ABI/testing/sysfs-firmware-ofw +16 -1
Index: b/Documentation/ABI/testing/sysfs-firmware-ofw
===================================================================
@@ -25,4 +25,19 @@ Description:
 		directory name is the resolved path component name (node
 		name plus address). Properties are represented as files
 		in the directory. The contents of each file is the exact
-		binary data from the device tree.
+		binary data from the device tree.  Files that are exceptions
+		to this description will be described separately in this file.
+
+What:		/sys/firmware/devicetree/.../%driver_name
+Date:		April 2014
+KernelVersion:  3.15
+Contact:	Frank Rowand <[email protected]>
+Description:
+		This file does not represent a device tree property.  The file
+		will exist only if a driver is bound to the device tree node.
+		Reading from this file returns the name of the driver.
+
+		The apparently bizarre choice of prefixing the file name with
+		"%" is to avoid any possible conflict with a valid device tree
+		property name.  ePAPR version 1.1 does not allow a property
+		name to contain the character "%".
#1 lore raw
Quoted 6 lines · Frank Rowand

Create some infrastructure to aid trouble shooting device tree related boot issues.

Add a %driver_name file to each device tree node sysfs directory which has had a driver bound to it. This allows detecting device tree nodes which failed to be bound to any driver.

Why is this needed, shouldn't there already be a "driver" symlink in sysfs for these devices when a driver binds to them? The rest of the driver model works that way, why is of devices any different?

Quoted 31 lines

Examples of using the %driver_name file (note that /proc/device-tree is a link to the base of the device tree sysfs tree):

1) To find list of device tree nodes with no driver:

  # A few false positives may be reported.  For example,
  #   node_full_path of "." is the board.
  #
  # output is: node_full_path compatible_string
  #
  cd /proc/device-tree
  for k in `find . -type d`; do
     if [[ -f ${k}/compatible && ! -f ${k}/%driver_name ]] ; then
        if [[ "`cat ${k}/compatible`" != "simple-bus" ]] ; then
           echo `echo ${k} | sed -e 's|./||'` `cat ${k}/compatible`
        fi
     fi
  done | sort

2) To find list of device tree nodes with a bound driver:

  # output is:  node_full_path driver_name
  #
  cd /proc/device-tree
  for k in `find . -name %driver_name` ; do
     echo `echo ${k} | sed -e 's|./||' -e 's|/%driver_name$||'` `cat ${k}`
  done | sort
Quoted 8 lines

3) To find list of device tree nodes with a bound driver:

  # output is:  driver_name node_full_path
  #
  cd /proc/device-tree
  for k in `find . -name %driver_name` ; do
     echo `cat ${k}` `echo ${k} | sed -e 's|./||' -e 's|/%driver_name$||'`
  done | sort

If we take this patch, these examples should be somewhere in the documentation to make it easy for others.

Quoted 1 line

Minor nit, your From: line doesn't match this signed-off-by: so something has to change (or add a new From: line, like SubmittingPatches decribes how to do.)

thanks,

greg k-h

#2 lore raw
Quoted 4 lines · Greg Kroah-Hartman
Quoted 3 lines · Frank Rowand

Create some infrastructure to aid trouble shooting device tree related boot issues.

Quoted 8 lines
Quoted 3 lines

Add a %driver_name file to each device tree node sysfs directory which has had a driver bound to it. This allows detecting device tree nodes which failed to be bound to any driver.

Why is this needed, shouldn't there already be a "driver" symlink in sysfs for these devices when a driver binds to them? The rest of the driver model works that way, why is of devices any different?

Because it hasn't been added yet! I only just committed the change to convert device_nodes into kobjects in v3.14. The next step is to add driver symlinks.

That said, the devicetree node is already exposed in the uevent for a device. It should already be possible to find all device tree nodes that don't have a device, or devices without a driver:

To get a list of all nodes:

find /proc/device-tree/ -type d | sed -e 's/\/proc\/device-tree//'

or a little more nuanced, only choosing nodes with a compatible property:

for k in find /proc/device-tree/ -name compatible; do

	echo $(dirname $k) | sed -e 's/\/proc\/device-tree//'

done | sort

It can get even more refined than that if need be.

To get a list of all nodes with a device that has been created:

for k in find devices -name uevent; do

	grep '^OF_FULLNAME' $k | sed -e 's/OF_FULLNAME=//'

done | sort

To get a list of all nodes with a device that has been bound to a driver:

for k in find devices -name uevent; do

	if [[ -d $(dirname $k)/driver ]]; then
		grep '^OF_FULLNAME' $k | sed -e 's/OF_FULLNAME=//'
	fi

done | sort

The suggestions you have below would be the anything in the first list that isn't in the second or third:

bound=$(for k in find /sys/devices -name uevent; do

		if [[ -d $(dirname $k)/driver ]]; then
			grep '^OF_FULLNAME' $k | sed -e 's/OF_FULLNAME=//'
		fi
	done)

nodes=$(for k in find /proc/device-tree/ -name compatible; do

		echo $(dirname $k) | sed -e 's/\/proc\/device-tree//'
	done | sort)

for n in $nodes; do

	if ! echo $bound | grep -q "$n"; then
		echo $n $(cat /proc/device-tree/$n/compatible)
	fi

done

Quoted 45 lines
Quoted 31 lines

Examples of using the %driver_name file (note that /proc/device-tree is a link to the base of the device tree sysfs tree):

1) To find list of device tree nodes with no driver:

  # A few false positives may be reported.  For example,
  #   node_full_path of "." is the board.
  #
  # output is: node_full_path compatible_string
  #
  cd /proc/device-tree
  for k in `find . -type d`; do
     if [[ -f ${k}/compatible && ! -f ${k}/%driver_name ]] ; then
        if [[ "`cat ${k}/compatible`" != "simple-bus" ]] ; then
           echo `echo ${k} | sed -e 's|./||'` `cat ${k}/compatible`
        fi
     fi
  done | sort

2) To find list of device tree nodes with a bound driver:

  # output is:  node_full_path driver_name
  #
  cd /proc/device-tree
  for k in `find . -name %driver_name` ; do
     echo `echo ${k} | sed -e 's|./||' -e 's|/%driver_name$||'` `cat ${k}`
  done | sort
Quoted 8 lines

3) To find list of device tree nodes with a bound driver:

  # output is:  driver_name node_full_path
  #
  cd /proc/device-tree
  for k in `find . -name %driver_name` ; do
     echo `cat ${k}` `echo ${k} | sed -e 's|./||' -e 's|/%driver_name$||'`
  done | sort

If we take this patch, these examples should be somewhere in the documentation to make it easy for others.

Quoted 1 line
Quoted 7 lines

Minor nit, your From: line doesn't match this signed-off-by: so something has to change (or add a new From: line, like SubmittingPatches decribes how to do.)

thanks,

greg k-h

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#3 lore raw
Quoted 9 lines · Grant Likely
Quoted 8 lines · Greg Kroah-Hartman
Quoted 6 lines · Frank Rowand

Create some infrastructure to aid trouble shooting device tree related boot issues.

Add a %driver_name file to each device tree node sysfs directory which has had a driver bound to it. This allows detecting device tree nodes which failed to be bound to any driver.

Quoted 8 lines
Quoted 4 lines

Why is this needed, shouldn't there already be a "driver" symlink in sysfs for these devices when a driver binds to them? The rest of the driver model works that way, why is of devices any different?

Because it hasn't been added yet! I only just committed the change to convert device_nodes into kobjects in v3.14. The next step is to add driver symlinks.

No need to add a "driver" symlink. The device directories in sysfs already have a driver symlink.

Quoted 15 lines

That said, the devicetree node is already exposed in the uevent for a device. It should already be possible to find all device tree nodes that don't have a device, or devices without a driver:

To get a list of all nodes:

find /proc/device-tree/ -type d | sed -e 's/\/proc\/device-tree//'

or a little more nuanced, only choosing nodes with a compatible property:

for k in find /proc/device-tree/ -name compatible; do

	echo $(dirname $k) | sed -e 's/\/proc\/device-tree//'

done | sort

Quoted 7 lines

It can get even more refined than that if need be.

To get a list of all nodes with a device that has been created:

for k in find devices -name uevent; do

	grep '^OF_FULLNAME' $k | sed -e 's/OF_FULLNAME=//'

done | sort

< snip >

Thanks Grant! I did not realize that uevent contained that information.

-Frank

#4 lore raw
Quoted 15 lines · Frank Rowand
Quoted 14 lines · Grant Likely
Quoted 12 lines · Greg Kroah-Hartman
Quoted 6 lines · Frank Rowand

Create some infrastructure to aid trouble shooting device tree related boot issues.

Add a %driver_name file to each device tree node sysfs directory which has had a driver bound to it. This allows detecting device tree nodes which failed to be bound to any driver.

Why is this needed, shouldn't there already be a "driver" symlink in sysfs for these devices when a driver binds to them? The rest of the driver model works that way, why is of devices any different?

Quoted 6 lines
Quoted 3 lines

Because it hasn't been added yet! I only just committed the change to convert device_nodes into kobjects in v3.14. The next step is to add driver symlinks.

No need to add a "driver" symlink. The device directories in sysfs already have a driver symlink.

Sorry, I meant of_node symlink. That is the bit I've been planning to add.

g.

#5 lore raw
In reply to Greg Kroah-Hartman
Quoted 11 lines · Greg Kroah-Hartman
Quoted 6 lines · Frank Rowand

Create some infrastructure to aid trouble shooting device tree related boot issues.

Add a %driver_name file to each device tree node sysfs directory which has had a driver bound to it. This allows detecting device tree nodes which failed to be bound to any driver.

Why is this needed, shouldn't there already be a "driver" symlink in sysfs for these devices when a driver binds to them? The rest of the driver model works that way, why is of devices any different?

Yes, the devices do have a "driver" symlink in sysfs.

The problem I had was that I could not deterministically determine the device name in /sysfs that was associated with a device tree node that the device was created for. And I couldn't find a link from the device tree entries to the device tree node.

Grant's reply to your email provided the solution to my problem; the device uevents file contains the full device tree path of the associated device tree node.

Grant's reply removes the need for my patch.

Quoted 41 lines
Quoted 32 lines

Examples of using the %driver_name file (note that /proc/device-tree is a link to the base of the device tree sysfs tree):

1) To find list of device tree nodes with no driver:

  # A few false positives may be reported.  For example,
  #   node_full_path of "." is the board.
  #
  # output is: node_full_path compatible_string
  #
  cd /proc/device-tree
  for k in `find . -type d`; do
     if [[ -f ${k}/compatible && ! -f ${k}/%driver_name ]] ; then
        if [[ "`cat ${k}/compatible`" != "simple-bus" ]] ; then
           echo `echo ${k} | sed -e 's|./||'` `cat ${k}/compatible`
        fi
     fi
  done | sort

2) To find list of device tree nodes with a bound driver:

  # output is:  node_full_path driver_name
  #
  cd /proc/device-tree
  for k in `find . -name %driver_name` ; do
     echo `echo ${k} | sed -e 's|./||' -e 's|/%driver_name$||'` `cat ${k}`
  done | sort
Quoted 8 lines

3) To find list of device tree nodes with a bound driver:

  # output is:  driver_name node_full_path
  #
  cd /proc/device-tree
  for k in `find . -name %driver_name` ; do
     echo `cat ${k}` `echo ${k} | sed -e 's|./||' -e 's|/%driver_name$||'`
  done | sort
Quoted 2 lines

If we take this patch, these examples should be somewhere in the documentation to make it easy for others.

That is a good idea. I'll package up the equivalent shell code from Grant's email. Any suggestions on location?

scripts/debug/devicetree/
scripts/devicetree/debug/
Documentation/devicetree/scripts/

If there is no good location in the kernel tree, then I will put them either on the devicetree wiki, or the devicetree section of the elinux wiki.

Quoted 6 lines
Quoted 2 lines

Minor nit, your From: line doesn't match this signed-off-by: so something has to change (or add a new From: line, like SubmittingPatches decribes how to do.)

Oops, thanks for pointing that out.

Quoted 4 lines

thanks,

greg k-h

-Frank

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#6 lore raw
Quoted 12 lines · Frank Rowand
Quoted 11 lines
Quoted 8 lines

3) To find list of device tree nodes with a bound driver:

  # output is:  driver_name node_full_path
  #
  cd /proc/device-tree
  for k in `find . -name %driver_name` ; do
     echo `cat ${k}` `echo ${k} | sed -e 's|./||' -e 's|/%driver_name$||'`
  done | sort

If we take this patch, these examples should be somewhere in the documentation to make it easy for others.

Quoted 6 lines

That is a good idea. I'll package up the equivalent shell code from Grant's email. Any suggestions on location?

scripts/debug/devicetree/
scripts/devicetree/debug/
Documentation/devicetree/scripts/

tools/ is probably the best place for them, or in Documentation/, either would work.

thanks,

greg k-h