Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
948ad1ac AS |
2 | #include <linux/string.h> |
3 | #include <linux/err.h> | |
4 | #include <linux/slab.h> | |
5 | #include <linux/of.h> | |
6 | ||
7 | #include "of_helpers.h" | |
8 | ||
9 | /** | |
10 | * pseries_of_derive_parent - basically like dirname(1) | |
11 | * @path: the full_name of a node to be added to the tree | |
12 | * | |
13 | * Returns the node which should be the parent of the node | |
14 | * described by path. E.g., for path = "/foo/bar", returns | |
15 | * the node with full_name = "/foo". | |
16 | */ | |
17 | struct device_node *pseries_of_derive_parent(const char *path) | |
18 | { | |
dc85aaed | 19 | struct device_node *parent; |
948ad1ac | 20 | char *parent_path = "/"; |
f755ecfb NF |
21 | const char *tail; |
22 | ||
23 | /* We do not want the trailing '/' character */ | |
24 | tail = kbasename(path) - 1; | |
948ad1ac AS |
25 | |
26 | /* reject if path is "/" */ | |
27 | if (!strcmp(path, "/")) | |
28 | return ERR_PTR(-EINVAL); | |
29 | ||
f755ecfb | 30 | if (tail > path) { |
a46d9884 | 31 | parent_path = kstrndup(path, tail - path, GFP_KERNEL); |
948ad1ac AS |
32 | if (!parent_path) |
33 | return ERR_PTR(-ENOMEM); | |
948ad1ac AS |
34 | } |
35 | parent = of_find_node_by_path(parent_path); | |
948ad1ac AS |
36 | if (strcmp(parent_path, "/")) |
37 | kfree(parent_path); | |
dc85aaed | 38 | return parent ? parent : ERR_PTR(-EINVAL); |
948ad1ac | 39 | } |