[Cbe-oss-dev] [PATCH] cell: indexing of SPUs based on firmware vicinity property

Andre Detsch adetsch at br.ibm.com
Sun Feb 18 09:56:10 EST 2007


Subject: cell: indexing of SPUs based on firmware vicinity property
From: Andre Detsch <adetsch at br.ibm.com>

This patch links spus according to their physical position using
information provided by the firmware through a special vicinity
device-tree property. This property is present in current version
of Malta firmware.

Example of vicinity properties for a node in Malta:

Node:        Vicinity property contains phandles of:
spe at 0        [ spe at 100000 , mic-tm at 50a000 ]
spe at 100000   [ spe at 0      , spe at 200000    ]
spe at 200000   [ spe at 100000 , spe at 300000    ]
spe at 300000   [ spe at 200000 , bif0 at 512000   ]
spe at 80000    [ spe at 180000 , mic-tm at 50a000 ]
spe at 180000   [ spe at 80000  , spe at 280000    ]
spe at 280000   [ spe at 180000 , spe at 380000    ]
spe at 380000   [ spe at 280000 , bif0 at 512000   ]

Only spe@* have a vicinity property (e.g., bif0 at 512000 and
mic-tm at 50a000 do not have it).

Signed-off-by: Andre Detsch <adetsch at br.ibm.com>

Index: linux-2.6.20/arch/powerpc/platforms/cell/spu_base.c
===================================================================
--- linux-2.6.20.orig/arch/powerpc/platforms/cell/spu_base.c
+++ linux-2.6.20/arch/powerpc/platforms/cell/spu_base.c
@@ -735,6 +735,88 @@ static int of_has_vicinity(void)
 	return of_find_property(spu_devnode(spu), "vicinity", NULL) != NULL;
 }
 
+static struct spu *aff_devnode_spu(int be, struct device_node *dn)
+{
+	struct spu *spu;
+
+	list_for_each_entry(spu, &be_spu_info[be].spus, be_list)
+		if (spu_devnode(spu) == dn)
+			return spu;
+	return NULL;
+}
+
+static struct spu *
+aff_node_next_to(int be, struct device_node *target, struct device_node 
*avoid)
+{
+	struct spu *spu;
+	const phandle *vic_handles;
+	int lenp, i;
+
+	list_for_each_entry(spu, &be_spu_info[be].spus, be_list) {
+		if (spu_devnode(spu) == avoid)
+			continue;
+		vic_handles = get_property(spu_devnode(spu), "vicinity", &lenp);
+		for (i=0; i < (lenp / sizeof(phandle)); i++) {
+			if (vic_handles[i] == target->linux_phandle)
+				return spu;
+		}
+	}
+	return NULL;
+}
+
+static void init_aff_fw_vicinity_node(int be)
+{
+	struct spu *spu, *last_spu;
+	struct device_node *vic_dn, *last_spu_dn;
+	phandle avoid_ph;
+	const phandle *vic_handles;
+	const char *name;
+	int lenp, i, added, mem_aff;
+
+	last_spu = list_entry(be_spu_info[be].spus.next, struct spu, be_list);
+	avoid_ph = 0;
+	for (added = 1; added < be_spu_info[be].n_spus; added++) {
+		last_spu_dn = spu_devnode(last_spu);
+		vic_handles = get_property(last_spu_dn, "vicinity", &lenp);
+
+		for (i = 0; i < (lenp / sizeof(phandle)); i++) {
+			if (vic_handles[i] == avoid_ph)
+				continue;
+
+			vic_dn = of_find_node_by_phandle(vic_handles[i]);
+			if (!vic_dn)
+				continue;
+
+			name = get_property(vic_dn, "name", NULL);
+			if (strcmp(name, "spe") == 0) {
+				spu = aff_devnode_spu(be, vic_dn);
+				avoid_ph = last_spu_dn->linux_phandle;
+			} else {
+				mem_aff = strcmp(name, "mic-tm") == 0;
+				spu = aff_node_next_to(be, vic_dn, last_spu_dn);
+				if (!spu)
+					continue;
+				if (mem_aff) {
+					last_spu->has_mem_affinity = 1;
+					spu->has_mem_affinity = 1;
+				}
+				avoid_ph = vic_dn->linux_phandle;
+			}
+			list_add_tail(&spu->aff_list, &last_spu->aff_list);
+			last_spu = spu;
+			break;
+		}
+	}
+}
+
+static void init_aff_fw_vicinity(void)
+{
+	int be;
+
+	for (be = 0; be < MAX_NUMNODES; be++)
+		init_aff_fw_vicinity_node(be);
+}
+
 static int __init init_spu_base(void)
 {
 	int i, ret;
@@ -763,7 +845,9 @@ static int __init init_spu_base(void)
 
 	xmon_register_spus(&spu_full_list);
 
-	if (!of_has_vicinity()) {
+	if (of_has_vicinity()) {
+		init_aff_fw_vicinity();
+	} else {
 		root = of_get_flat_dt_root();
 		if (of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
 			init_aff_QS20_harcoded();



More information about the cbe-oss-dev mailing list