Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:16

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /* Iterate over device tree topology, breadth or depth-first
0004  *
0005  * COPYRIGHT (c) 2009 Cobham Gaisler AB.
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, this list of conditions and the following disclaimer.
0012  * 2. Redistributions in binary form must reproduce the above copyright
0013  *    notice, this list of conditions and the following disclaimer in the
0014  *    documentation and/or other materials provided with the distribution.
0015  *
0016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0017  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0019  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0020  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0021  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0022  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0023  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0024  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0025  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0026  * POSSIBILITY OF SUCH DAMAGE.
0027  */
0028 
0029 #include <string.h>
0030 #include <drvmgr/drvmgr.h>
0031 #include <drvmgr/drvmgr_list.h>
0032 #include "drvmgr_internal.h"
0033 
0034 /* Traverse device tree breadth-first. Supports up to 31 buses */
0035 static intptr_t drvmgr_for_each_dev_breadth(
0036     intptr_t (*func)(struct drvmgr_dev *dev, void *arg),
0037     void *arg
0038     )
0039 {
0040     int ret = 0, i, pos;
0041     struct drvmgr_bus *bus, *buses[32];
0042     struct drvmgr_dev *dev;
0043 
0044     pos = 0;
0045     memset(&buses[0], 0, sizeof(buses));
0046     buses[pos++] = drvmgr.root_dev.bus;     /* Get root bus */
0047 
0048     for (i = 0, bus = buses[0]; buses[i]; i++, bus = buses[i]) {
0049         dev = bus->children;
0050         while (dev) {
0051             ret = func(dev, arg);
0052             if (ret != 0)
0053                 break;
0054             if (dev->bus && pos < 31)
0055                 buses[pos++] = dev->bus;
0056 
0057             dev = dev->next_in_bus;
0058         }
0059     }
0060 
0061     return ret;
0062 }
0063 
0064 /* Traverse device tree depth-first. */
0065 static intptr_t drvmgr_for_each_dev_depth(
0066     intptr_t (*func)(struct drvmgr_dev *dev, void *arg),
0067     void *arg
0068     )
0069 {
0070     int ret = 0;
0071     struct drvmgr_dev *dev;
0072 
0073     /* Get first device */
0074     dev = drvmgr.root_dev.bus->children;
0075 
0076     while (dev) {
0077         ret = func(dev, arg);
0078         if (ret != 0)
0079             break;
0080         if (dev->bus && dev->bus->children) {
0081             dev = dev->bus->children;
0082         } else {
0083 next_dev:
0084             if (dev->next_in_bus == NULL) {
0085                 /* Step up one level... back to parent bus */
0086                 dev = dev->parent->dev;
0087                 if (dev == &drvmgr.root_dev)
0088                     break;
0089                 goto next_dev;
0090             } else {
0091                 dev = dev->next_in_bus;
0092             }
0093         }
0094     }
0095 
0096     return ret;
0097 }
0098 
0099 /* Traverse device tree depth-first or breadth-first */
0100 intptr_t drvmgr_for_each_dev(
0101     intptr_t (*func)(struct drvmgr_dev *dev, void *arg),
0102     void *arg,
0103     int options
0104     )
0105 {
0106     intptr_t ret;
0107 
0108     DRVMGR_LOCK_READ();
0109 
0110     /* Get Root Device */
0111     if (drvmgr.root_dev.bus->children != NULL) {
0112         if (options & DRVMGR_FED_BF)
0113             ret = drvmgr_for_each_dev_breadth(func, arg);
0114         else
0115             ret = drvmgr_for_each_dev_depth(func, arg);
0116     } else
0117         ret = 0;
0118 
0119     DRVMGR_UNLOCK();
0120 
0121     return ret;
0122 }