Date: Mon, 1 Sep 2014 22:40:31 +0000 (UTC) From: Ian Lepore <ian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r270953 - head/sys/dev/ofw Message-ID: <201409012240.s81MeVrB010269@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ian Date: Mon Sep 1 22:40:31 2014 New Revision: 270953 URL: http://svnweb.freebsd.org/changeset/base/270953 Log: Create a mechanism for looking up a device_t associated with an ofw/fdt xref handle, and for registering that association. Also use the same data for faster translations between node and xref handles. Now when fdt properties contain &othernode references, a driver can find the device instance that corresponds to &othernode, and thus can use interfaces provided by that instance. Reviewed by: nwhitehorn Modified: head/sys/dev/ofw/openfirm.c head/sys/dev/ofw/openfirm.h Modified: head/sys/dev/ofw/openfirm.c ============================================================================== --- head/sys/dev/ofw/openfirm.c Mon Sep 1 22:25:42 2014 (r270952) +++ head/sys/dev/ofw/openfirm.c Mon Sep 1 22:40:31 2014 (r270953) @@ -84,6 +84,78 @@ static ofw_t ofw_obj; static struct ofw_kobj ofw_kernel_obj; static struct kobj_ops ofw_kernel_kops; +struct xrefinfo { + phandle_t xref; + phandle_t node; + device_t dev; + SLIST_ENTRY(xrefinfo) next_entry; +}; + +static SLIST_HEAD(, xrefinfo) xreflist = SLIST_HEAD_INITIALIZER(xreflist); +static boolean_t xref_init_done; + +#define FIND_BY_XREF 0 +#define FIND_BY_NODE 1 + +/* + * xref-phandle-device lookup helper routines. + * + * As soon as we are able to use malloc(), walk the node tree and build a list + * of info that cross-references node handles, xref handles, and device_t + * instances. This list exists primarily to allow association of a device_t + * with an xref handle, but it is also used to speed up translation between xref + * and node handles. Before malloc() is available we have to recursively search + * the node tree each time we want to translate between a node and xref handle. + * Afterwards we can do the translations by searching this much shorter list. + */ +static void +xrefinfo_create(phandle_t node) +{ + struct xrefinfo * xi; + phandle_t child, xref; + + /* + * Recursively descend from parent, looking for nodes with a property + * named either "phandle", "ibm,phandle", or "linux,phandle". For each + * such node found create an entry in the xreflist. + */ + for (child = OF_child(node); child != 0; child = OF_peer(child)) { + xrefinfo_create(child); + if (OF_getencprop(child, "phandle", &xref, sizeof(xref)) == + -1 && OF_getencprop(child, "ibm,phandle", &xref, + sizeof(xref)) == -1 && OF_getencprop(child, + "linux,phandle", &xref, sizeof(xref)) == -1) + continue; + xi = malloc(sizeof(*xi), M_OFWPROP, M_WAITOK | M_ZERO); + xi->node = child; + xi->xref = xref; + SLIST_INSERT_HEAD(&xreflist, xi, next_entry); + } +} + +static void +xrefinfo_init(void *unsed) +{ + + xrefinfo_create(OF_peer(0)); + xref_init_done = true; +} +SYSINIT(xrefinfo, SI_SUB_KMEM, SI_ORDER_ANY, xrefinfo_init, NULL); + +static struct xrefinfo * +xrefinfo_find(phandle_t phandle, int find_by) +{ + struct xrefinfo * xi; + + SLIST_FOREACH(xi, &xreflist, next_entry) { + if (find_by == FIND_BY_XREF && phandle == xi->xref) + return (xi); + else if (find_by == FIND_BY_NODE && phandle == xi->node) + return (xi); + } + return (NULL); +} + /* * OFW install routines. Highest priority wins, equal priority also * overrides allowing last-set to win. @@ -465,29 +537,67 @@ OF_child_xref_phandle(phandle_t parent, phandle_t OF_node_from_xref(phandle_t xref) { + struct xrefinfo *xi; phandle_t node; - node = OF_child_xref_phandle(OF_peer(0), xref); - if (node == -1) - return (xref); + if (xref_init_done) { + if ((xi = xrefinfo_find(xref, FIND_BY_XREF)) == NULL) + return (xref); + return (xi->node); + } + if ((node = OF_child_xref_phandle(OF_peer(0), xref)) == -1) + return (xref); return (node); } phandle_t OF_xref_from_node(phandle_t node) { + struct xrefinfo *xi; phandle_t xref; + if (xref_init_done) { + if ((xi = xrefinfo_find(node, FIND_BY_NODE)) == NULL) + return (node); + return (xi->xref); + } + if (OF_getencprop(node, "phandle", &xref, sizeof(xref)) == -1 && OF_getencprop(node, "ibm,phandle", &xref, sizeof(xref)) == -1 && OF_getencprop(node, "linux,phandle", &xref, sizeof(xref)) == -1) return (node); - return (xref); } +device_t +OF_device_from_xref(phandle_t xref) +{ + struct xrefinfo *xi; + + if (xref_init_done) { + if ((xi = xrefinfo_find(xref, FIND_BY_XREF)) == NULL) + return (NULL); + return (xi->dev); + } + panic("Attempt to find device before xreflist_init"); +} + +int +OF_device_register_xref(phandle_t xref, device_t dev) +{ + struct xrefinfo *xi; + + if (xref_init_done) { + if ((xi = xrefinfo_find(xref, FIND_BY_XREF)) == NULL) + return (ENXIO); + xi->dev = dev; + return (0); + } + panic("Attempt to register device before xreflist_init"); +} + /* Call the method in the scope of a given instance. */ int OF_call_method(const char *method, ihandle_t instance, int nargs, int nreturns, Modified: head/sys/dev/ofw/openfirm.h ============================================================================== --- head/sys/dev/ofw/openfirm.h Mon Sep 1 22:25:42 2014 (r270952) +++ head/sys/dev/ofw/openfirm.h Mon Sep 1 22:40:31 2014 (r270953) @@ -133,6 +133,16 @@ ssize_t OF_package_to_path(phandle_t no phandle_t OF_node_from_xref(phandle_t xref); phandle_t OF_xref_from_node(phandle_t node); +/* + * When properties contain references to other nodes using xref handles it is + * often necessary to use interfaces provided by the driver for the referenced + * instance. These routines allow a driver that provides such an interface to + * register its association with an xref handle, and for other drivers to obtain + * the device_t associated with an xref handle. + */ +device_t OF_device_from_xref(phandle_t xref); +int OF_device_register_xref(phandle_t xref, device_t dev); + /* Device I/O functions */ ihandle_t OF_open(const char *path); void OF_close(ihandle_t instance);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201409012240.s81MeVrB010269>