diff options
Diffstat (limited to 'arch/ia64')
| -rw-r--r-- | arch/ia64/kernel/entry.S | 1 | ||||
| -rw-r--r-- | arch/ia64/kernel/gate.lds.S | 1 | ||||
| -rw-r--r-- | arch/ia64/kernel/iosapic.c | 265 | ||||
| -rw-r--r-- | arch/ia64/kernel/palinfo.c | 8 | ||||
| -rw-r--r-- | arch/ia64/kernel/time.c | 2 | ||||
| -rw-r--r-- | arch/ia64/kernel/topology.c | 367 | ||||
| -rw-r--r-- | arch/ia64/kernel/vmlinux.lds.S | 18 | ||||
| -rw-r--r-- | arch/ia64/mm/init.c | 8 | ||||
| -rw-r--r-- | arch/ia64/mm/ioremap.c | 6 | ||||
| -rw-r--r-- | arch/ia64/mm/tlb.c | 12 | ||||
| -rw-r--r-- | arch/ia64/sn/kernel/sn2/sn_hwperf.c | 8 |
11 files changed, 568 insertions, 128 deletions
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 0e3eda99e549..750e8e7fbdc3 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S | |||
| @@ -1605,5 +1605,6 @@ sys_call_table: | |||
| 1605 | data8 sys_ni_syscall // reserved for pselect | 1605 | data8 sys_ni_syscall // reserved for pselect |
| 1606 | data8 sys_ni_syscall // 1295 reserved for ppoll | 1606 | data8 sys_ni_syscall // 1295 reserved for ppoll |
| 1607 | data8 sys_unshare | 1607 | data8 sys_unshare |
| 1608 | data8 sys_splice | ||
| 1608 | 1609 | ||
| 1609 | .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls | 1610 | .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls |
diff --git a/arch/ia64/kernel/gate.lds.S b/arch/ia64/kernel/gate.lds.S index e1e4aba9ecd0..7c99e6ec3daf 100644 --- a/arch/ia64/kernel/gate.lds.S +++ b/arch/ia64/kernel/gate.lds.S | |||
| @@ -59,6 +59,7 @@ SECTIONS | |||
| 59 | *(.dynbss) | 59 | *(.dynbss) |
| 60 | *(.bss .bss.* .gnu.linkonce.b.*) | 60 | *(.bss .bss.* .gnu.linkonce.b.*) |
| 61 | *(__ex_table) | 61 | *(__ex_table) |
| 62 | *(__mca_table) | ||
| 62 | } | 63 | } |
| 63 | } | 64 | } |
| 64 | 65 | ||
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 8832c553230a..7956eb9058fc 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c | |||
| @@ -9,54 +9,65 @@ | |||
| 9 | * Copyright (C) 1999 VA Linux Systems | 9 | * Copyright (C) 1999 VA Linux Systems |
| 10 | * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com> | 10 | * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com> |
| 11 | * | 11 | * |
| 12 | * 00/04/19 D. Mosberger Rewritten to mirror more closely the x86 I/O APIC code. | 12 | * 00/04/19 D. Mosberger Rewritten to mirror more closely the x86 I/O |
| 13 | * In particular, we now have separate handlers for edge | 13 | * APIC code. In particular, we now have separate |
| 14 | * and level triggered interrupts. | 14 | * handlers for edge and level triggered |
| 15 | * 00/10/27 Asit Mallick, Goutham Rao <goutham.rao@intel.com> IRQ vector allocation | 15 | * interrupts. |
| 16 | * PCI to vector mapping, shared PCI interrupts. | 16 | * 00/10/27 Asit Mallick, Goutham Rao <goutham.rao@intel.com> IRQ vector |
| 17 | * 00/10/27 D. Mosberger Document things a bit more to make them more understandable. | 17 | * allocation PCI to vector mapping, shared PCI |
| 18 | * Clean up much of the old IOSAPIC cruft. | 18 | * interrupts. |
| 19 | * 01/07/27 J.I. Lee PCI irq routing, Platform/Legacy interrupts and fixes for | 19 | * 00/10/27 D. Mosberger Document things a bit more to make them more |
| 20 | * ACPI S5(SoftOff) support. | 20 | * understandable. Clean up much of the old |
| 21 | * IOSAPIC cruft. | ||
| 22 | * 01/07/27 J.I. Lee PCI irq routing, Platform/Legacy interrupts | ||
| 23 | * and fixes for ACPI S5(SoftOff) support. | ||
| 21 | * 02/01/23 J.I. Lee iosapic pgm fixes for PCI irq routing from _PRT | 24 | * 02/01/23 J.I. Lee iosapic pgm fixes for PCI irq routing from _PRT |
| 22 | * 02/01/07 E. Focht <efocht@ess.nec.de> Redirectable interrupt vectors in | 25 | * 02/01/07 E. Focht <efocht@ess.nec.de> Redirectable interrupt |
| 23 | * iosapic_set_affinity(), initializations for | 26 | * vectors in iosapic_set_affinity(), |
| 24 | * /proc/irq/#/smp_affinity | 27 | * initializations for /proc/irq/#/smp_affinity |
| 25 | * 02/04/02 P. Diefenbaugh Cleaned up ACPI PCI IRQ routing. | 28 | * 02/04/02 P. Diefenbaugh Cleaned up ACPI PCI IRQ routing. |
| 26 | * 02/04/18 J.I. Lee bug fix in iosapic_init_pci_irq | 29 | * 02/04/18 J.I. Lee bug fix in iosapic_init_pci_irq |
| 27 | * 02/04/30 J.I. Lee bug fix in find_iosapic to fix ACPI PCI IRQ to IOSAPIC mapping | 30 | * 02/04/30 J.I. Lee bug fix in find_iosapic to fix ACPI PCI IRQ to |
| 28 | * error | 31 | * IOSAPIC mapping error |
| 29 | * 02/07/29 T. Kochi Allocate interrupt vectors dynamically | 32 | * 02/07/29 T. Kochi Allocate interrupt vectors dynamically |
| 30 | * 02/08/04 T. Kochi Cleaned up terminology (irq, global system interrupt, vector, etc.) | 33 | * 02/08/04 T. Kochi Cleaned up terminology (irq, global system |
| 31 | * 02/09/20 D. Mosberger Simplified by taking advantage of ACPI's pci_irq code. | 34 | * interrupt, vector, etc.) |
| 35 | * 02/09/20 D. Mosberger Simplified by taking advantage of ACPI's | ||
| 36 | * pci_irq code. | ||
| 32 | * 03/02/19 B. Helgaas Make pcat_compat system-wide, not per-IOSAPIC. | 37 | * 03/02/19 B. Helgaas Make pcat_compat system-wide, not per-IOSAPIC. |
| 33 | * Remove iosapic_address & gsi_base from external interfaces. | 38 | * Remove iosapic_address & gsi_base from |
| 34 | * Rationalize __init/__devinit attributes. | 39 | * external interfaces. Rationalize |
| 40 | * __init/__devinit attributes. | ||
| 35 | * 04/12/04 Ashok Raj <ashok.raj@intel.com> Intel Corporation 2004 | 41 | * 04/12/04 Ashok Raj <ashok.raj@intel.com> Intel Corporation 2004 |
| 36 | * Updated to work with irq migration necessary for CPU Hotplug | 42 | * Updated to work with irq migration necessary |
| 43 | * for CPU Hotplug | ||
| 37 | */ | 44 | */ |
| 38 | /* | 45 | /* |
| 39 | * Here is what the interrupt logic between a PCI device and the kernel looks like: | 46 | * Here is what the interrupt logic between a PCI device and the kernel looks |
| 47 | * like: | ||
| 40 | * | 48 | * |
| 41 | * (1) A PCI device raises one of the four interrupt pins (INTA, INTB, INTC, INTD). The | 49 | * (1) A PCI device raises one of the four interrupt pins (INTA, INTB, INTC, |
| 42 | * device is uniquely identified by its bus--, and slot-number (the function | 50 | * INTD). The device is uniquely identified by its bus-, and slot-number |
| 43 | * number does not matter here because all functions share the same interrupt | 51 | * (the function number does not matter here because all functions share |
| 44 | * lines). | 52 | * the same interrupt lines). |
| 45 | * | 53 | * |
| 46 | * (2) The motherboard routes the interrupt line to a pin on a IOSAPIC controller. | 54 | * (2) The motherboard routes the interrupt line to a pin on a IOSAPIC |
| 47 | * Multiple interrupt lines may have to share the same IOSAPIC pin (if they're level | 55 | * controller. Multiple interrupt lines may have to share the same |
| 48 | * triggered and use the same polarity). Each interrupt line has a unique Global | 56 | * IOSAPIC pin (if they're level triggered and use the same polarity). |
| 49 | * System Interrupt (GSI) number which can be calculated as the sum of the controller's | 57 | * Each interrupt line has a unique Global System Interrupt (GSI) number |
| 50 | * base GSI number and the IOSAPIC pin number to which the line connects. | 58 | * which can be calculated as the sum of the controller's base GSI number |
| 59 | * and the IOSAPIC pin number to which the line connects. | ||
| 51 | * | 60 | * |
| 52 | * (3) The IOSAPIC uses an internal routing table entries (RTEs) to map the IOSAPIC pin | 61 | * (3) The IOSAPIC uses an internal routing table entries (RTEs) to map the |
| 53 | * into the IA-64 interrupt vector. This interrupt vector is then sent to the CPU. | 62 | * IOSAPIC pin into the IA-64 interrupt vector. This interrupt vector is then |
| 63 | * sent to the CPU. | ||
| 54 | * | 64 | * |
| 55 | * (4) The kernel recognizes an interrupt as an IRQ. The IRQ interface is used as | 65 | * (4) The kernel recognizes an interrupt as an IRQ. The IRQ interface is |
| 56 | * architecture-independent interrupt handling mechanism in Linux. As an | 66 | * used as architecture-independent interrupt handling mechanism in Linux. |
| 57 | * IRQ is a number, we have to have IA-64 interrupt vector number <-> IRQ number | 67 | * As an IRQ is a number, we have to have |
| 58 | * mapping. On smaller systems, we use one-to-one mapping between IA-64 vector and | 68 | * IA-64 interrupt vector number <-> IRQ number mapping. On smaller |
| 59 | * IRQ. A platform can implement platform_irq_to_vector(irq) and | 69 | * systems, we use one-to-one mapping between IA-64 vector and IRQ. A |
| 70 | * platform can implement platform_irq_to_vector(irq) and | ||
| 60 | * platform_local_vector_to_irq(vector) APIs to differentiate the mapping. | 71 | * platform_local_vector_to_irq(vector) APIs to differentiate the mapping. |
| 61 | * Please see also include/asm-ia64/hw_irq.h for those APIs. | 72 | * Please see also include/asm-ia64/hw_irq.h for those APIs. |
| 62 | * | 73 | * |
| @@ -64,9 +75,9 @@ | |||
| 64 | * | 75 | * |
| 65 | * PCI pin -> global system interrupt (GSI) -> IA-64 vector <-> IRQ | 76 | * PCI pin -> global system interrupt (GSI) -> IA-64 vector <-> IRQ |
| 66 | * | 77 | * |
| 67 | * Note: The term "IRQ" is loosely used everywhere in Linux kernel to describe interrupts. | 78 | * Note: The term "IRQ" is loosely used everywhere in Linux kernel to |
| 68 | * Now we use "IRQ" only for Linux IRQ's. ISA IRQ (isa_irq) is the only exception in this | 79 | * describeinterrupts. Now we use "IRQ" only for Linux IRQ's. ISA IRQ |
| 69 | * source code. | 80 | * (isa_irq) is the only exception in this source code. |
| 70 | */ | 81 | */ |
| 71 | #include <linux/config.h> | 82 | #include <linux/config.h> |
| 72 | 83 | ||
| @@ -90,7 +101,6 @@ | |||
| 90 | #include <asm/ptrace.h> | 101 | #include <asm/ptrace.h> |
| 91 | #include <asm/system.h> | 102 | #include <asm/system.h> |
| 92 | 103 | ||
| 93 | |||
| 94 | #undef DEBUG_INTERRUPT_ROUTING | 104 | #undef DEBUG_INTERRUPT_ROUTING |
| 95 | 105 | ||
| 96 | #ifdef DEBUG_INTERRUPT_ROUTING | 106 | #ifdef DEBUG_INTERRUPT_ROUTING |
| @@ -99,36 +109,46 @@ | |||
| 99 | #define DBG(fmt...) | 109 | #define DBG(fmt...) |
| 100 | #endif | 110 | #endif |
| 101 | 111 | ||
| 102 | #define NR_PREALLOCATE_RTE_ENTRIES (PAGE_SIZE / sizeof(struct iosapic_rte_info)) | 112 | #define NR_PREALLOCATE_RTE_ENTRIES \ |
| 113 | (PAGE_SIZE / sizeof(struct iosapic_rte_info)) | ||
| 103 | #define RTE_PREALLOCATED (1) | 114 | #define RTE_PREALLOCATED (1) |
| 104 | 115 | ||
| 105 | static DEFINE_SPINLOCK(iosapic_lock); | 116 | static DEFINE_SPINLOCK(iosapic_lock); |
| 106 | 117 | ||
| 107 | /* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */ | 118 | /* |
| 119 | * These tables map IA-64 vectors to the IOSAPIC pin that generates this | ||
| 120 | * vector. | ||
| 121 | */ | ||
| 108 | 122 | ||
| 109 | struct iosapic_rte_info { | 123 | struct iosapic_rte_info { |
| 110 | struct list_head rte_list; /* node in list of RTEs sharing the same vector */ | 124 | struct list_head rte_list; /* node in list of RTEs sharing the |
| 125 | * same vector */ | ||
| 111 | char __iomem *addr; /* base address of IOSAPIC */ | 126 | char __iomem *addr; /* base address of IOSAPIC */ |
| 112 | unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ | 127 | unsigned int gsi_base; /* first GSI assigned to this |
| 128 | * IOSAPIC */ | ||
| 113 | char rte_index; /* IOSAPIC RTE index */ | 129 | char rte_index; /* IOSAPIC RTE index */ |
| 114 | int refcnt; /* reference counter */ | 130 | int refcnt; /* reference counter */ |
| 115 | unsigned int flags; /* flags */ | 131 | unsigned int flags; /* flags */ |
| 116 | } ____cacheline_aligned; | 132 | } ____cacheline_aligned; |
| 117 | 133 | ||
| 118 | static struct iosapic_intr_info { | 134 | static struct iosapic_intr_info { |
| 119 | struct list_head rtes; /* RTEs using this vector (empty => not an IOSAPIC interrupt) */ | 135 | struct list_head rtes; /* RTEs using this vector (empty => |
| 136 | * not an IOSAPIC interrupt) */ | ||
| 120 | int count; /* # of RTEs that shares this vector */ | 137 | int count; /* # of RTEs that shares this vector */ |
| 121 | u32 low32; /* current value of low word of Redirection table entry */ | 138 | u32 low32; /* current value of low word of |
| 139 | * Redirection table entry */ | ||
| 122 | unsigned int dest; /* destination CPU physical ID */ | 140 | unsigned int dest; /* destination CPU physical ID */ |
| 123 | unsigned char dmode : 3; /* delivery mode (see iosapic.h) */ | 141 | unsigned char dmode : 3; /* delivery mode (see iosapic.h) */ |
| 124 | unsigned char polarity: 1; /* interrupt polarity (see iosapic.h) */ | 142 | unsigned char polarity: 1; /* interrupt polarity |
| 143 | * (see iosapic.h) */ | ||
| 125 | unsigned char trigger : 1; /* trigger mode (see iosapic.h) */ | 144 | unsigned char trigger : 1; /* trigger mode (see iosapic.h) */ |
| 126 | } iosapic_intr_info[IA64_NUM_VECTORS]; | 145 | } iosapic_intr_info[IA64_NUM_VECTORS]; |
| 127 | 146 | ||
| 128 | static struct iosapic { | 147 | static struct iosapic { |
| 129 | char __iomem *addr; /* base address of IOSAPIC */ | 148 | char __iomem *addr; /* base address of IOSAPIC */ |
| 130 | unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ | 149 | unsigned int gsi_base; /* first GSI assigned to this |
| 131 | unsigned short num_rte; /* number of RTE in this IOSAPIC */ | 150 | * IOSAPIC */ |
| 151 | unsigned short num_rte; /* # of RTEs on this IOSAPIC */ | ||
| 132 | int rtes_inuse; /* # of RTEs in use on this IOSAPIC */ | 152 | int rtes_inuse; /* # of RTEs in use on this IOSAPIC */ |
| 133 | #ifdef CONFIG_NUMA | 153 | #ifdef CONFIG_NUMA |
| 134 | unsigned short node; /* numa node association via pxm */ | 154 | unsigned short node; /* numa node association via pxm */ |
| @@ -149,7 +169,8 @@ find_iosapic (unsigned int gsi) | |||
| 149 | int i; | 169 | int i; |
| 150 | 170 | ||
| 151 | for (i = 0; i < NR_IOSAPICS; i++) { | 171 | for (i = 0; i < NR_IOSAPICS; i++) { |
| 152 | if ((unsigned) (gsi - iosapic_lists[i].gsi_base) < iosapic_lists[i].num_rte) | 172 | if ((unsigned) (gsi - iosapic_lists[i].gsi_base) < |
| 173 | iosapic_lists[i].num_rte) | ||
| 153 | return i; | 174 | return i; |
| 154 | } | 175 | } |
| 155 | 176 | ||
| @@ -162,7 +183,8 @@ _gsi_to_vector (unsigned int gsi) | |||
| 162 | struct iosapic_intr_info *info; | 183 | struct iosapic_intr_info *info; |
| 163 | struct iosapic_rte_info *rte; | 184 | struct iosapic_rte_info *rte; |
| 164 | 185 | ||
| 165 | for (info = iosapic_intr_info; info < iosapic_intr_info + IA64_NUM_VECTORS; ++info) | 186 | for (info = iosapic_intr_info; info < |
| 187 | iosapic_intr_info + IA64_NUM_VECTORS; ++info) | ||
| 166 | list_for_each_entry(rte, &info->rtes, rte_list) | 188 | list_for_each_entry(rte, &info->rtes, rte_list) |
| 167 | if (rte->gsi_base + rte->rte_index == gsi) | 189 | if (rte->gsi_base + rte->rte_index == gsi) |
| 168 | return info - iosapic_intr_info; | 190 | return info - iosapic_intr_info; |
| @@ -185,8 +207,8 @@ gsi_to_irq (unsigned int gsi) | |||
| 185 | unsigned long flags; | 207 | unsigned long flags; |
| 186 | int irq; | 208 | int irq; |
| 187 | /* | 209 | /* |
| 188 | * XXX fix me: this assumes an identity mapping vetween IA-64 vector and Linux irq | 210 | * XXX fix me: this assumes an identity mapping between IA-64 vector |
| 189 | * numbers... | 211 | * and Linux irq numbers... |
| 190 | */ | 212 | */ |
| 191 | spin_lock_irqsave(&iosapic_lock, flags); | 213 | spin_lock_irqsave(&iosapic_lock, flags); |
| 192 | { | 214 | { |
| @@ -197,7 +219,8 @@ gsi_to_irq (unsigned int gsi) | |||
| 197 | return irq; | 219 | return irq; |
| 198 | } | 220 | } |
| 199 | 221 | ||
| 200 | static struct iosapic_rte_info *gsi_vector_to_rte(unsigned int gsi, unsigned int vec) | 222 | static struct iosapic_rte_info *gsi_vector_to_rte(unsigned int gsi, |
| 223 | unsigned int vec) | ||
| 201 | { | 224 | { |
| 202 | struct iosapic_rte_info *rte; | 225 | struct iosapic_rte_info *rte; |
| 203 | 226 | ||
| @@ -237,7 +260,9 @@ set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask) | |||
| 237 | 260 | ||
| 238 | for (irq = 0; irq < NR_IRQS; ++irq) | 261 | for (irq = 0; irq < NR_IRQS; ++irq) |
| 239 | if (irq_to_vector(irq) == vector) { | 262 | if (irq_to_vector(irq) == vector) { |
| 240 | set_irq_affinity_info(irq, (int)(dest & 0xffff), redir); | 263 | set_irq_affinity_info(irq, |
| 264 | (int)(dest & 0xffff), | ||
| 265 | redir); | ||
| 241 | break; | 266 | break; |
| 242 | } | 267 | } |
| 243 | } | 268 | } |
| @@ -259,7 +284,7 @@ set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask) | |||
| 259 | } | 284 | } |
| 260 | 285 | ||
| 261 | static void | 286 | static void |
| 262 | nop (unsigned int vector) | 287 | nop (unsigned int irq) |
| 263 | { | 288 | { |
| 264 | /* do nothing... */ | 289 | /* do nothing... */ |
| 265 | } | 290 | } |
| @@ -281,7 +306,8 @@ mask_irq (unsigned int irq) | |||
| 281 | { | 306 | { |
| 282 | /* set only the mask bit */ | 307 | /* set only the mask bit */ |
| 283 | low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK; | 308 | low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK; |
| 284 | list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { | 309 | list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, |
| 310 | rte_list) { | ||
| 285 | addr = rte->addr; | 311 | addr = rte->addr; |
| 286 | rte_index = rte->rte_index; | 312 | rte_index = rte->rte_index; |
| 287 | iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); | 313 | iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); |
| @@ -306,7 +332,8 @@ unmask_irq (unsigned int irq) | |||
| 306 | spin_lock_irqsave(&iosapic_lock, flags); | 332 | spin_lock_irqsave(&iosapic_lock, flags); |
| 307 | { | 333 | { |
| 308 | low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK; | 334 | low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK; |
| 309 | list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { | 335 | list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, |
| 336 | rte_list) { | ||
| 310 | addr = rte->addr; | 337 | addr = rte->addr; |
| 311 | rte_index = rte->rte_index; | 338 | rte_index = rte->rte_index; |
| 312 | iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); | 339 | iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); |
| @@ -346,21 +373,25 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) | |||
| 346 | 373 | ||
| 347 | spin_lock_irqsave(&iosapic_lock, flags); | 374 | spin_lock_irqsave(&iosapic_lock, flags); |
| 348 | { | 375 | { |
| 349 | low32 = iosapic_intr_info[vec].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT); | 376 | low32 = iosapic_intr_info[vec].low32 & |
| 377 | ~(7 << IOSAPIC_DELIVERY_SHIFT); | ||
| 350 | 378 | ||
| 351 | if (redir) | 379 | if (redir) |
| 352 | /* change delivery mode to lowest priority */ | 380 | /* change delivery mode to lowest priority */ |
| 353 | low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT); | 381 | low32 |= (IOSAPIC_LOWEST_PRIORITY << |
| 382 | IOSAPIC_DELIVERY_SHIFT); | ||
| 354 | else | 383 | else |
| 355 | /* change delivery mode to fixed */ | 384 | /* change delivery mode to fixed */ |
| 356 | low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT); | 385 | low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT); |
| 357 | 386 | ||
| 358 | iosapic_intr_info[vec].low32 = low32; | 387 | iosapic_intr_info[vec].low32 = low32; |
| 359 | iosapic_intr_info[vec].dest = dest; | 388 | iosapic_intr_info[vec].dest = dest; |
| 360 | list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { | 389 | list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, |
| 390 | rte_list) { | ||
| 361 | addr = rte->addr; | 391 | addr = rte->addr; |
| 362 | rte_index = rte->rte_index; | 392 | rte_index = rte->rte_index; |
| 363 | iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32); | 393 | iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), |
| 394 | high32); | ||
| 364 | iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); | 395 | iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); |
| 365 | } | 396 | } |
| 366 | } | 397 | } |
| @@ -433,7 +464,8 @@ iosapic_ack_edge_irq (unsigned int irq) | |||
| 433 | * interrupt for real. This prevents IRQ storms from unhandled | 464 | * interrupt for real. This prevents IRQ storms from unhandled |
| 434 | * devices. | 465 | * devices. |
| 435 | */ | 466 | */ |
| 436 | if ((idesc->status & (IRQ_PENDING|IRQ_DISABLED)) == (IRQ_PENDING|IRQ_DISABLED)) | 467 | if ((idesc->status & (IRQ_PENDING|IRQ_DISABLED)) == |
| 468 | (IRQ_PENDING|IRQ_DISABLED)) | ||
| 437 | mask_irq(irq); | 469 | mask_irq(irq); |
| 438 | } | 470 | } |
| 439 | 471 | ||
| @@ -467,7 +499,8 @@ iosapic_version (char __iomem *addr) | |||
| 467 | return iosapic_read(addr, IOSAPIC_VERSION); | 499 | return iosapic_read(addr, IOSAPIC_VERSION); |
| 468 | } | 500 | } |
| 469 | 501 | ||
| 470 | static int iosapic_find_sharable_vector (unsigned long trigger, unsigned long pol) | 502 | static int iosapic_find_sharable_vector (unsigned long trigger, |
| 503 | unsigned long pol) | ||
| 471 | { | 504 | { |
| 472 | int i, vector = -1, min_count = -1; | 505 | int i, vector = -1, min_count = -1; |
| 473 | struct iosapic_intr_info *info; | 506 | struct iosapic_intr_info *info; |
| @@ -482,7 +515,8 @@ static int iosapic_find_sharable_vector (unsigned long trigger, unsigned long po | |||
| 482 | for (i = IA64_FIRST_DEVICE_VECTOR; i <= IA64_LAST_DEVICE_VECTOR; i++) { | 515 | for (i = IA64_FIRST_DEVICE_VECTOR; i <= IA64_LAST_DEVICE_VECTOR; i++) { |
| 483 | info = &iosapic_intr_info[i]; | 516 | info = &iosapic_intr_info[i]; |
| 484 | if (info->trigger == trigger && info->polarity == pol && | 517 | if (info->trigger == trigger && info->polarity == pol && |
| 485 | (info->dmode == IOSAPIC_FIXED || info->dmode == IOSAPIC_LOWEST_PRIORITY)) { | 518 | (info->dmode == IOSAPIC_FIXED || info->dmode == |
| 519 | IOSAPIC_LOWEST_PRIORITY)) { | ||
| 486 | if (min_count == -1 || info->count < min_count) { | 520 | if (min_count == -1 || info->count < min_count) { |
| 487 | vector = i; | 521 | vector = i; |
| 488 | min_count = info->count; | 522 | min_count = info->count; |
| @@ -506,12 +540,15 @@ iosapic_reassign_vector (int vector) | |||
| 506 | new_vector = assign_irq_vector(AUTO_ASSIGN); | 540 | new_vector = assign_irq_vector(AUTO_ASSIGN); |
| 507 | if (new_vector < 0) | 541 | if (new_vector < 0) |
| 508 | panic("%s: out of interrupt vectors!\n", __FUNCTION__); | 542 | panic("%s: out of interrupt vectors!\n", __FUNCTION__); |
| 509 | printk(KERN_INFO "Reassigning vector %d to %d\n", vector, new_vector); | 543 | printk(KERN_INFO "Reassigning vector %d to %d\n", |
| 544 | vector, new_vector); | ||
| 510 | memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector], | 545 | memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector], |
| 511 | sizeof(struct iosapic_intr_info)); | 546 | sizeof(struct iosapic_intr_info)); |
| 512 | INIT_LIST_HEAD(&iosapic_intr_info[new_vector].rtes); | 547 | INIT_LIST_HEAD(&iosapic_intr_info[new_vector].rtes); |
| 513 | list_move(iosapic_intr_info[vector].rtes.next, &iosapic_intr_info[new_vector].rtes); | 548 | list_move(iosapic_intr_info[vector].rtes.next, |
| 514 | memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info)); | 549 | &iosapic_intr_info[new_vector].rtes); |
| 550 | memset(&iosapic_intr_info[vector], 0, | ||
| 551 | sizeof(struct iosapic_intr_info)); | ||
| 515 | iosapic_intr_info[vector].low32 = IOSAPIC_MASK; | 552 | iosapic_intr_info[vector].low32 = IOSAPIC_MASK; |
| 516 | INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); | 553 | INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); |
| 517 | } | 554 | } |
| @@ -524,7 +561,8 @@ static struct iosapic_rte_info *iosapic_alloc_rte (void) | |||
| 524 | int preallocated = 0; | 561 | int preallocated = 0; |
| 525 | 562 | ||
| 526 | if (!iosapic_kmalloc_ok && list_empty(&free_rte_list)) { | 563 | if (!iosapic_kmalloc_ok && list_empty(&free_rte_list)) { |
| 527 | rte = alloc_bootmem(sizeof(struct iosapic_rte_info) * NR_PREALLOCATE_RTE_ENTRIES); | 564 | rte = alloc_bootmem(sizeof(struct iosapic_rte_info) * |
| 565 | NR_PREALLOCATE_RTE_ENTRIES); | ||
| 528 | if (!rte) | 566 | if (!rte) |
| 529 | return NULL; | 567 | return NULL; |
| 530 | for (i = 0; i < NR_PREALLOCATE_RTE_ENTRIES; i++, rte++) | 568 | for (i = 0; i < NR_PREALLOCATE_RTE_ENTRIES; i++, rte++) |
| @@ -532,7 +570,8 @@ static struct iosapic_rte_info *iosapic_alloc_rte (void) | |||
| 532 | } | 570 | } |
| 533 | 571 | ||
| 534 | if (!list_empty(&free_rte_list)) { | 572 | if (!list_empty(&free_rte_list)) { |
| 535 | rte = list_entry(free_rte_list.next, struct iosapic_rte_info, rte_list); | 573 | rte = list_entry(free_rte_list.next, struct iosapic_rte_info, |
| 574 | rte_list); | ||
| 536 | list_del(&rte->rte_list); | 575 | list_del(&rte->rte_list); |
| 537 | preallocated++; | 576 | preallocated++; |
| 538 | } else { | 577 | } else { |
| @@ -575,7 +614,8 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, | |||
| 575 | 614 | ||
| 576 | index = find_iosapic(gsi); | 615 | index = find_iosapic(gsi); |
| 577 | if (index < 0) { | 616 | if (index < 0) { |
| 578 | printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n", __FUNCTION__, gsi); | 617 | printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n", |
| 618 | __FUNCTION__, gsi); | ||
| 579 | return -ENODEV; | 619 | return -ENODEV; |
| 580 | } | 620 | } |
| 581 | 621 | ||
| @@ -586,7 +626,8 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, | |||
| 586 | if (!rte) { | 626 | if (!rte) { |
| 587 | rte = iosapic_alloc_rte(); | 627 | rte = iosapic_alloc_rte(); |
| 588 | if (!rte) { | 628 | if (!rte) { |
| 589 | printk(KERN_WARNING "%s: cannot allocate memory\n", __FUNCTION__); | 629 | printk(KERN_WARNING "%s: cannot allocate memory\n", |
| 630 | __FUNCTION__); | ||
| 590 | return -ENOMEM; | 631 | return -ENOMEM; |
| 591 | } | 632 | } |
| 592 | 633 | ||
| @@ -602,7 +643,9 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, | |||
| 602 | else if (vector_is_shared(vector)) { | 643 | else if (vector_is_shared(vector)) { |
| 603 | struct iosapic_intr_info *info = &iosapic_intr_info[vector]; | 644 | struct iosapic_intr_info *info = &iosapic_intr_info[vector]; |
| 604 | if (info->trigger != trigger || info->polarity != polarity) { | 645 | if (info->trigger != trigger || info->polarity != polarity) { |
| 605 | printk (KERN_WARNING "%s: cannot override the interrupt\n", __FUNCTION__); | 646 | printk (KERN_WARNING |
| 647 | "%s: cannot override the interrupt\n", | ||
| 648 | __FUNCTION__); | ||
| 606 | return -EINVAL; | 649 | return -EINVAL; |
| 607 | } | 650 | } |
| 608 | } | 651 | } |
| @@ -619,8 +662,10 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, | |||
| 619 | idesc = irq_descp(vector); | 662 | idesc = irq_descp(vector); |
| 620 | if (idesc->handler != irq_type) { | 663 | if (idesc->handler != irq_type) { |
| 621 | if (idesc->handler != &no_irq_type) | 664 | if (idesc->handler != &no_irq_type) |
| 622 | printk(KERN_WARNING "%s: changing vector %d from %s to %s\n", | 665 | printk(KERN_WARNING |
| 623 | __FUNCTION__, vector, idesc->handler->typename, irq_type->typename); | 666 | "%s: changing vector %d from %s to %s\n", |
| 667 | __FUNCTION__, vector, | ||
| 668 | idesc->handler->typename, irq_type->typename); | ||
| 624 | idesc->handler = irq_type; | 669 | idesc->handler = irq_type; |
| 625 | } | 670 | } |
| 626 | return 0; | 671 | return 0; |
| @@ -681,7 +726,7 @@ get_target_cpu (unsigned int gsi, int vector) | |||
| 681 | if (!num_cpus) | 726 | if (!num_cpus) |
| 682 | goto skip_numa_setup; | 727 | goto skip_numa_setup; |
| 683 | 728 | ||
| 684 | /* Use vector assigment to distribute across cpus in node */ | 729 | /* Use vector assignment to distribute across cpus in node */ |
| 685 | cpu_index = vector % num_cpus; | 730 | cpu_index = vector % num_cpus; |
| 686 | 731 | ||
| 687 | for (numa_cpu = first_cpu(cpu_mask) ; i < cpu_index ; i++) | 732 | for (numa_cpu = first_cpu(cpu_mask) ; i < cpu_index ; i++) |
| @@ -703,7 +748,7 @@ skip_numa_setup: | |||
| 703 | } while (!cpu_online(cpu)); | 748 | } while (!cpu_online(cpu)); |
| 704 | 749 | ||
| 705 | return cpu_physical_id(cpu); | 750 | return cpu_physical_id(cpu); |
| 706 | #else | 751 | #else /* CONFIG_SMP */ |
| 707 | return cpu_physical_id(smp_processor_id()); | 752 | return cpu_physical_id(smp_processor_id()); |
| 708 | #endif | 753 | #endif |
| 709 | } | 754 | } |
| @@ -755,7 +800,8 @@ again: | |||
| 755 | if (list_empty(&iosapic_intr_info[vector].rtes)) | 800 | if (list_empty(&iosapic_intr_info[vector].rtes)) |
| 756 | free_irq_vector(vector); | 801 | free_irq_vector(vector); |
| 757 | spin_unlock(&iosapic_lock); | 802 | spin_unlock(&iosapic_lock); |
| 758 | spin_unlock_irqrestore(&irq_descp(vector)->lock, flags); | 803 | spin_unlock_irqrestore(&irq_descp(vector)->lock, |
| 804 | flags); | ||
| 759 | goto again; | 805 | goto again; |
| 760 | } | 806 | } |
| 761 | 807 | ||
| @@ -764,7 +810,8 @@ again: | |||
| 764 | polarity, trigger); | 810 | polarity, trigger); |
| 765 | if (err < 0) { | 811 | if (err < 0) { |
| 766 | spin_unlock(&iosapic_lock); | 812 | spin_unlock(&iosapic_lock); |
| 767 | spin_unlock_irqrestore(&irq_descp(vector)->lock, flags); | 813 | spin_unlock_irqrestore(&irq_descp(vector)->lock, |
| 814 | flags); | ||
| 768 | return err; | 815 | return err; |
| 769 | } | 816 | } |
| 770 | 817 | ||
| @@ -806,7 +853,8 @@ iosapic_unregister_intr (unsigned int gsi) | |||
| 806 | */ | 853 | */ |
| 807 | irq = gsi_to_irq(gsi); | 854 | irq = gsi_to_irq(gsi); |
| 808 | if (irq < 0) { | 855 | if (irq < 0) { |
| 809 | printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi); | 856 | printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", |
| 857 | gsi); | ||
| 810 | WARN_ON(1); | 858 | WARN_ON(1); |
| 811 | return; | 859 | return; |
| 812 | } | 860 | } |
| @@ -817,7 +865,9 @@ iosapic_unregister_intr (unsigned int gsi) | |||
| 817 | spin_lock(&iosapic_lock); | 865 | spin_lock(&iosapic_lock); |
| 818 | { | 866 | { |
| 819 | if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) { | 867 | if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) { |
| 820 | printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi); | 868 | printk(KERN_ERR |
| 869 | "iosapic_unregister_intr(%u) unbalanced\n", | ||
| 870 | gsi); | ||
| 821 | WARN_ON(1); | 871 | WARN_ON(1); |
| 822 | goto out; | 872 | goto out; |
| 823 | } | 873 | } |
| @@ -827,7 +877,8 @@ iosapic_unregister_intr (unsigned int gsi) | |||
| 827 | 877 | ||
| 828 | /* Mask the interrupt */ | 878 | /* Mask the interrupt */ |
| 829 | low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK; | 879 | low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK; |
| 830 | iosapic_write(rte->addr, IOSAPIC_RTE_LOW(rte->rte_index), low32); | 880 | iosapic_write(rte->addr, IOSAPIC_RTE_LOW(rte->rte_index), |
| 881 | low32); | ||
| 831 | 882 | ||
| 832 | /* Remove the rte entry from the list */ | 883 | /* Remove the rte entry from the list */ |
| 833 | list_del(&rte->rte_list); | 884 | list_del(&rte->rte_list); |
| @@ -840,7 +891,9 @@ iosapic_unregister_intr (unsigned int gsi) | |||
| 840 | trigger = iosapic_intr_info[vector].trigger; | 891 | trigger = iosapic_intr_info[vector].trigger; |
| 841 | polarity = iosapic_intr_info[vector].polarity; | 892 | polarity = iosapic_intr_info[vector].polarity; |
| 842 | dest = iosapic_intr_info[vector].dest; | 893 | dest = iosapic_intr_info[vector].dest; |
| 843 | printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d unregistered\n", | 894 | printk(KERN_INFO |
| 895 | "GSI %u (%s, %s) -> CPU %d (0x%04x)" | ||
| 896 | " vector %d unregistered\n", | ||
| 844 | gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), | 897 | gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), |
| 845 | (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), | 898 | (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), |
| 846 | cpu_logical_id(dest), dest, vector); | 899 | cpu_logical_id(dest), dest, vector); |
| @@ -853,12 +906,15 @@ iosapic_unregister_intr (unsigned int gsi) | |||
| 853 | idesc->handler = &no_irq_type; | 906 | idesc->handler = &no_irq_type; |
| 854 | 907 | ||
| 855 | /* Clear the interrupt information */ | 908 | /* Clear the interrupt information */ |
| 856 | memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info)); | 909 | memset(&iosapic_intr_info[vector], 0, |
| 910 | sizeof(struct iosapic_intr_info)); | ||
| 857 | iosapic_intr_info[vector].low32 |= IOSAPIC_MASK; | 911 | iosapic_intr_info[vector].low32 |= IOSAPIC_MASK; |
| 858 | INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); | 912 | INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); |
| 859 | 913 | ||
| 860 | if (idesc->action) { | 914 | if (idesc->action) { |
| 861 | printk(KERN_ERR "interrupt handlers still exist on IRQ %u\n", irq); | 915 | printk(KERN_ERR |
| 916 | "interrupt handlers still exist on" | ||
| 917 | "IRQ %u\n", irq); | ||
| 862 | WARN_ON(1); | 918 | WARN_ON(1); |
| 863 | } | 919 | } |
| 864 | 920 | ||
| @@ -873,7 +929,6 @@ iosapic_unregister_intr (unsigned int gsi) | |||
| 873 | 929 | ||
| 874 | /* | 930 | /* |
| 875 | * ACPI calls this when it finds an entry for a platform interrupt. | 931 | * ACPI calls this when it finds an entry for a platform interrupt. |
| 876 | * Note that the irq_base and IOSAPIC address must be set in iosapic_init(). | ||
| 877 | */ | 932 | */ |
| 878 | int __init | 933 | int __init |
| 879 | iosapic_register_platform_intr (u32 int_type, unsigned int gsi, | 934 | iosapic_register_platform_intr (u32 int_type, unsigned int gsi, |
| @@ -907,13 +962,16 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, | |||
| 907 | mask = 1; | 962 | mask = 1; |
| 908 | break; | 963 | break; |
| 909 | default: | 964 | default: |
| 910 | printk(KERN_ERR "iosapic_register_platform_irq(): invalid int type 0x%x\n", int_type); | 965 | printk(KERN_ERR "%s: invalid int type 0x%x\n", __FUNCTION__, |
| 966 | int_type); | ||
| 911 | return -1; | 967 | return -1; |
| 912 | } | 968 | } |
| 913 | 969 | ||
| 914 | register_intr(gsi, vector, delivery, polarity, trigger); | 970 | register_intr(gsi, vector, delivery, polarity, trigger); |
| 915 | 971 | ||
| 916 | printk(KERN_INFO "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n", | 972 | printk(KERN_INFO |
| 973 | "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x)" | ||
| 974 | " vector %d\n", | ||
| 917 | int_type < ARRAY_SIZE(name) ? name[int_type] : "unknown", | 975 | int_type < ARRAY_SIZE(name) ? name[int_type] : "unknown", |
| 918 | int_type, gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), | 976 | int_type, gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), |
| 919 | (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), | 977 | (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), |
| @@ -923,10 +981,8 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, | |||
| 923 | return vector; | 981 | return vector; |
| 924 | } | 982 | } |
| 925 | 983 | ||
| 926 | |||
| 927 | /* | 984 | /* |
| 928 | * ACPI calls this when it finds an entry for a legacy ISA IRQ override. | 985 | * ACPI calls this when it finds an entry for a legacy ISA IRQ override. |
| 929 | * Note that the gsi_base and IOSAPIC address must be set in iosapic_init(). | ||
| 930 | */ | 986 | */ |
| 931 | void __init | 987 | void __init |
| 932 | iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, | 988 | iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, |
| @@ -955,16 +1011,19 @@ iosapic_system_init (int system_pcat_compat) | |||
| 955 | 1011 | ||
| 956 | for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) { | 1012 | for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) { |
| 957 | iosapic_intr_info[vector].low32 = IOSAPIC_MASK; | 1013 | iosapic_intr_info[vector].low32 = IOSAPIC_MASK; |
| 958 | INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); /* mark as unused */ | 1014 | /* mark as unused */ |
| 1015 | INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); | ||
| 959 | } | 1016 | } |
| 960 | 1017 | ||
| 961 | pcat_compat = system_pcat_compat; | 1018 | pcat_compat = system_pcat_compat; |
| 962 | if (pcat_compat) { | 1019 | if (pcat_compat) { |
| 963 | /* | 1020 | /* |
| 964 | * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support | 1021 | * Disable the compatibility mode interrupts (8259 style), |
| 965 | * enabled. | 1022 | * needs IN/OUT support enabled. |
| 966 | */ | 1023 | */ |
| 967 | printk(KERN_INFO "%s: Disabling PC-AT compatible 8259 interrupts\n", __FUNCTION__); | 1024 | printk(KERN_INFO |
| 1025 | "%s: Disabling PC-AT compatible 8259 interrupts\n", | ||
| 1026 | __FUNCTION__); | ||
| 968 | outb(0xff, 0xA1); | 1027 | outb(0xff, 0xA1); |
| 969 | outb(0xff, 0x21); | 1028 | outb(0xff, 0x21); |
| 970 | } | 1029 | } |
| @@ -1004,10 +1063,7 @@ iosapic_check_gsi_range (unsigned int gsi_base, unsigned int ver) | |||
| 1004 | base = iosapic_lists[index].gsi_base; | 1063 | base = iosapic_lists[index].gsi_base; |
| 1005 | end = base + iosapic_lists[index].num_rte - 1; | 1064 | end = base + iosapic_lists[index].num_rte - 1; |
| 1006 | 1065 | ||
| 1007 | if (gsi_base < base && gsi_end < base) | 1066 | if (gsi_end < base || end < gsi_base) |
| 1008 | continue;/* OK */ | ||
| 1009 | |||
| 1010 | if (gsi_base > end && gsi_end > end) | ||
| 1011 | continue; /* OK */ | 1067 | continue; /* OK */ |
| 1012 | 1068 | ||
| 1013 | return -EBUSY; | 1069 | return -EBUSY; |
| @@ -1053,12 +1109,14 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base) | |||
| 1053 | 1109 | ||
| 1054 | if ((gsi_base == 0) && pcat_compat) { | 1110 | if ((gsi_base == 0) && pcat_compat) { |
| 1055 | /* | 1111 | /* |
| 1056 | * Map the legacy ISA devices into the IOSAPIC data. Some of these may | 1112 | * Map the legacy ISA devices into the IOSAPIC data. Some of |
| 1057 | * get reprogrammed later on with data from the ACPI Interrupt Source | 1113 | * these may get reprogrammed later on with data from the ACPI |
| 1058 | * Override table. | 1114 | * Interrupt Source Override table. |
| 1059 | */ | 1115 | */ |
| 1060 | for (isa_irq = 0; isa_irq < 16; ++isa_irq) | 1116 | for (isa_irq = 0; isa_irq < 16; ++isa_irq) |
| 1061 | iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE); | 1117 | iosapic_override_isa_irq(isa_irq, isa_irq, |
| 1118 | IOSAPIC_POL_HIGH, | ||
| 1119 | IOSAPIC_EDGE); | ||
| 1062 | } | 1120 | } |
| 1063 | return 0; | 1121 | return 0; |
| 1064 | } | 1122 | } |
| @@ -1081,7 +1139,8 @@ iosapic_remove (unsigned int gsi_base) | |||
| 1081 | 1139 | ||
| 1082 | if (iosapic_lists[index].rtes_inuse) { | 1140 | if (iosapic_lists[index].rtes_inuse) { |
| 1083 | err = -EBUSY; | 1141 | err = -EBUSY; |
| 1084 | printk(KERN_WARNING "%s: IOSAPIC for GSI base %u is busy\n", | 1142 | printk(KERN_WARNING |
| 1143 | "%s: IOSAPIC for GSI base %u is busy\n", | ||
| 1085 | __FUNCTION__, gsi_base); | 1144 | __FUNCTION__, gsi_base); |
| 1086 | goto out; | 1145 | goto out; |
| 1087 | } | 1146 | } |
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c index 89faa603c6be..6386f63c413e 100644 --- a/arch/ia64/kernel/palinfo.c +++ b/arch/ia64/kernel/palinfo.c | |||
| @@ -240,7 +240,7 @@ cache_info(char *page) | |||
| 240 | } | 240 | } |
| 241 | p += sprintf(p, | 241 | p += sprintf(p, |
| 242 | "%s Cache level %lu:\n" | 242 | "%s Cache level %lu:\n" |
| 243 | "\tSize : %lu bytes\n" | 243 | "\tSize : %u bytes\n" |
| 244 | "\tAttributes : ", | 244 | "\tAttributes : ", |
| 245 | cache_types[j+cci.pcci_unified], i+1, | 245 | cache_types[j+cci.pcci_unified], i+1, |
| 246 | cci.pcci_cache_size); | 246 | cci.pcci_cache_size); |
| @@ -648,9 +648,9 @@ frequency_info(char *page) | |||
| 648 | if (ia64_pal_freq_ratios(&proc, &bus, &itc) != 0) return 0; | 648 | if (ia64_pal_freq_ratios(&proc, &bus, &itc) != 0) return 0; |
| 649 | 649 | ||
| 650 | p += sprintf(p, | 650 | p += sprintf(p, |
| 651 | "Processor/Clock ratio : %ld/%ld\n" | 651 | "Processor/Clock ratio : %d/%d\n" |
| 652 | "Bus/Clock ratio : %ld/%ld\n" | 652 | "Bus/Clock ratio : %d/%d\n" |
| 653 | "ITC/Clock ratio : %ld/%ld\n", | 653 | "ITC/Clock ratio : %d/%d\n", |
| 654 | proc.num, proc.den, bus.num, bus.den, itc.num, itc.den); | 654 | proc.num, proc.den, bus.num, bus.den, itc.num, itc.den); |
| 655 | 655 | ||
| 656 | return p - page; | 656 | return p - page; |
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index ac167436e936..49958904045b 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c | |||
| @@ -188,7 +188,7 @@ ia64_init_itm (void) | |||
| 188 | itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den; | 188 | itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den; |
| 189 | 189 | ||
| 190 | local_cpu_data->itm_delta = (itc_freq + HZ/2) / HZ; | 190 | local_cpu_data->itm_delta = (itc_freq + HZ/2) / HZ; |
| 191 | printk(KERN_DEBUG "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, " | 191 | printk(KERN_DEBUG "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%u/%u, " |
| 192 | "ITC freq=%lu.%03luMHz", smp_processor_id(), | 192 | "ITC freq=%lu.%03luMHz", smp_processor_id(), |
| 193 | platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000, | 193 | platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000, |
| 194 | itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000); | 194 | itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000); |
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c index 3b6fd798c4d6..b47476d655f1 100644 --- a/arch/ia64/kernel/topology.c +++ b/arch/ia64/kernel/topology.c | |||
| @@ -9,6 +9,8 @@ | |||
| 9 | * 2002/08/07 Erich Focht <efocht@ess.nec.de> | 9 | * 2002/08/07 Erich Focht <efocht@ess.nec.de> |
| 10 | * Populate cpu entries in sysfs for non-numa systems as well | 10 | * Populate cpu entries in sysfs for non-numa systems as well |
| 11 | * Intel Corporation - Ashok Raj | 11 | * Intel Corporation - Ashok Raj |
| 12 | * 02/27/2006 Zhang, Yanmin | ||
| 13 | * Populate cpu cache entries in sysfs for cpu cache info | ||
| 12 | */ | 14 | */ |
| 13 | 15 | ||
| 14 | #include <linux/config.h> | 16 | #include <linux/config.h> |
| @@ -19,6 +21,7 @@ | |||
| 19 | #include <linux/init.h> | 21 | #include <linux/init.h> |
| 20 | #include <linux/bootmem.h> | 22 | #include <linux/bootmem.h> |
| 21 | #include <linux/nodemask.h> | 23 | #include <linux/nodemask.h> |
| 24 | #include <linux/notifier.h> | ||
| 22 | #include <asm/mmzone.h> | 25 | #include <asm/mmzone.h> |
| 23 | #include <asm/numa.h> | 26 | #include <asm/numa.h> |
| 24 | #include <asm/cpu.h> | 27 | #include <asm/cpu.h> |
| @@ -101,3 +104,367 @@ out: | |||
| 101 | } | 104 | } |
| 102 | 105 | ||
| 103 | subsys_initcall(topology_init); | 106 | subsys_initcall(topology_init); |
| 107 | |||
| 108 | |||
| 109 | /* | ||
| 110 | * Export cpu cache information through sysfs | ||
| 111 | */ | ||
| 112 | |||
| 113 | /* | ||
| 114 | * A bunch of string array to get pretty printing | ||
| 115 | */ | ||
| 116 | static const char *cache_types[] = { | ||
| 117 | "", /* not used */ | ||
| 118 | "Instruction", | ||
| 119 | "Data", | ||
| 120 | "Unified" /* unified */ | ||
| 121 | }; | ||
| 122 | |||
| 123 | static const char *cache_mattrib[]={ | ||
| 124 | "WriteThrough", | ||
| 125 | "WriteBack", | ||
| 126 | "", /* reserved */ | ||
| 127 | "" /* reserved */ | ||
| 128 | }; | ||
| 129 | |||
| 130 | struct cache_info { | ||
| 131 | pal_cache_config_info_t cci; | ||
| 132 | cpumask_t shared_cpu_map; | ||
| 133 | int level; | ||
| 134 | int type; | ||
| 135 | struct kobject kobj; | ||
| 136 | }; | ||
| 137 | |||
| 138 | struct cpu_cache_info { | ||
| 139 | struct cache_info *cache_leaves; | ||
| 140 | int num_cache_leaves; | ||
| 141 | struct kobject kobj; | ||
| 142 | }; | ||
| 143 | |||
| 144 | static struct cpu_cache_info all_cpu_cache_info[NR_CPUS]; | ||
| 145 | #define LEAF_KOBJECT_PTR(x,y) (&all_cpu_cache_info[x].cache_leaves[y]) | ||
| 146 | |||
| 147 | #ifdef CONFIG_SMP | ||
| 148 | static void cache_shared_cpu_map_setup( unsigned int cpu, | ||
| 149 | struct cache_info * this_leaf) | ||
| 150 | { | ||
| 151 | pal_cache_shared_info_t csi; | ||
| 152 | int num_shared, i = 0; | ||
| 153 | unsigned int j; | ||
| 154 | |||
| 155 | if (cpu_data(cpu)->threads_per_core <= 1 && | ||
| 156 | cpu_data(cpu)->cores_per_socket <= 1) { | ||
| 157 | cpu_set(cpu, this_leaf->shared_cpu_map); | ||
| 158 | return; | ||
| 159 | } | ||
| 160 | |||
| 161 | if (ia64_pal_cache_shared_info(this_leaf->level, | ||
| 162 | this_leaf->type, | ||
| 163 | 0, | ||
| 164 | &csi) != PAL_STATUS_SUCCESS) | ||
| 165 | return; | ||
| 166 | |||
| 167 | num_shared = (int) csi.num_shared; | ||
| 168 | do { | ||
| 169 | for_each_cpu(j) | ||
| 170 | if (cpu_data(cpu)->socket_id == cpu_data(j)->socket_id | ||
| 171 | && cpu_data(j)->core_id == csi.log1_cid | ||
| 172 | && cpu_data(j)->thread_id == csi.log1_tid) | ||
| 173 | cpu_set(j, this_leaf->shared_cpu_map); | ||
| 174 | |||
| 175 | i++; | ||
| 176 | } while (i < num_shared && | ||
| 177 | ia64_pal_cache_shared_info(this_leaf->level, | ||
| 178 | this_leaf->type, | ||
| 179 | i, | ||
| 180 | &csi) == PAL_STATUS_SUCCESS); | ||
| 181 | } | ||
| 182 | #else | ||
| 183 | static void cache_shared_cpu_map_setup(unsigned int cpu, | ||
| 184 | struct cache_info * this_leaf) | ||
| 185 | { | ||
| 186 | cpu_set(cpu, this_leaf->shared_cpu_map); | ||
| 187 | return; | ||
| 188 | } | ||
| 189 | #endif | ||
| 190 | |||
| 191 | static ssize_t show_coherency_line_size(struct cache_info *this_leaf, | ||
| 192 | char *buf) | ||
| 193 | { | ||
| 194 | return sprintf(buf, "%u\n", 1 << this_leaf->cci.pcci_line_size); | ||
| 195 | } | ||
| 196 | |||
| 197 | static ssize_t show_ways_of_associativity(struct cache_info *this_leaf, | ||
| 198 | char *buf) | ||
| 199 | { | ||
| 200 | return sprintf(buf, "%u\n", this_leaf->cci.pcci_assoc); | ||
| 201 | } | ||
| 202 | |||
| 203 | static ssize_t show_attributes(struct cache_info *this_leaf, char *buf) | ||
| 204 | { | ||
| 205 | return sprintf(buf, | ||
| 206 | "%s\n", | ||
| 207 | cache_mattrib[this_leaf->cci.pcci_cache_attr]); | ||
| 208 | } | ||
| 209 | |||
| 210 | static ssize_t show_size(struct cache_info *this_leaf, char *buf) | ||
| 211 | { | ||
| 212 | return sprintf(buf, "%uK\n", this_leaf->cci.pcci_cache_size / 1024); | ||
| 213 | } | ||
| 214 | |||
| 215 | static ssize_t show_number_of_sets(struct cache_info *this_leaf, char *buf) | ||
| 216 | { | ||
| 217 | unsigned number_of_sets = this_leaf->cci.pcci_cache_size; | ||
| 218 | number_of_sets /= this_leaf->cci.pcci_assoc; | ||
| 219 | number_of_sets /= 1 << this_leaf->cci.pcci_line_size; | ||
| 220 | |||
| 221 | return sprintf(buf, "%u\n", number_of_sets); | ||
| 222 | } | ||
| 223 | |||
| 224 | static ssize_t show_shared_cpu_map(struct cache_info *this_leaf, char *buf) | ||
| 225 | { | ||
| 226 | ssize_t len; | ||
| 227 | cpumask_t shared_cpu_map; | ||
| 228 | |||
| 229 | cpus_and(shared_cpu_map, this_leaf->shared_cpu_map, cpu_online_map); | ||
| 230 | len = cpumask_scnprintf(buf, NR_CPUS+1, shared_cpu_map); | ||
| 231 | len += sprintf(buf+len, "\n"); | ||
| 232 | return len; | ||
| 233 | } | ||
| 234 | |||
| 235 | static ssize_t show_type(struct cache_info *this_leaf, char *buf) | ||
| 236 | { | ||
| 237 | int type = this_leaf->type + this_leaf->cci.pcci_unified; | ||
| 238 | return sprintf(buf, "%s\n", cache_types[type]); | ||
| 239 | } | ||
| 240 | |||
| 241 | static ssize_t show_level(struct cache_info *this_leaf, char *buf) | ||
| 242 | { | ||
| 243 | return sprintf(buf, "%u\n", this_leaf->level); | ||
| 244 | } | ||
| 245 | |||
| 246 | struct cache_attr { | ||
| 247 | struct attribute attr; | ||
| 248 | ssize_t (*show)(struct cache_info *, char *); | ||
| 249 | ssize_t (*store)(struct cache_info *, const char *, size_t count); | ||
| 250 | }; | ||
| 251 | |||
| 252 | #ifdef define_one_ro | ||
| 253 | #undef define_one_ro | ||
| 254 | #endif | ||
| 255 | #define define_one_ro(_name) \ | ||
| 256 | static struct cache_attr _name = \ | ||
| 257 | __ATTR(_name, 0444, show_##_name, NULL) | ||
| 258 | |||
| 259 | define_one_ro(level); | ||
| 260 | define_one_ro(type); | ||
| 261 | define_one_ro(coherency_line_size); | ||
| 262 | define_one_ro(ways_of_associativity); | ||
| 263 | define_one_ro(size); | ||
| 264 | define_one_ro(number_of_sets); | ||
| 265 | define_one_ro(shared_cpu_map); | ||
| 266 | define_one_ro(attributes); | ||
| 267 | |||
| 268 | static struct attribute * cache_default_attrs[] = { | ||
| 269 | &type.attr, | ||
| 270 | &level.attr, | ||
| 271 | &coherency_line_size.attr, | ||
| 272 | &ways_of_associativity.attr, | ||
| 273 | &attributes.attr, | ||
| 274 | &size.attr, | ||
| 275 | &number_of_sets.attr, | ||
| 276 | &shared_cpu_map.attr, | ||
| 277 | NULL | ||
| 278 | }; | ||
| 279 | |||
| 280 | #define to_object(k) container_of(k, struct cache_info, kobj) | ||
| 281 | #define to_attr(a) container_of(a, struct cache_attr, attr) | ||
| 282 | |||
| 283 | static ssize_t cache_show(struct kobject * kobj, struct attribute * attr, char * buf) | ||
| 284 | { | ||
| 285 | struct cache_attr *fattr = to_attr(attr); | ||
| 286 | struct cache_info *this_leaf = to_object(kobj); | ||
| 287 | ssize_t ret; | ||
| 288 | |||
| 289 | ret = fattr->show ? fattr->show(this_leaf, buf) : 0; | ||
| 290 | return ret; | ||
| 291 | } | ||
| 292 | |||
| 293 | static struct sysfs_ops cache_sysfs_ops = { | ||
| 294 | .show = cache_show | ||
| 295 | }; | ||
| 296 | |||
| 297 | static struct kobj_type cache_ktype = { | ||
| 298 | .sysfs_ops = &cache_sysfs_ops, | ||
| 299 | .default_attrs = cache_default_attrs, | ||
| 300 | }; | ||
| 301 | |||
| 302 | static struct kobj_type cache_ktype_percpu_entry = { | ||
| 303 | .sysfs_ops = &cache_sysfs_ops, | ||
| 304 | }; | ||
| 305 | |||
| 306 | static void __cpuinit cpu_cache_sysfs_exit(unsigned int cpu) | ||
| 307 | { | ||
| 308 | if (all_cpu_cache_info[cpu].cache_leaves) { | ||
| 309 | kfree(all_cpu_cache_info[cpu].cache_leaves); | ||
| 310 | all_cpu_cache_info[cpu].cache_leaves = NULL; | ||
| 311 | } | ||
| 312 | all_cpu_cache_info[cpu].num_cache_leaves = 0; | ||
| 313 | memset(&all_cpu_cache_info[cpu].kobj, 0, sizeof(struct kobject)); | ||
| 314 | |||
| 315 | return; | ||
| 316 | } | ||
| 317 | |||
| 318 | static int __cpuinit cpu_cache_sysfs_init(unsigned int cpu) | ||
| 319 | { | ||
| 320 | u64 i, levels, unique_caches; | ||
| 321 | pal_cache_config_info_t cci; | ||
| 322 | int j; | ||
| 323 | s64 status; | ||
| 324 | struct cache_info *this_cache; | ||
| 325 | int num_cache_leaves = 0; | ||
| 326 | |||
| 327 | if ((status = ia64_pal_cache_summary(&levels, &unique_caches)) != 0) { | ||
| 328 | printk(KERN_ERR "ia64_pal_cache_summary=%ld\n", status); | ||
| 329 | return -1; | ||
| 330 | } | ||
| 331 | |||
| 332 | this_cache=kzalloc(sizeof(struct cache_info)*unique_caches, | ||
| 333 | GFP_KERNEL); | ||
| 334 | if (this_cache == NULL) | ||
| 335 | return -ENOMEM; | ||
| 336 | |||
| 337 | for (i=0; i < levels; i++) { | ||
| 338 | for (j=2; j >0 ; j--) { | ||
| 339 | if ((status=ia64_pal_cache_config_info(i,j, &cci)) != | ||
| 340 | PAL_STATUS_SUCCESS) | ||
| 341 | continue; | ||
| 342 | |||
| 343 | this_cache[num_cache_leaves].cci = cci; | ||
| 344 | this_cache[num_cache_leaves].level = i + 1; | ||
| 345 | this_cache[num_cache_leaves].type = j; | ||
| 346 | |||
| 347 | cache_shared_cpu_map_setup(cpu, | ||
| 348 | &this_cache[num_cache_leaves]); | ||
| 349 | num_cache_leaves ++; | ||
| 350 | } | ||
| 351 | } | ||
| 352 | |||
| 353 | all_cpu_cache_info[cpu].cache_leaves = this_cache; | ||
| 354 | all_cpu_cache_info[cpu].num_cache_leaves = num_cache_leaves; | ||
| 355 | |||
| 356 | memset(&all_cpu_cache_info[cpu].kobj, 0, sizeof(struct kobject)); | ||
| 357 | |||
| 358 | return 0; | ||
| 359 | } | ||
| 360 | |||
| 361 | /* Add cache interface for CPU device */ | ||
| 362 | static int __cpuinit cache_add_dev(struct sys_device * sys_dev) | ||
| 363 | { | ||
| 364 | unsigned int cpu = sys_dev->id; | ||
| 365 | unsigned long i, j; | ||
| 366 | struct cache_info *this_object; | ||
| 367 | int retval = 0; | ||
| 368 | cpumask_t oldmask; | ||
| 369 | |||
| 370 | if (all_cpu_cache_info[cpu].kobj.parent) | ||
| 371 | return 0; | ||
| 372 | |||
| 373 | oldmask = current->cpus_allowed; | ||
| 374 | retval = set_cpus_allowed(current, cpumask_of_cpu(cpu)); | ||
| 375 | if (unlikely(retval)) | ||
| 376 | return retval; | ||
| 377 | |||
| 378 | retval = cpu_cache_sysfs_init(cpu); | ||
| 379 | set_cpus_allowed(current, oldmask); | ||
| 380 | if (unlikely(retval < 0)) | ||
| 381 | return retval; | ||
| 382 | |||
| 383 | all_cpu_cache_info[cpu].kobj.parent = &sys_dev->kobj; | ||
| 384 | kobject_set_name(&all_cpu_cache_info[cpu].kobj, "%s", "cache"); | ||
| 385 | all_cpu_cache_info[cpu].kobj.ktype = &cache_ktype_percpu_entry; | ||
| 386 | retval = kobject_register(&all_cpu_cache_info[cpu].kobj); | ||
| 387 | |||
| 388 | for (i = 0; i < all_cpu_cache_info[cpu].num_cache_leaves; i++) { | ||
| 389 | this_object = LEAF_KOBJECT_PTR(cpu,i); | ||
| 390 | this_object->kobj.parent = &all_cpu_cache_info[cpu].kobj; | ||
| 391 | kobject_set_name(&(this_object->kobj), "index%1lu", i); | ||
| 392 | this_object->kobj.ktype = &cache_ktype; | ||
| 393 | retval = kobject_register(&(this_object->kobj)); | ||
| 394 | if (unlikely(retval)) { | ||
| 395 | for (j = 0; j < i; j++) { | ||
| 396 | kobject_unregister( | ||
| 397 | &(LEAF_KOBJECT_PTR(cpu,j)->kobj)); | ||
| 398 | } | ||
| 399 | kobject_unregister(&all_cpu_cache_info[cpu].kobj); | ||
| 400 | cpu_cache_sysfs_exit(cpu); | ||
| 401 | break; | ||
| 402 | } | ||
| 403 | } | ||
| 404 | return retval; | ||
| 405 | } | ||
| 406 | |||
| 407 | /* Remove cache interface for CPU device */ | ||
| 408 | static int __cpuinit cache_remove_dev(struct sys_device * sys_dev) | ||
| 409 | { | ||
| 410 | unsigned int cpu = sys_dev->id; | ||
| 411 | unsigned long i; | ||
| 412 | |||
| 413 | for (i = 0; i < all_cpu_cache_info[cpu].num_cache_leaves; i++) | ||
| 414 | kobject_unregister(&(LEAF_KOBJECT_PTR(cpu,i)->kobj)); | ||
| 415 | |||
| 416 | if (all_cpu_cache_info[cpu].kobj.parent) { | ||
| 417 | kobject_unregister(&all_cpu_cache_info[cpu].kobj); | ||
| 418 | memset(&all_cpu_cache_info[cpu].kobj, | ||
| 419 | 0, | ||
| 420 | sizeof(struct kobject)); | ||
| 421 | } | ||
| 422 | |||
| 423 | cpu_cache_sysfs_exit(cpu); | ||
| 424 | |||
| 425 | return 0; | ||
| 426 | } | ||
| 427 | |||
| 428 | /* | ||
| 429 | * When a cpu is hot-plugged, do a check and initiate | ||
| 430 | * cache kobject if necessary | ||
| 431 | */ | ||
| 432 | static int __cpuinit cache_cpu_callback(struct notifier_block *nfb, | ||
| 433 | unsigned long action, void *hcpu) | ||
| 434 | { | ||
| 435 | unsigned int cpu = (unsigned long)hcpu; | ||
| 436 | struct sys_device *sys_dev; | ||
| 437 | |||
| 438 | sys_dev = get_cpu_sysdev(cpu); | ||
| 439 | switch (action) { | ||
| 440 | case CPU_ONLINE: | ||
| 441 | cache_add_dev(sys_dev); | ||
| 442 | break; | ||
| 443 | case CPU_DEAD: | ||
| 444 | cache_remove_dev(sys_dev); | ||
| 445 | break; | ||
| 446 | } | ||
| 447 | return NOTIFY_OK; | ||
| 448 | } | ||
| 449 | |||
| 450 | static struct notifier_block cache_cpu_notifier = | ||
| 451 | { | ||
| 452 | .notifier_call = cache_cpu_callback | ||
| 453 | }; | ||
| 454 | |||
| 455 | static int __cpuinit cache_sysfs_init(void) | ||
| 456 | { | ||
| 457 | int i; | ||
| 458 | |||
| 459 | for_each_online_cpu(i) { | ||
| 460 | cache_cpu_callback(&cache_cpu_notifier, CPU_ONLINE, | ||
| 461 | (void *)(long)i); | ||
| 462 | } | ||
| 463 | |||
| 464 | register_cpu_notifier(&cache_cpu_notifier); | ||
| 465 | |||
| 466 | return 0; | ||
| 467 | } | ||
| 468 | |||
| 469 | device_initcall(cache_sysfs_init); | ||
| 470 | |||
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index 0b9e56dd7f05..783600fe52b2 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S | |||
| @@ -70,6 +70,15 @@ SECTIONS | |||
| 70 | __stop___ex_table = .; | 70 | __stop___ex_table = .; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | /* MCA table */ | ||
| 74 | . = ALIGN(16); | ||
| 75 | __mca_table : AT(ADDR(__mca_table) - LOAD_OFFSET) | ||
| 76 | { | ||
| 77 | __start___mca_table = .; | ||
| 78 | *(__mca_table) | ||
| 79 | __stop___mca_table = .; | ||
| 80 | } | ||
| 81 | |||
| 73 | /* Global data */ | 82 | /* Global data */ |
| 74 | _data = .; | 83 | _data = .; |
| 75 | 84 | ||
| @@ -130,15 +139,6 @@ SECTIONS | |||
| 130 | __initcall_end = .; | 139 | __initcall_end = .; |
| 131 | } | 140 | } |
| 132 | 141 | ||
| 133 | /* MCA table */ | ||
| 134 | . = ALIGN(16); | ||
| 135 | __mca_table : AT(ADDR(__mca_table) - LOAD_OFFSET) | ||
| 136 | { | ||
| 137 | __start___mca_table = .; | ||
| 138 | *(__mca_table) | ||
| 139 | __stop___mca_table = .; | ||
| 140 | } | ||
| 141 | |||
| 142 | .data.patch.vtop : AT(ADDR(.data.patch.vtop) - LOAD_OFFSET) | 142 | .data.patch.vtop : AT(ADDR(.data.patch.vtop) - LOAD_OFFSET) |
| 143 | { | 143 | { |
| 144 | __start___vtop_patchlist = .; | 144 | __start___vtop_patchlist = .; |
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 2ef1151cde90..cafa8776a53d 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c | |||
| @@ -109,6 +109,7 @@ lazy_mmu_prot_update (pte_t pte) | |||
| 109 | { | 109 | { |
| 110 | unsigned long addr; | 110 | unsigned long addr; |
| 111 | struct page *page; | 111 | struct page *page; |
| 112 | unsigned long order; | ||
| 112 | 113 | ||
| 113 | if (!pte_exec(pte)) | 114 | if (!pte_exec(pte)) |
| 114 | return; /* not an executable page... */ | 115 | return; /* not an executable page... */ |
| @@ -119,7 +120,12 @@ lazy_mmu_prot_update (pte_t pte) | |||
| 119 | if (test_bit(PG_arch_1, &page->flags)) | 120 | if (test_bit(PG_arch_1, &page->flags)) |
| 120 | return; /* i-cache is already coherent with d-cache */ | 121 | return; /* i-cache is already coherent with d-cache */ |
| 121 | 122 | ||
| 122 | flush_icache_range(addr, addr + PAGE_SIZE); | 123 | if (PageCompound(page)) { |
| 124 | order = (unsigned long) (page[1].lru.prev); | ||
| 125 | flush_icache_range(addr, addr + (1UL << order << PAGE_SHIFT)); | ||
| 126 | } | ||
| 127 | else | ||
| 128 | flush_icache_range(addr, addr + PAGE_SIZE); | ||
| 123 | set_bit(PG_arch_1, &page->flags); /* mark page as clean */ | 129 | set_bit(PG_arch_1, &page->flags); /* mark page as clean */ |
| 124 | } | 130 | } |
| 125 | 131 | ||
diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c index 62328621f99c..643ccc6960ce 100644 --- a/arch/ia64/mm/ioremap.c +++ b/arch/ia64/mm/ioremap.c | |||
| @@ -21,12 +21,12 @@ __ioremap (unsigned long offset, unsigned long size) | |||
| 21 | void __iomem * | 21 | void __iomem * |
| 22 | ioremap (unsigned long offset, unsigned long size) | 22 | ioremap (unsigned long offset, unsigned long size) |
| 23 | { | 23 | { |
| 24 | if (efi_mem_attribute_range(offset, size, EFI_MEMORY_UC)) | ||
| 25 | return __ioremap(offset, size); | ||
| 26 | |||
| 27 | if (efi_mem_attribute_range(offset, size, EFI_MEMORY_WB)) | 24 | if (efi_mem_attribute_range(offset, size, EFI_MEMORY_WB)) |
| 28 | return phys_to_virt(offset); | 25 | return phys_to_virt(offset); |
| 29 | 26 | ||
| 27 | if (efi_mem_attribute_range(offset, size, EFI_MEMORY_UC)) | ||
| 28 | return __ioremap(offset, size); | ||
| 29 | |||
| 30 | /* | 30 | /* |
| 31 | * Someday this should check ACPI resources so we | 31 | * Someday this should check ACPI resources so we |
| 32 | * can do the right thing for hot-plugged regions. | 32 | * can do the right thing for hot-plugged regions. |
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index 6a4eec9113e8..4dbbca0b5e9c 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c | |||
| @@ -156,17 +156,19 @@ flush_tlb_range (struct vm_area_struct *vma, unsigned long start, | |||
| 156 | nbits = purge.max_bits; | 156 | nbits = purge.max_bits; |
| 157 | start &= ~((1UL << nbits) - 1); | 157 | start &= ~((1UL << nbits) - 1); |
| 158 | 158 | ||
| 159 | # ifdef CONFIG_SMP | ||
| 160 | platform_global_tlb_purge(mm, start, end, nbits); | ||
| 161 | # else | ||
| 162 | preempt_disable(); | 159 | preempt_disable(); |
| 160 | #ifdef CONFIG_SMP | ||
| 161 | if (mm != current->active_mm || cpus_weight(mm->cpu_vm_mask) != 1) { | ||
| 162 | platform_global_tlb_purge(mm, start, end, nbits); | ||
| 163 | preempt_enable(); | ||
| 164 | return; | ||
| 165 | } | ||
| 166 | #endif | ||
| 163 | do { | 167 | do { |
| 164 | ia64_ptcl(start, (nbits<<2)); | 168 | ia64_ptcl(start, (nbits<<2)); |
| 165 | start += (1UL << nbits); | 169 | start += (1UL << nbits); |
| 166 | } while (start < end); | 170 | } while (start < end); |
| 167 | preempt_enable(); | 171 | preempt_enable(); |
| 168 | # endif | ||
| 169 | |||
| 170 | ia64_srlz_i(); /* srlz.i implies srlz.d */ | 172 | ia64_srlz_i(); /* srlz.i implies srlz.d */ |
| 171 | } | 173 | } |
| 172 | EXPORT_SYMBOL(flush_tlb_range); | 174 | EXPORT_SYMBOL(flush_tlb_range); |
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c index 70db21f3df21..d917afa30b27 100644 --- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c +++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c | |||
| @@ -110,7 +110,11 @@ static int sn_hwperf_geoid_to_cnode(char *location) | |||
| 110 | if (sn_hwperf_location_to_bpos(location, &rack, &bay, &slot, &slab)) | 110 | if (sn_hwperf_location_to_bpos(location, &rack, &bay, &slot, &slab)) |
| 111 | return -1; | 111 | return -1; |
| 112 | 112 | ||
| 113 | for_each_node(cnode) { | 113 | /* |
| 114 | * FIXME: replace with cleaner for_each_XXX macro which addresses | ||
| 115 | * both compute and IO nodes once ACPI3.0 is available. | ||
| 116 | */ | ||
| 117 | for (cnode = 0; cnode < num_cnodes; cnode++) { | ||
| 114 | geoid = cnodeid_get_geoid(cnode); | 118 | geoid = cnodeid_get_geoid(cnode); |
| 115 | module_id = geo_module(geoid); | 119 | module_id = geo_module(geoid); |
| 116 | this_rack = MODULE_GET_RACK(module_id); | 120 | this_rack = MODULE_GET_RACK(module_id); |
| @@ -605,7 +609,7 @@ static int sn_hwperf_op_cpu(struct sn_hwperf_op_info *op_info) | |||
| 605 | op_info->a->arg &= SN_HWPERF_ARG_OBJID_MASK; | 609 | op_info->a->arg &= SN_HWPERF_ARG_OBJID_MASK; |
| 606 | 610 | ||
| 607 | if (cpu != SN_HWPERF_ARG_ANY_CPU) { | 611 | if (cpu != SN_HWPERF_ARG_ANY_CPU) { |
| 608 | if (cpu >= num_online_cpus() || !cpu_online(cpu)) { | 612 | if (cpu >= NR_CPUS || !cpu_online(cpu)) { |
| 609 | r = -EINVAL; | 613 | r = -EINVAL; |
| 610 | goto out; | 614 | goto out; |
| 611 | } | 615 | } |
