[PATCH] powerpc: Allow devices to register with numa topology
Change of_node_to_nid() to traverse the device tree, looking for a numa id.
Cell uses this to assign ids to SPUs, which are children of the CPU node.
Existing users of of_node_to_nid() are altered to use of_node_to_nid_single(),
which doesn't do the traversal.
Export an attach_sysdev_to_node() function, allowing system devices (eg.
SPUs) to link themselves into the numa topology in sysfs.
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index ed737ca..5bc2585 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -322,13 +322,31 @@
}
}
}
+
+int sysfs_add_device_to_node(struct sys_device *dev, int nid)
+{
+ struct node *node = &node_devices[nid];
+ return sysfs_create_link(&node->sysdev.kobj, &dev->kobj,
+ kobject_name(&dev->kobj));
+}
+
+void sysfs_remove_device_from_node(struct sys_device *dev, int nid)
+{
+ struct node *node = &node_devices[nid];
+ sysfs_remove_link(&node->sysdev.kobj, kobject_name(&dev->kobj));
+}
+
#else
static void register_nodes(void)
{
return;
}
+
#endif
+EXPORT_SYMBOL_GPL(sysfs_add_device_to_node);
+EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node);
+
/* Only valid if CPU is present. */
static ssize_t show_physical_id(struct sys_device *dev, char *buf)
{
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 0a335f3..092355f 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -194,7 +194,7 @@
/* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa
* info is found.
*/
-static int of_node_to_nid(struct device_node *device)
+static int of_node_to_nid_single(struct device_node *device)
{
int nid = -1;
unsigned int *tmp;
@@ -216,6 +216,28 @@
return nid;
}
+/* Walk the device tree upwards, looking for an associativity id */
+int of_node_to_nid(struct device_node *device)
+{
+ struct device_node *tmp;
+ int nid = -1;
+
+ of_node_get(device);
+ while (device) {
+ nid = of_node_to_nid_single(device);
+ if (nid != -1)
+ break;
+
+ tmp = device;
+ device = of_get_parent(tmp);
+ of_node_put(tmp);
+ }
+ of_node_put(device);
+
+ return nid;
+}
+EXPORT_SYMBOL_GPL(of_node_to_nid);
+
/*
* In theory, the "ibm,associativity" property may contain multiple
* associativity lists because a resource may be multiply connected
@@ -300,7 +322,7 @@
goto out;
}
- nid = of_node_to_nid(cpu);
+ nid = of_node_to_nid_single(cpu);
if (nid < 0 || !node_online(nid))
nid = any_online_node(NODE_MASK_ALL);
@@ -393,7 +415,7 @@
cpu = find_cpu_node(i);
BUG_ON(!cpu);
- nid = of_node_to_nid(cpu);
+ nid = of_node_to_nid_single(cpu);
of_node_put(cpu);
/*
@@ -437,7 +459,7 @@
* have associativity properties. If none, then
* everything goes to default_nid.
*/
- nid = of_node_to_nid(memory);
+ nid = of_node_to_nid_single(memory);
if (nid < 0)
nid = default_nid;
node_set_online(nid);
@@ -776,7 +798,7 @@
ha_new_range:
start = read_n_cells(n_mem_addr_cells, &memcell_buf);
size = read_n_cells(n_mem_size_cells, &memcell_buf);
- nid = of_node_to_nid(memory);
+ nid = of_node_to_nid_single(memory);
/* Domains not present at boot default to 0 */
if (nid < 0 || !node_online(nid))