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