while (!cpumask_empty(*cpu_mask)) { if (cpumask_subset(*cpu_mask, candidate_mask)) /* Found a range where we can insert the new cpu(s) */ break;
cpumask_shift_left(*cpu_mask, *cpu_mask, nthreads);
}
/* Record the newly used CPU ids for the associate node. */
cpumask_or(node_recorded_ids_map[assigned_node],
node_recorded_ids_map[assigned_node], cpu_mask);
/* *IfnodeissettoNUMA_NO_NODE,CPUidshavebereusedfrom *anothernode,removethemfromitsmask.
*/ if (node == NUMA_NO_NODE) {
cpu = cpumask_first(cpu_mask);
pr_warn("Reusing free CPU ids %d-%d from another node\n",
cpu, cpu + nthreads - 1);
for_each_online_node(node) { if (node == assigned_node) continue;
cpumask_andnot(node_recorded_ids_map[node],
node_recorded_ids_map[node],
cpu_mask);
}
}
intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", &len); if (!intserv) return;
nthreads = len / sizeof(u32);
cpu_maps_update_begin(); for (i = 0; i < nthreads; i++) {
thread = be32_to_cpu(intserv[i]);
for_each_present_cpu(cpu) { if (get_hard_smp_processor_id(cpu) != thread) continue;
BUG_ON(cpu_online(cpu));
set_cpu_present(cpu, false);
set_hard_smp_processor_id(cpu, -1);
update_numa_cpu_lookup_table(cpu, -1); break;
} if (cpu >= nr_cpu_ids)
printk(KERN_WARNING "Could not find cpu to remove " "with physical id 0x%x\n", thread);
}
cpu_maps_update_done();
}
staticint dlpar_offline_cpu(struct device_node *dn)
{ int rc = 0; unsignedint cpu; int len, nthreads, i; const __be32 *intserv;
u32 thread;
intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", &len); if (!intserv) return -EINVAL;
nthreads = len / sizeof(u32);
cpu_maps_update_begin(); for (i = 0; i < nthreads; i++) {
thread = be32_to_cpu(intserv[i]);
for_each_present_cpu(cpu) { if (get_hard_smp_processor_id(cpu) != thread) continue;
if (!cpu_online(cpu)) break;
/* *device_offline()willreturn-EBUSY(viacpu_down())ifthere *isonlyoneCPUleft.Checkitheretofailearlierandwitha *moreinformativeerrormessage,whilealsoretainingthe *cpu_add_remove_locktobesurethatnoCPUsarebeing *online/offlinedduringthischeck.
*/ if (num_online_cpus() == 1) {
pr_warn("Unable to remove last online CPU %pOFn\n", dn);
rc = -EBUSY; goto out_unlock;
}
cpu_maps_update_done();
rc = device_offline(get_cpu_device(cpu)); if (rc) goto out;
cpu_maps_update_begin(); break;
} if (cpu == num_possible_cpus()) {
pr_warn("Could not find cpu to offline with physical id 0x%x\n",
thread);
}
}
out_unlock:
cpu_maps_update_done();
out: return rc;
}
staticint dlpar_online_cpu(struct device_node *dn)
{ int rc = 0; unsignedint cpu; int len, nthreads, i; const __be32 *intserv;
u32 thread;
intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", &len); if (!intserv) return -EINVAL;
nthreads = len / sizeof(u32);
cpu_maps_update_begin(); for (i = 0; i < nthreads; i++) {
thread = be32_to_cpu(intserv[i]);
for_each_present_cpu(cpu) { if (get_hard_smp_processor_id(cpu) != thread) continue;
if (!topology_is_primary_thread(cpu)) { if (cpu_smt_control != CPU_SMT_ENABLED) break; if (!topology_smt_thread_allowed(cpu)) break;
}
break;
} if (cpu == num_possible_cpus())
printk(KERN_WARNING "Could not find cpu to online " "with physical id 0x%x\n", thread);
}
cpu_maps_update_done();
info = of_find_property(parent, "ibm,drc-info", NULL); if (!info) returnfalse;
value = of_prop_next_u32(info, NULL, &count);
/* First value of ibm,drc-info is number of drc-info records */ if (value)
value++; else returnfalse;
for (i = 0; i < count; i++) { if (of_read_drc_info_cell(&info, &value, &drc)) returnfalse;
if (strncmp(drc.drc_type, "CPU", 3)) break;
if (drc_index > drc.last_drc_index) continue;
index = drc.drc_index_start; for (j = 0; j < drc.num_sequential_elems; j++) { if (drc_index == index) returntrue;
index += drc.sequential_inc;
}
}
returnfalse;
}
staticbool valid_cpu_drc_index(struct device_node *parent, u32 drc_index)
{ bool found = false; int rc, index;
if (of_property_present(parent, "ibm,drc-info")) return drc_info_valid_index(parent, drc_index);
/* Note that the format of the ibm,drc-indexes array is *thenumberofentriesinthearrayfollowedbythearray *ofdrcvaluessowestartlookingatindex=1.
*/
index = 1; while (!found) {
u32 drc;
/* Processors can be added/removed only on LPAR */ if (firmware_has_feature(FW_FEATURE_LPAR)) {
for_each_node(node) { if (!alloc_cpumask_var_node(&node_recorded_ids_map[node],
GFP_KERNEL, node)) return -ENOMEM;
/* Record ids of CPU added at boot time */
cpumask_copy(node_recorded_ids_map[node],
cpumask_of_node(node));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.