summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorAndrew Morton <akpm@digeo.com>2003-05-12 09:12:07 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2003-05-12 09:12:07 -0700
commit41541461da07d58d3db0df5218c10ead64882d7a (patch)
tree21d4dab852b9aac7439682126cf6843371d83d51 /include
parentcab0e744beabc97ae4c7ca86379277a04f9665bd (diff)
[PATCH] fix for clusterd io_apics
From: Keith Mannthey <kmannth@us.ibm.com> The following is a patch to fix inconsistent use of the function set_ioapic_affinity. In the current kernel it is unclear as to weather the value being passed to the function is a cpu mask or valid apic id. In irq_affinity_write_proc the kernel passes on a cpu mask but the kirqd thread passes on logical apic ids. In flat apic mode this is not an issue because a cpu mask represents the apic value. However in clustered apic mode the cpu mask is very different from the logical apic id. This is an attempt to do the right thing for clustered apics. I clarify that the value being passed to set_ioapic_affinity is a cpu mask not a apicid. Set_ioapic_affinity will do the conversion to logical apic ids. Since many cpu masks don't map to valid apicids in clustered apic mode TARGET_CPUS is used as a default value when such a situation occurs. I think this is a good step in making irq_affinity clustered apic safe.
Diffstat (limited to 'include')
-rw-r--r--include/asm-i386/mach-bigsmp/mach_apic.h37
-rw-r--r--include/asm-i386/mach-default/mach_apic.h5
-rw-r--r--include/asm-i386/mach-numaq/mach_apic.h34
-rw-r--r--include/asm-i386/mach-summit/mach_apic.h37
-rw-r--r--include/asm-i386/mach-visws/mach_apic.h4
5 files changed, 115 insertions, 2 deletions
diff --git a/include/asm-i386/mach-bigsmp/mach_apic.h b/include/asm-i386/mach-bigsmp/mach_apic.h
index 93972fcd768f..7b6435b052f3 100644
--- a/include/asm-i386/mach-bigsmp/mach_apic.h
+++ b/include/asm-i386/mach-bigsmp/mach_apic.h
@@ -34,10 +34,12 @@ static inline unsigned long check_apicid_used(unsigned long bitmap, int apicid)
return 0;
}
static inline unsigned long check_apicid_present(int bit)
-{
+{
return (phys_cpu_present_map & (1 << bit));
}
+#define apicid_cluster(apicid) (apicid & 0xF0)
+
static inline unsigned long calculate_ldr(unsigned long old)
{
unsigned long id;
@@ -134,4 +136,37 @@ static inline unsigned get_apic_id(unsigned long x)
#define GET_APIC_ID(x) get_apic_id(x)
+static inline unsigned int cpu_mask_to_apicid (unsigned long cpumask)
+{
+ int num_bits_set;
+ int cpus_found = 0;
+ int cpu;
+ int apicid;
+
+ num_bits_set = hweight32(cpumask);
+ /* Return id to all */
+ if (num_bits_set == 32)
+ return (int) 0xFF;
+ /*
+ * The cpus in the mask must all be on the apic cluster. If are not
+ * on the same apicid cluster return default value of TARGET_CPUS.
+ */
+ cpu = ffs(cpumask)-1;
+ apicid = cpu_to_logical_apicid(cpu);
+ while (cpus_found < num_bits_set) {
+ if (cpumask & (1 << cpu)) {
+ int new_apicid = cpu_to_logical_apicid(cpu);
+ if (apicid_cluster(apicid) !=
+ apicid_cluster(new_apicid)){
+ printk ("%s: Not a valid mask!\n",__FUNCTION__);
+ return TARGET_CPUS;
+ }
+ apicid = apicid | new_apicid;
+ cpus_found++;
+ }
+ cpu++;
+ }
+ return apicid;
+}
+
#endif /* __ASM_MACH_APIC_H */
diff --git a/include/asm-i386/mach-default/mach_apic.h b/include/asm-i386/mach-default/mach_apic.h
index e865f01f5167..ad40d96b3824 100644
--- a/include/asm-i386/mach-default/mach_apic.h
+++ b/include/asm-i386/mach-default/mach_apic.h
@@ -120,4 +120,9 @@ static inline int apic_id_registered(void)
&phys_cpu_present_map));
}
+static inline unsigned int cpu_mask_to_apicid (unsigned long cpumask)
+{
+ return cpumask;
+}
+
#endif /* __ASM_MACH_APIC_H */
diff --git a/include/asm-i386/mach-numaq/mach_apic.h b/include/asm-i386/mach-numaq/mach_apic.h
index 54a7c97fe8d1..d5160168908a 100644
--- a/include/asm-i386/mach-numaq/mach_apic.h
+++ b/include/asm-i386/mach-numaq/mach_apic.h
@@ -17,6 +17,7 @@
#define APIC_BROADCAST_ID 0x0F
#define check_apicid_used(bitmap, apicid) ((bitmap) & (1 << (apicid)))
#define check_apicid_present(bit) (phys_cpu_present_map & (1 << bit))
+#define apicid_cluster(apicid) (apicid & 0xF0)
static inline int apic_id_registered(void)
{
@@ -115,4 +116,37 @@ static inline unsigned get_apic_id(unsigned long x)
#define GET_APIC_ID(x) get_apic_id(x)
+static inline unsigned int cpu_mask_to_apicid (unsigned long cpumask)
+{
+ int num_bits_set;
+ int cpus_found = 0;
+ int cpu;
+ int apicid;
+
+ num_bits_set = hweight32(cpumask);
+ /* Return id to all */
+ if (num_bits_set == 32)
+ return (int) 0xFF;
+ /*
+ * The cpus in the mask must all be on the apic cluster. If are not
+ * on the same apicid cluster return default value of TARGET_CPUS.
+ */
+ cpu = ffs(cpumask)-1;
+ apicid = cpu_to_logical_apicid(cpu);
+ while (cpus_found < num_bits_set) {
+ if (cpumask & (1 << cpu)) {
+ int new_apicid = cpu_to_logical_apicid(cpu);
+ if (apicid_cluster(apicid) !=
+ apicid_cluster(new_apicid)){
+ printk ("%s: Not a valid mask!\n",__FUNCTION__);
+ return TARGET_CPUS;
+ }
+ apicid = apicid | new_apicid;
+ cpus_found++;
+ }
+ cpu++;
+ }
+ return apicid;
+}
+
#endif /* __ASM_MACH_APIC_H */
diff --git a/include/asm-i386/mach-summit/mach_apic.h b/include/asm-i386/mach-summit/mach_apic.h
index ae58d629c9ba..93207f09d43b 100644
--- a/include/asm-i386/mach-summit/mach_apic.h
+++ b/include/asm-i386/mach-summit/mach_apic.h
@@ -34,7 +34,7 @@ static inline unsigned long target_cpus(void)
#define APIC_BROADCAST_ID (0x0F)
static inline unsigned long check_apicid_used(unsigned long bitmap, int apicid)
-{
+{
return (x86_summit ? 0 : (bitmap & (1 << apicid)));
}
@@ -44,6 +44,8 @@ static inline unsigned long check_apicid_present(int bit)
return (x86_summit ? 1 : (phys_cpu_present_map & (1 << bit)));
}
+#define apicid_cluster(apicid) (apicid & 0xF0)
+
extern u8 bios_cpu_apicid[];
static inline void init_apic_ldr(void)
@@ -142,4 +144,37 @@ static inline unsigned get_apic_id(unsigned long x)
#define GET_APIC_ID(x) get_apic_id(x)
+static inline unsigned int cpu_mask_to_apicid (unsigned long cpumask)
+{
+ int num_bits_set;
+ int cpus_found = 0;
+ int cpu;
+ int apicid;
+
+ num_bits_set = hweight32(cpumask);
+ /* Return id to all */
+ if (num_bits_set == 32)
+ return (int) 0xFF;
+ /*
+ * The cpus in the mask must all be on the apic cluster. If are not
+ * on the same apicid cluster return default value of TARGET_CPUS.
+ */
+ cpu = ffs(cpumask)-1;
+ apicid = cpu_to_logical_apicid(cpu);
+ while (cpus_found < num_bits_set) {
+ if (cpumask & (1 << cpu)) {
+ int new_apicid = cpu_to_logical_apicid(cpu);
+ if (apicid_cluster(apicid) !=
+ apicid_cluster(new_apicid)){
+ printk ("%s: Not a valid mask!\n",__FUNCTION__);
+ return TARGET_CPUS;
+ }
+ apicid = apicid | new_apicid;
+ cpus_found++;
+ }
+ cpu++;
+ }
+ return apicid;
+}
+
#endif /* __ASM_MACH_APIC_H */
diff --git a/include/asm-i386/mach-visws/mach_apic.h b/include/asm-i386/mach-visws/mach_apic.h
index 84047e09ce2b..641c173d4f76 100644
--- a/include/asm-i386/mach-visws/mach_apic.h
+++ b/include/asm-i386/mach-visws/mach_apic.h
@@ -77,4 +77,8 @@ static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
return test_bit(boot_cpu_physical_apicid, &phys_cpu_present_map);
}
+static inline unsigned int cpu_mask_to_apicid (unsigned long cpumask)
+{
+ return cpumask;
+}
#endif /* __ASM_MACH_APIC_H */