aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/kernel')
-rw-r--r--arch/ia64/kernel/entry.S14
-rw-r--r--arch/ia64/kernel/iosapic.c358
-rw-r--r--arch/ia64/kernel/irq_ia64.c16
-rw-r--r--arch/ia64/kernel/perfmon.c59
-rw-r--r--arch/ia64/kernel/perfmon_default_smpl.c13
-rw-r--r--arch/ia64/kernel/setup.c69
-rw-r--r--arch/ia64/kernel/smpboot.c217
-rw-r--r--arch/ia64/kernel/unwind.c27
8 files changed, 619 insertions, 154 deletions
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 0272c010a3ba..bd86fea49a0c 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -728,12 +728,8 @@ ENTRY(ia64_leave_syscall)
728 mov f8=f0 // clear f8 728 mov f8=f0 // clear f8
729 ;; 729 ;;
730 ld8 r30=[r2],16 // M0|1 load cr.ifs 730 ld8 r30=[r2],16 // M0|1 load cr.ifs
731 mov.m ar.ssd=r0 // M2 clear ar.ssd
732 cmp.eq p9,p0=r0,r0 // set p9 to indicate that we should restore cr.ifs
733 ;;
734 ld8 r25=[r3],16 // M0|1 load ar.unat 731 ld8 r25=[r3],16 // M0|1 load ar.unat
735 mov.m ar.csd=r0 // M2 clear ar.csd 732 cmp.eq p9,p0=r0,r0 // set p9 to indicate that we should restore cr.ifs
736 mov r22=r0 // clear r22
737 ;; 733 ;;
738 ld8 r26=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs 734 ld8 r26=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs
739(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled 735(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled
@@ -756,11 +752,15 @@ ENTRY(ia64_leave_syscall)
756 mov f7=f0 // clear f7 752 mov f7=f0 // clear f7
757 ;; 753 ;;
758 ld8.fill r12=[r2] // restore r12 (sp) 754 ld8.fill r12=[r2] // restore r12 (sp)
755 mov.m ar.ssd=r0 // M2 clear ar.ssd
756 mov r22=r0 // clear r22
757
759 ld8.fill r15=[r3] // restore r15 758 ld8.fill r15=[r3] // restore r15
759(pUStk) st1 [r14]=r17
760 addl r3=THIS_CPU(ia64_phys_stacked_size_p8),r0 760 addl r3=THIS_CPU(ia64_phys_stacked_size_p8),r0
761 ;; 761 ;;
762(pUStk) ld4 r3=[r3] // r3 = cpu_data->phys_stacked_size_p8 762(pUStk) ld4 r17=[r3] // r17 = cpu_data->phys_stacked_size_p8
763(pUStk) st1 [r14]=r17 763 mov.m ar.csd=r0 // M2 clear ar.csd
764 mov b6=r18 // I0 restore b6 764 mov b6=r18 // I0 restore b6
765 ;; 765 ;;
766 mov r14=r0 // clear r14 766 mov r14=r0 // clear r14
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index c15be5c38f56..88b014381df5 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -79,6 +79,7 @@
79#include <linux/smp.h> 79#include <linux/smp.h>
80#include <linux/smp_lock.h> 80#include <linux/smp_lock.h>
81#include <linux/string.h> 81#include <linux/string.h>
82#include <linux/bootmem.h>
82 83
83#include <asm/delay.h> 84#include <asm/delay.h>
84#include <asm/hw_irq.h> 85#include <asm/hw_irq.h>
@@ -98,19 +99,30 @@
98#define DBG(fmt...) 99#define DBG(fmt...)
99#endif 100#endif
100 101
102#define NR_PREALLOCATE_RTE_ENTRIES (PAGE_SIZE / sizeof(struct iosapic_rte_info))
103#define RTE_PREALLOCATED (1)
104
101static DEFINE_SPINLOCK(iosapic_lock); 105static DEFINE_SPINLOCK(iosapic_lock);
102 106
103/* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */ 107/* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */
104 108
105static struct iosapic_intr_info { 109struct iosapic_rte_info {
110 struct list_head rte_list; /* node in list of RTEs sharing the same vector */
106 char __iomem *addr; /* base address of IOSAPIC */ 111 char __iomem *addr; /* base address of IOSAPIC */
107 u32 low32; /* current value of low word of Redirection table entry */
108 unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ 112 unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */
109 char rte_index; /* IOSAPIC RTE index (-1 => not an IOSAPIC interrupt) */ 113 char rte_index; /* IOSAPIC RTE index */
114 int refcnt; /* reference counter */
115 unsigned int flags; /* flags */
116} ____cacheline_aligned;
117
118static struct iosapic_intr_info {
119 struct list_head rtes; /* RTEs using this vector (empty => not an IOSAPIC interrupt) */
120 int count; /* # of RTEs that shares this vector */
121 u32 low32; /* current value of low word of Redirection table entry */
122 unsigned int dest; /* destination CPU physical ID */
110 unsigned char dmode : 3; /* delivery mode (see iosapic.h) */ 123 unsigned char dmode : 3; /* delivery mode (see iosapic.h) */
111 unsigned char polarity: 1; /* interrupt polarity (see iosapic.h) */ 124 unsigned char polarity: 1; /* interrupt polarity (see iosapic.h) */
112 unsigned char trigger : 1; /* trigger mode (see iosapic.h) */ 125 unsigned char trigger : 1; /* trigger mode (see iosapic.h) */
113 int refcnt; /* reference counter */
114} iosapic_intr_info[IA64_NUM_VECTORS]; 126} iosapic_intr_info[IA64_NUM_VECTORS];
115 127
116static struct iosapic { 128static struct iosapic {
@@ -126,6 +138,8 @@ static int num_iosapic;
126 138
127static unsigned char pcat_compat __initdata; /* 8259 compatibility flag */ 139static unsigned char pcat_compat __initdata; /* 8259 compatibility flag */
128 140
141static int iosapic_kmalloc_ok;
142static LIST_HEAD(free_rte_list);
129 143
130/* 144/*
131 * Find an IOSAPIC associated with a GSI 145 * Find an IOSAPIC associated with a GSI
@@ -147,10 +161,12 @@ static inline int
147_gsi_to_vector (unsigned int gsi) 161_gsi_to_vector (unsigned int gsi)
148{ 162{
149 struct iosapic_intr_info *info; 163 struct iosapic_intr_info *info;
164 struct iosapic_rte_info *rte;
150 165
151 for (info = iosapic_intr_info; info < iosapic_intr_info + IA64_NUM_VECTORS; ++info) 166 for (info = iosapic_intr_info; info < iosapic_intr_info + IA64_NUM_VECTORS; ++info)
152 if (info->gsi_base + info->rte_index == gsi) 167 list_for_each_entry(rte, &info->rtes, rte_list)
153 return info - iosapic_intr_info; 168 if (rte->gsi_base + rte->rte_index == gsi)
169 return info - iosapic_intr_info;
154 return -1; 170 return -1;
155} 171}
156 172
@@ -167,33 +183,52 @@ gsi_to_vector (unsigned int gsi)
167int 183int
168gsi_to_irq (unsigned int gsi) 184gsi_to_irq (unsigned int gsi)
169{ 185{
186 unsigned long flags;
187 int irq;
170 /* 188 /*
171 * XXX fix me: this assumes an identity mapping vetween IA-64 vector and Linux irq 189 * XXX fix me: this assumes an identity mapping vetween IA-64 vector and Linux irq
172 * numbers... 190 * numbers...
173 */ 191 */
174 return _gsi_to_vector(gsi); 192 spin_lock_irqsave(&iosapic_lock, flags);
193 {
194 irq = _gsi_to_vector(gsi);
195 }
196 spin_unlock_irqrestore(&iosapic_lock, flags);
197
198 return irq;
199}
200
201static struct iosapic_rte_info *gsi_vector_to_rte(unsigned int gsi, unsigned int vec)
202{
203 struct iosapic_rte_info *rte;
204
205 list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list)
206 if (rte->gsi_base + rte->rte_index == gsi)
207 return rte;
208 return NULL;
175} 209}
176 210
177static void 211static void
178set_rte (unsigned int vector, unsigned int dest, int mask) 212set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask)
179{ 213{
180 unsigned long pol, trigger, dmode; 214 unsigned long pol, trigger, dmode;
181 u32 low32, high32; 215 u32 low32, high32;
182 char __iomem *addr; 216 char __iomem *addr;
183 int rte_index; 217 int rte_index;
184 char redir; 218 char redir;
219 struct iosapic_rte_info *rte;
185 220
186 DBG(KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest); 221 DBG(KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest);
187 222
188 rte_index = iosapic_intr_info[vector].rte_index; 223 rte = gsi_vector_to_rte(gsi, vector);
189 if (rte_index < 0) 224 if (!rte)
190 return; /* not an IOSAPIC interrupt */ 225 return; /* not an IOSAPIC interrupt */
191 226
192 addr = iosapic_intr_info[vector].addr; 227 rte_index = rte->rte_index;
228 addr = rte->addr;
193 pol = iosapic_intr_info[vector].polarity; 229 pol = iosapic_intr_info[vector].polarity;
194 trigger = iosapic_intr_info[vector].trigger; 230 trigger = iosapic_intr_info[vector].trigger;
195 dmode = iosapic_intr_info[vector].dmode; 231 dmode = iosapic_intr_info[vector].dmode;
196 vector &= (~IA64_IRQ_REDIRECTED);
197 232
198 redir = (dmode == IOSAPIC_LOWEST_PRIORITY) ? 1 : 0; 233 redir = (dmode == IOSAPIC_LOWEST_PRIORITY) ? 1 : 0;
199 234
@@ -221,6 +256,7 @@ set_rte (unsigned int vector, unsigned int dest, int mask)
221 iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32); 256 iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32);
222 iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); 257 iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
223 iosapic_intr_info[vector].low32 = low32; 258 iosapic_intr_info[vector].low32 = low32;
259 iosapic_intr_info[vector].dest = dest;
224} 260}
225 261
226static void 262static void
@@ -237,18 +273,20 @@ mask_irq (unsigned int irq)
237 u32 low32; 273 u32 low32;
238 int rte_index; 274 int rte_index;
239 ia64_vector vec = irq_to_vector(irq); 275 ia64_vector vec = irq_to_vector(irq);
276 struct iosapic_rte_info *rte;
240 277
241 addr = iosapic_intr_info[vec].addr; 278 if (list_empty(&iosapic_intr_info[vec].rtes))
242 rte_index = iosapic_intr_info[vec].rte_index;
243
244 if (rte_index < 0)
245 return; /* not an IOSAPIC interrupt! */ 279 return; /* not an IOSAPIC interrupt! */
246 280
247 spin_lock_irqsave(&iosapic_lock, flags); 281 spin_lock_irqsave(&iosapic_lock, flags);
248 { 282 {
249 /* set only the mask bit */ 283 /* set only the mask bit */
250 low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK; 284 low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK;
251 iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); 285 list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) {
286 addr = rte->addr;
287 rte_index = rte->rte_index;
288 iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
289 }
252 } 290 }
253 spin_unlock_irqrestore(&iosapic_lock, flags); 291 spin_unlock_irqrestore(&iosapic_lock, flags);
254} 292}
@@ -261,16 +299,19 @@ unmask_irq (unsigned int irq)
261 u32 low32; 299 u32 low32;
262 int rte_index; 300 int rte_index;
263 ia64_vector vec = irq_to_vector(irq); 301 ia64_vector vec = irq_to_vector(irq);
302 struct iosapic_rte_info *rte;
264 303
265 addr = iosapic_intr_info[vec].addr; 304 if (list_empty(&iosapic_intr_info[vec].rtes))
266 rte_index = iosapic_intr_info[vec].rte_index;
267 if (rte_index < 0)
268 return; /* not an IOSAPIC interrupt! */ 305 return; /* not an IOSAPIC interrupt! */
269 306
270 spin_lock_irqsave(&iosapic_lock, flags); 307 spin_lock_irqsave(&iosapic_lock, flags);
271 { 308 {
272 low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK; 309 low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK;
273 iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); 310 list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) {
311 addr = rte->addr;
312 rte_index = rte->rte_index;
313 iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
314 }
274 } 315 }
275 spin_unlock_irqrestore(&iosapic_lock, flags); 316 spin_unlock_irqrestore(&iosapic_lock, flags);
276} 317}
@@ -286,6 +327,7 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask)
286 char __iomem *addr; 327 char __iomem *addr;
287 int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0; 328 int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0;
288 ia64_vector vec; 329 ia64_vector vec;
330 struct iosapic_rte_info *rte;
289 331
290 irq &= (~IA64_IRQ_REDIRECTED); 332 irq &= (~IA64_IRQ_REDIRECTED);
291 vec = irq_to_vector(irq); 333 vec = irq_to_vector(irq);
@@ -295,10 +337,7 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask)
295 337
296 dest = cpu_physical_id(first_cpu(mask)); 338 dest = cpu_physical_id(first_cpu(mask));
297 339
298 rte_index = iosapic_intr_info[vec].rte_index; 340 if (list_empty(&iosapic_intr_info[vec].rtes))
299 addr = iosapic_intr_info[vec].addr;
300
301 if (rte_index < 0)
302 return; /* not an IOSAPIC interrupt */ 341 return; /* not an IOSAPIC interrupt */
303 342
304 set_irq_affinity_info(irq, dest, redir); 343 set_irq_affinity_info(irq, dest, redir);
@@ -318,8 +357,13 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask)
318 low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT); 357 low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT);
319 358
320 iosapic_intr_info[vec].low32 = low32; 359 iosapic_intr_info[vec].low32 = low32;
321 iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32); 360 iosapic_intr_info[vec].dest = dest;
322 iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); 361 list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) {
362 addr = rte->addr;
363 rte_index = rte->rte_index;
364 iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32);
365 iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
366 }
323 } 367 }
324 spin_unlock_irqrestore(&iosapic_lock, flags); 368 spin_unlock_irqrestore(&iosapic_lock, flags);
325#endif 369#endif
@@ -340,9 +384,11 @@ static void
340iosapic_end_level_irq (unsigned int irq) 384iosapic_end_level_irq (unsigned int irq)
341{ 385{
342 ia64_vector vec = irq_to_vector(irq); 386 ia64_vector vec = irq_to_vector(irq);
387 struct iosapic_rte_info *rte;
343 388
344 move_irq(irq); 389 move_irq(irq);
345 iosapic_eoi(iosapic_intr_info[vec].addr, vec); 390 list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list)
391 iosapic_eoi(rte->addr, vec);
346} 392}
347 393
348#define iosapic_shutdown_level_irq mask_irq 394#define iosapic_shutdown_level_irq mask_irq
@@ -422,6 +468,34 @@ iosapic_version (char __iomem *addr)
422 return iosapic_read(addr, IOSAPIC_VERSION); 468 return iosapic_read(addr, IOSAPIC_VERSION);
423} 469}
424 470
471static int iosapic_find_sharable_vector (unsigned long trigger, unsigned long pol)
472{
473 int i, vector = -1, min_count = -1;
474 struct iosapic_intr_info *info;
475
476 /*
477 * shared vectors for edge-triggered interrupts are not
478 * supported yet
479 */
480 if (trigger == IOSAPIC_EDGE)
481 return -1;
482
483 for (i = IA64_FIRST_DEVICE_VECTOR; i <= IA64_LAST_DEVICE_VECTOR; i++) {
484 info = &iosapic_intr_info[i];
485 if (info->trigger == trigger && info->polarity == pol &&
486 (info->dmode == IOSAPIC_FIXED || info->dmode == IOSAPIC_LOWEST_PRIORITY)) {
487 if (min_count == -1 || info->count < min_count) {
488 vector = i;
489 min_count = info->count;
490 }
491 }
492 }
493 if (vector < 0)
494 panic("%s: out of interrupt vectors!\n", __FUNCTION__);
495
496 return vector;
497}
498
425/* 499/*
426 * if the given vector is already owned by other, 500 * if the given vector is already owned by other,
427 * assign a new vector for the other and make the vector available 501 * assign a new vector for the other and make the vector available
@@ -431,19 +505,63 @@ iosapic_reassign_vector (int vector)
431{ 505{
432 int new_vector; 506 int new_vector;
433 507
434 if (iosapic_intr_info[vector].rte_index >= 0 || iosapic_intr_info[vector].addr 508 if (!list_empty(&iosapic_intr_info[vector].rtes)) {
435 || iosapic_intr_info[vector].gsi_base || iosapic_intr_info[vector].dmode
436 || iosapic_intr_info[vector].polarity || iosapic_intr_info[vector].trigger)
437 {
438 new_vector = assign_irq_vector(AUTO_ASSIGN); 509 new_vector = assign_irq_vector(AUTO_ASSIGN);
439 printk(KERN_INFO "Reassigning vector %d to %d\n", vector, new_vector); 510 printk(KERN_INFO "Reassigning vector %d to %d\n", vector, new_vector);
440 memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector], 511 memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector],
441 sizeof(struct iosapic_intr_info)); 512 sizeof(struct iosapic_intr_info));
513 INIT_LIST_HEAD(&iosapic_intr_info[new_vector].rtes);
514 list_move(iosapic_intr_info[vector].rtes.next, &iosapic_intr_info[new_vector].rtes);
442 memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info)); 515 memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info));
443 iosapic_intr_info[vector].rte_index = -1; 516 iosapic_intr_info[vector].low32 = IOSAPIC_MASK;
517 INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);
444 } 518 }
445} 519}
446 520
521static struct iosapic_rte_info *iosapic_alloc_rte (void)
522{
523 int i;
524 struct iosapic_rte_info *rte;
525 int preallocated = 0;
526
527 if (!iosapic_kmalloc_ok && list_empty(&free_rte_list)) {
528 rte = alloc_bootmem(sizeof(struct iosapic_rte_info) * NR_PREALLOCATE_RTE_ENTRIES);
529 if (!rte)
530 return NULL;
531 for (i = 0; i < NR_PREALLOCATE_RTE_ENTRIES; i++, rte++)
532 list_add(&rte->rte_list, &free_rte_list);
533 }
534
535 if (!list_empty(&free_rte_list)) {
536 rte = list_entry(free_rte_list.next, struct iosapic_rte_info, rte_list);
537 list_del(&rte->rte_list);
538 preallocated++;
539 } else {
540 rte = kmalloc(sizeof(struct iosapic_rte_info), GFP_ATOMIC);
541 if (!rte)
542 return NULL;
543 }
544
545 memset(rte, 0, sizeof(struct iosapic_rte_info));
546 if (preallocated)
547 rte->flags |= RTE_PREALLOCATED;
548
549 return rte;
550}
551
552static void iosapic_free_rte (struct iosapic_rte_info *rte)
553{
554 if (rte->flags & RTE_PREALLOCATED)
555 list_add_tail(&rte->rte_list, &free_rte_list);
556 else
557 kfree(rte);
558}
559
560static inline int vector_is_shared (int vector)
561{
562 return (iosapic_intr_info[vector].count > 1);
563}
564
447static void 565static void
448register_intr (unsigned int gsi, int vector, unsigned char delivery, 566register_intr (unsigned int gsi, int vector, unsigned char delivery,
449 unsigned long polarity, unsigned long trigger) 567 unsigned long polarity, unsigned long trigger)
@@ -454,6 +572,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
454 int index; 572 int index;
455 unsigned long gsi_base; 573 unsigned long gsi_base;
456 void __iomem *iosapic_address; 574 void __iomem *iosapic_address;
575 struct iosapic_rte_info *rte;
457 576
458 index = find_iosapic(gsi); 577 index = find_iosapic(gsi);
459 if (index < 0) { 578 if (index < 0) {
@@ -464,14 +583,33 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
464 iosapic_address = iosapic_lists[index].addr; 583 iosapic_address = iosapic_lists[index].addr;
465 gsi_base = iosapic_lists[index].gsi_base; 584 gsi_base = iosapic_lists[index].gsi_base;
466 585
467 rte_index = gsi - gsi_base; 586 rte = gsi_vector_to_rte(gsi, vector);
468 iosapic_intr_info[vector].rte_index = rte_index; 587 if (!rte) {
588 rte = iosapic_alloc_rte();
589 if (!rte) {
590 printk(KERN_WARNING "%s: cannot allocate memory\n", __FUNCTION__);
591 return;
592 }
593
594 rte_index = gsi - gsi_base;
595 rte->rte_index = rte_index;
596 rte->addr = iosapic_address;
597 rte->gsi_base = gsi_base;
598 rte->refcnt++;
599 list_add_tail(&rte->rte_list, &iosapic_intr_info[vector].rtes);
600 iosapic_intr_info[vector].count++;
601 }
602 else if (vector_is_shared(vector)) {
603 struct iosapic_intr_info *info = &iosapic_intr_info[vector];
604 if (info->trigger != trigger || info->polarity != polarity) {
605 printk (KERN_WARNING "%s: cannot override the interrupt\n", __FUNCTION__);
606 return;
607 }
608 }
609
469 iosapic_intr_info[vector].polarity = polarity; 610 iosapic_intr_info[vector].polarity = polarity;
470 iosapic_intr_info[vector].dmode = delivery; 611 iosapic_intr_info[vector].dmode = delivery;
471 iosapic_intr_info[vector].addr = iosapic_address;
472 iosapic_intr_info[vector].gsi_base = gsi_base;
473 iosapic_intr_info[vector].trigger = trigger; 612 iosapic_intr_info[vector].trigger = trigger;
474 iosapic_intr_info[vector].refcnt++;
475 613
476 if (trigger == IOSAPIC_EDGE) 614 if (trigger == IOSAPIC_EDGE)
477 irq_type = &irq_type_iosapic_edge; 615 irq_type = &irq_type_iosapic_edge;
@@ -494,6 +632,13 @@ get_target_cpu (unsigned int gsi, int vector)
494 static int cpu = -1; 632 static int cpu = -1;
495 633
496 /* 634 /*
635 * In case of vector shared by multiple RTEs, all RTEs that
636 * share the vector need to use the same destination CPU.
637 */
638 if (!list_empty(&iosapic_intr_info[vector].rtes))
639 return iosapic_intr_info[vector].dest;
640
641 /*
497 * If the platform supports redirection via XTP, let it 642 * If the platform supports redirection via XTP, let it
498 * distribute interrupts. 643 * distribute interrupts.
499 */ 644 */
@@ -565,10 +710,12 @@ int
565iosapic_register_intr (unsigned int gsi, 710iosapic_register_intr (unsigned int gsi,
566 unsigned long polarity, unsigned long trigger) 711 unsigned long polarity, unsigned long trigger)
567{ 712{
568 int vector; 713 int vector, mask = 1;
569 unsigned int dest; 714 unsigned int dest;
570 unsigned long flags; 715 unsigned long flags;
571 716 struct iosapic_rte_info *rte;
717 u32 low32;
718again:
572 /* 719 /*
573 * If this GSI has already been registered (i.e., it's a 720 * If this GSI has already been registered (i.e., it's a
574 * shared interrupt, or we lost a race to register it), 721 * shared interrupt, or we lost a race to register it),
@@ -578,19 +725,45 @@ iosapic_register_intr (unsigned int gsi,
578 { 725 {
579 vector = gsi_to_vector(gsi); 726 vector = gsi_to_vector(gsi);
580 if (vector > 0) { 727 if (vector > 0) {
581 iosapic_intr_info[vector].refcnt++; 728 rte = gsi_vector_to_rte(gsi, vector);
729 rte->refcnt++;
582 spin_unlock_irqrestore(&iosapic_lock, flags); 730 spin_unlock_irqrestore(&iosapic_lock, flags);
583 return vector; 731 return vector;
584 } 732 }
733 }
734 spin_unlock_irqrestore(&iosapic_lock, flags);
735
736 /* If vector is running out, we try to find a sharable vector */
737 vector = assign_irq_vector_nopanic(AUTO_ASSIGN);
738 if (vector < 0)
739 vector = iosapic_find_sharable_vector(trigger, polarity);
740
741 spin_lock_irqsave(&irq_descp(vector)->lock, flags);
742 spin_lock(&iosapic_lock);
743 {
744 if (gsi_to_vector(gsi) > 0) {
745 if (list_empty(&iosapic_intr_info[vector].rtes))
746 free_irq_vector(vector);
747 spin_unlock(&iosapic_lock);
748 spin_unlock_irqrestore(&irq_descp(vector)->lock, flags);
749 goto again;
750 }
585 751
586 vector = assign_irq_vector(AUTO_ASSIGN);
587 dest = get_target_cpu(gsi, vector); 752 dest = get_target_cpu(gsi, vector);
588 register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, 753 register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
589 polarity, trigger); 754 polarity, trigger);
590 755
591 set_rte(vector, dest, 1); 756 /*
757 * If the vector is shared and already unmasked for
758 * other interrupt sources, don't mask it.
759 */
760 low32 = iosapic_intr_info[vector].low32;
761 if (vector_is_shared(vector) && !(low32 & IOSAPIC_MASK))
762 mask = 0;
763 set_rte(gsi, vector, dest, mask);
592 } 764 }
593 spin_unlock_irqrestore(&iosapic_lock, flags); 765 spin_unlock(&iosapic_lock);
766 spin_unlock_irqrestore(&irq_descp(vector)->lock, flags);
594 767
595 printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n", 768 printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n",
596 gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), 769 gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
@@ -607,8 +780,10 @@ iosapic_unregister_intr (unsigned int gsi)
607 unsigned long flags; 780 unsigned long flags;
608 int irq, vector; 781 int irq, vector;
609 irq_desc_t *idesc; 782 irq_desc_t *idesc;
610 int rte_index; 783 u32 low32;
611 unsigned long trigger, polarity; 784 unsigned long trigger, polarity;
785 unsigned int dest;
786 struct iosapic_rte_info *rte;
612 787
613 /* 788 /*
614 * If the irq associated with the gsi is not found, 789 * If the irq associated with the gsi is not found,
@@ -627,54 +802,56 @@ iosapic_unregister_intr (unsigned int gsi)
627 spin_lock_irqsave(&idesc->lock, flags); 802 spin_lock_irqsave(&idesc->lock, flags);
628 spin_lock(&iosapic_lock); 803 spin_lock(&iosapic_lock);
629 { 804 {
630 rte_index = iosapic_intr_info[vector].rte_index; 805 if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) {
631 if (rte_index < 0) {
632 spin_unlock(&iosapic_lock);
633 spin_unlock_irqrestore(&idesc->lock, flags);
634 printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi); 806 printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi);
635 WARN_ON(1); 807 WARN_ON(1);
636 return; 808 goto out;
637 } 809 }
638 810
639 if (--iosapic_intr_info[vector].refcnt > 0) { 811 if (--rte->refcnt > 0)
640 spin_unlock(&iosapic_lock); 812 goto out;
641 spin_unlock_irqrestore(&idesc->lock, flags);
642 return;
643 }
644 813
645 /* 814 /* Mask the interrupt */
646 * If interrupt handlers still exist on the irq 815 low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK;
647 * associated with the gsi, don't unregister the 816 iosapic_write(rte->addr, IOSAPIC_RTE_LOW(rte->rte_index), low32);
648 * interrupt.
649 */
650 if (idesc->action) {
651 iosapic_intr_info[vector].refcnt++;
652 spin_unlock(&iosapic_lock);
653 spin_unlock_irqrestore(&idesc->lock, flags);
654 printk(KERN_WARNING "Cannot unregister GSI. IRQ %u is still in use.\n", irq);
655 return;
656 }
657 817
658 /* Clear the interrupt controller descriptor. */ 818 /* Remove the rte entry from the list */
659 idesc->handler = &no_irq_type; 819 list_del(&rte->rte_list);
820 iosapic_intr_info[vector].count--;
821 iosapic_free_rte(rte);
660 822
661 trigger = iosapic_intr_info[vector].trigger; 823 trigger = iosapic_intr_info[vector].trigger;
662 polarity = iosapic_intr_info[vector].polarity; 824 polarity = iosapic_intr_info[vector].polarity;
825 dest = iosapic_intr_info[vector].dest;
826 printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d unregistered\n",
827 gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
828 (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
829 cpu_logical_id(dest), dest, vector);
830
831 if (list_empty(&iosapic_intr_info[vector].rtes)) {
832 /* Sanity check */
833 BUG_ON(iosapic_intr_info[vector].count);
834
835 /* Clear the interrupt controller descriptor */
836 idesc->handler = &no_irq_type;
837
838 /* Clear the interrupt information */
839 memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info));
840 iosapic_intr_info[vector].low32 |= IOSAPIC_MASK;
841 INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);
842
843 if (idesc->action) {
844 printk(KERN_ERR "interrupt handlers still exist on IRQ %u\n", irq);
845 WARN_ON(1);
846 }
663 847
664 /* Clear the interrupt information. */ 848 /* Free the interrupt vector */
665 memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info)); 849 free_irq_vector(vector);
666 iosapic_intr_info[vector].rte_index = -1; /* mark as unused */ 850 }
667 } 851 }
852 out:
668 spin_unlock(&iosapic_lock); 853 spin_unlock(&iosapic_lock);
669 spin_unlock_irqrestore(&idesc->lock, flags); 854 spin_unlock_irqrestore(&idesc->lock, flags);
670
671 /* Free the interrupt vector */
672 free_irq_vector(vector);
673
674 printk(KERN_INFO "GSI %u (%s, %s) -> vector %d unregisterd.\n",
675 gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
676 (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
677 vector);
678} 855}
679#endif /* CONFIG_ACPI_DEALLOCATE_IRQ */ 856#endif /* CONFIG_ACPI_DEALLOCATE_IRQ */
680 857
@@ -724,7 +901,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
724 (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), 901 (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
725 cpu_logical_id(dest), dest, vector); 902 cpu_logical_id(dest), dest, vector);
726 903
727 set_rte(vector, dest, mask); 904 set_rte(gsi, vector, dest, mask);
728 return vector; 905 return vector;
729} 906}
730 907
@@ -750,7 +927,7 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
750 polarity == IOSAPIC_POL_HIGH ? "high" : "low", 927 polarity == IOSAPIC_POL_HIGH ? "high" : "low",
751 cpu_logical_id(dest), dest, vector); 928 cpu_logical_id(dest), dest, vector);
752 929
753 set_rte(vector, dest, 1); 930 set_rte(gsi, vector, dest, 1);
754} 931}
755 932
756void __init 933void __init
@@ -758,8 +935,10 @@ iosapic_system_init (int system_pcat_compat)
758{ 935{
759 int vector; 936 int vector;
760 937
761 for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) 938 for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) {
762 iosapic_intr_info[vector].rte_index = -1; /* mark as unused */ 939 iosapic_intr_info[vector].low32 = IOSAPIC_MASK;
940 INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); /* mark as unused */
941 }
763 942
764 pcat_compat = system_pcat_compat; 943 pcat_compat = system_pcat_compat;
765 if (pcat_compat) { 944 if (pcat_compat) {
@@ -825,3 +1004,10 @@ map_iosapic_to_node(unsigned int gsi_base, int node)
825 return; 1004 return;
826} 1005}
827#endif 1006#endif
1007
1008static int __init iosapic_enable_kmalloc (void)
1009{
1010 iosapic_kmalloc_ok = 1;
1011 return 0;
1012}
1013core_initcall (iosapic_enable_kmalloc);
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index 5ba06ebe355b..4fe60c7a2e90 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -63,20 +63,30 @@ EXPORT_SYMBOL(isa_irq_to_vector_map);
63static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_NUM_DEVICE_VECTORS)]; 63static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_NUM_DEVICE_VECTORS)];
64 64
65int 65int
66assign_irq_vector (int irq) 66assign_irq_vector_nopanic (int irq)
67{ 67{
68 int pos, vector; 68 int pos, vector;
69 again: 69 again:
70 pos = find_first_zero_bit(ia64_vector_mask, IA64_NUM_DEVICE_VECTORS); 70 pos = find_first_zero_bit(ia64_vector_mask, IA64_NUM_DEVICE_VECTORS);
71 vector = IA64_FIRST_DEVICE_VECTOR + pos; 71 vector = IA64_FIRST_DEVICE_VECTOR + pos;
72 if (vector > IA64_LAST_DEVICE_VECTOR) 72 if (vector > IA64_LAST_DEVICE_VECTOR)
73 /* XXX could look for sharable vectors instead of panic'ing... */ 73 return -1;
74 panic("assign_irq_vector: out of interrupt vectors!");
75 if (test_and_set_bit(pos, ia64_vector_mask)) 74 if (test_and_set_bit(pos, ia64_vector_mask))
76 goto again; 75 goto again;
77 return vector; 76 return vector;
78} 77}
79 78
79int
80assign_irq_vector (int irq)
81{
82 int vector = assign_irq_vector_nopanic(irq);
83
84 if (vector < 0)
85 panic("assign_irq_vector: out of interrupt vectors!");
86
87 return vector;
88}
89
80void 90void
81free_irq_vector (int vector) 91free_irq_vector (int vector)
82{ 92{
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 71147be3279c..376fcbc3f8da 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -480,14 +480,6 @@ typedef struct {
480#define PFM_CMD_ARG_MANY -1 /* cannot be zero */ 480#define PFM_CMD_ARG_MANY -1 /* cannot be zero */
481 481
482typedef struct { 482typedef struct {
483 int debug; /* turn on/off debugging via syslog */
484 int debug_ovfl; /* turn on/off debug printk in overflow handler */
485 int fastctxsw; /* turn on/off fast (unsecure) ctxsw */
486 int expert_mode; /* turn on/off value checking */
487 int debug_pfm_read;
488} pfm_sysctl_t;
489
490typedef struct {
491 unsigned long pfm_spurious_ovfl_intr_count; /* keep track of spurious ovfl interrupts */ 483 unsigned long pfm_spurious_ovfl_intr_count; /* keep track of spurious ovfl interrupts */
492 unsigned long pfm_replay_ovfl_intr_count; /* keep track of replayed ovfl interrupts */ 484 unsigned long pfm_replay_ovfl_intr_count; /* keep track of replayed ovfl interrupts */
493 unsigned long pfm_ovfl_intr_count; /* keep track of ovfl interrupts */ 485 unsigned long pfm_ovfl_intr_count; /* keep track of ovfl interrupts */
@@ -514,8 +506,8 @@ static LIST_HEAD(pfm_buffer_fmt_list);
514static pmu_config_t *pmu_conf; 506static pmu_config_t *pmu_conf;
515 507
516/* sysctl() controls */ 508/* sysctl() controls */
517static pfm_sysctl_t pfm_sysctl; 509pfm_sysctl_t pfm_sysctl;
518int pfm_debug_var; 510EXPORT_SYMBOL(pfm_sysctl);
519 511
520static ctl_table pfm_ctl_table[]={ 512static ctl_table pfm_ctl_table[]={
521 {1, "debug", &pfm_sysctl.debug, sizeof(int), 0666, NULL, &proc_dointvec, NULL,}, 513 {1, "debug", &pfm_sysctl.debug, sizeof(int), 0666, NULL, &proc_dointvec, NULL,},
@@ -1576,7 +1568,7 @@ pfm_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
1576 goto abort_locked; 1568 goto abort_locked;
1577 } 1569 }
1578 1570
1579 DPRINT(("[%d] fd=%d type=%d\n", current->pid, msg->pfm_gen_msg.msg_ctx_fd, msg->pfm_gen_msg.msg_type)); 1571 DPRINT(("fd=%d type=%d\n", msg->pfm_gen_msg.msg_ctx_fd, msg->pfm_gen_msg.msg_type));
1580 1572
1581 ret = -EFAULT; 1573 ret = -EFAULT;
1582 if(copy_to_user(buf, msg, sizeof(pfm_msg_t)) == 0) ret = sizeof(pfm_msg_t); 1574 if(copy_to_user(buf, msg, sizeof(pfm_msg_t)) == 0) ret = sizeof(pfm_msg_t);
@@ -3695,8 +3687,6 @@ pfm_debug(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
3695 3687
3696 pfm_sysctl.debug = m == 0 ? 0 : 1; 3688 pfm_sysctl.debug = m == 0 ? 0 : 1;
3697 3689
3698 pfm_debug_var = pfm_sysctl.debug;
3699
3700 printk(KERN_INFO "perfmon debugging %s (timing reset)\n", pfm_sysctl.debug ? "on" : "off"); 3690 printk(KERN_INFO "perfmon debugging %s (timing reset)\n", pfm_sysctl.debug ? "on" : "off");
3701 3691
3702 if (m == 0) { 3692 if (m == 0) {
@@ -4996,13 +4986,21 @@ pfm_context_force_terminate(pfm_context_t *ctx, struct pt_regs *regs)
4996} 4986}
4997 4987
4998static int pfm_ovfl_notify_user(pfm_context_t *ctx, unsigned long ovfl_pmds); 4988static int pfm_ovfl_notify_user(pfm_context_t *ctx, unsigned long ovfl_pmds);
4999 4989 /*
4990 * pfm_handle_work() can be called with interrupts enabled
4991 * (TIF_NEED_RESCHED) or disabled. The down_interruptible
4992 * call may sleep, therefore we must re-enable interrupts
4993 * to avoid deadlocks. It is safe to do so because this function
4994 * is called ONLY when returning to user level (PUStk=1), in which case
4995 * there is no risk of kernel stack overflow due to deep
4996 * interrupt nesting.
4997 */
5000void 4998void
5001pfm_handle_work(void) 4999pfm_handle_work(void)
5002{ 5000{
5003 pfm_context_t *ctx; 5001 pfm_context_t *ctx;
5004 struct pt_regs *regs; 5002 struct pt_regs *regs;
5005 unsigned long flags; 5003 unsigned long flags, dummy_flags;
5006 unsigned long ovfl_regs; 5004 unsigned long ovfl_regs;
5007 unsigned int reason; 5005 unsigned int reason;
5008 int ret; 5006 int ret;
@@ -5039,18 +5037,15 @@ pfm_handle_work(void)
5039 //if (CTX_OVFL_NOBLOCK(ctx)) goto skip_blocking; 5037 //if (CTX_OVFL_NOBLOCK(ctx)) goto skip_blocking;
5040 if (reason == PFM_TRAP_REASON_RESET) goto skip_blocking; 5038 if (reason == PFM_TRAP_REASON_RESET) goto skip_blocking;
5041 5039
5040 /*
5041 * restore interrupt mask to what it was on entry.
5042 * Could be enabled/diasbled.
5043 */
5042 UNPROTECT_CTX(ctx, flags); 5044 UNPROTECT_CTX(ctx, flags);
5043 5045
5044 /* 5046 /*
5045 * pfm_handle_work() is currently called with interrupts disabled. 5047 * force interrupt enable because of down_interruptible()
5046 * The down_interruptible call may sleep, therefore we 5048 */
5047 * must re-enable interrupts to avoid deadlocks. It is
5048 * safe to do so because this function is called ONLY
5049 * when returning to user level (PUStk=1), in which case
5050 * there is no risk of kernel stack overflow due to deep
5051 * interrupt nesting.
5052 */
5053 BUG_ON(flags & IA64_PSR_I);
5054 local_irq_enable(); 5049 local_irq_enable();
5055 5050
5056 DPRINT(("before block sleeping\n")); 5051 DPRINT(("before block sleeping\n"));
@@ -5064,12 +5059,12 @@ pfm_handle_work(void)
5064 DPRINT(("after block sleeping ret=%d\n", ret)); 5059 DPRINT(("after block sleeping ret=%d\n", ret));
5065 5060
5066 /* 5061 /*
5067 * disable interrupts to restore state we had upon entering 5062 * lock context and mask interrupts again
5068 * this function 5063 * We save flags into a dummy because we may have
5064 * altered interrupts mask compared to entry in this
5065 * function.
5069 */ 5066 */
5070 local_irq_disable(); 5067 PROTECT_CTX(ctx, dummy_flags);
5071
5072 PROTECT_CTX(ctx, flags);
5073 5068
5074 /* 5069 /*
5075 * we need to read the ovfl_regs only after wake-up 5070 * we need to read the ovfl_regs only after wake-up
@@ -5095,7 +5090,9 @@ skip_blocking:
5095 ctx->ctx_ovfl_regs[0] = 0UL; 5090 ctx->ctx_ovfl_regs[0] = 0UL;
5096 5091
5097nothing_to_do: 5092nothing_to_do:
5098 5093 /*
5094 * restore flags as they were upon entry
5095 */
5099 UNPROTECT_CTX(ctx, flags); 5096 UNPROTECT_CTX(ctx, flags);
5100} 5097}
5101 5098
diff --git a/arch/ia64/kernel/perfmon_default_smpl.c b/arch/ia64/kernel/perfmon_default_smpl.c
index 965d29004555..344941db0a9e 100644
--- a/arch/ia64/kernel/perfmon_default_smpl.c
+++ b/arch/ia64/kernel/perfmon_default_smpl.c
@@ -20,24 +20,17 @@ MODULE_AUTHOR("Stephane Eranian <eranian@hpl.hp.com>");
20MODULE_DESCRIPTION("perfmon default sampling format"); 20MODULE_DESCRIPTION("perfmon default sampling format");
21MODULE_LICENSE("GPL"); 21MODULE_LICENSE("GPL");
22 22
23MODULE_PARM(debug, "i");
24MODULE_PARM_DESC(debug, "debug");
25
26MODULE_PARM(debug_ovfl, "i");
27MODULE_PARM_DESC(debug_ovfl, "debug ovfl");
28
29
30#define DEFAULT_DEBUG 1 23#define DEFAULT_DEBUG 1
31 24
32#ifdef DEFAULT_DEBUG 25#ifdef DEFAULT_DEBUG
33#define DPRINT(a) \ 26#define DPRINT(a) \
34 do { \ 27 do { \
35 if (unlikely(debug >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk a; } \ 28 if (unlikely(pfm_sysctl.debug >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk a; } \
36 } while (0) 29 } while (0)
37 30
38#define DPRINT_ovfl(a) \ 31#define DPRINT_ovfl(a) \
39 do { \ 32 do { \
40 if (unlikely(debug_ovfl >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk a; } \ 33 if (unlikely(pfm_sysctl.debug > 0 && pfm_sysctl.debug_ovfl >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk a; } \
41 } while (0) 34 } while (0)
42 35
43#else 36#else
@@ -45,8 +38,6 @@ MODULE_PARM_DESC(debug_ovfl, "debug ovfl");
45#define DPRINT_ovfl(a) 38#define DPRINT_ovfl(a)
46#endif 39#endif
47 40
48static int debug, debug_ovfl;
49
50static int 41static int
51default_validate(struct task_struct *task, unsigned int flags, int cpu, void *data) 42default_validate(struct task_struct *task, unsigned int flags, int cpu, void *data)
52{ 43{
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index f05650c801d2..b7e6b4cb374b 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -4,10 +4,15 @@
4 * Copyright (C) 1998-2001, 2003-2004 Hewlett-Packard Co 4 * Copyright (C) 1998-2001, 2003-2004 Hewlett-Packard Co
5 * David Mosberger-Tang <davidm@hpl.hp.com> 5 * David Mosberger-Tang <davidm@hpl.hp.com>
6 * Stephane Eranian <eranian@hpl.hp.com> 6 * Stephane Eranian <eranian@hpl.hp.com>
7 * Copyright (C) 2000, Rohit Seth <rohit.seth@intel.com> 7 * Copyright (C) 2000, 2004 Intel Corp
8 * Rohit Seth <rohit.seth@intel.com>
9 * Suresh Siddha <suresh.b.siddha@intel.com>
10 * Gordon Jin <gordon.jin@intel.com>
8 * Copyright (C) 1999 VA Linux Systems 11 * Copyright (C) 1999 VA Linux Systems
9 * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> 12 * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
10 * 13 *
14 * 12/26/04 S.Siddha, G.Jin, R.Seth
15 * Add multi-threading and multi-core detection
11 * 11/12/01 D.Mosberger Convert get_cpuinfo() to seq_file based show_cpuinfo(). 16 * 11/12/01 D.Mosberger Convert get_cpuinfo() to seq_file based show_cpuinfo().
12 * 04/04/00 D.Mosberger renamed cpu_initialized to cpu_online_map 17 * 04/04/00 D.Mosberger renamed cpu_initialized to cpu_online_map
13 * 03/31/00 R.Seth cpu_initialized and current->processor fixes 18 * 03/31/00 R.Seth cpu_initialized and current->processor fixes
@@ -296,6 +301,34 @@ mark_bsp_online (void)
296#endif 301#endif
297} 302}
298 303
304#ifdef CONFIG_SMP
305static void
306check_for_logical_procs (void)
307{
308 pal_logical_to_physical_t info;
309 s64 status;
310
311 status = ia64_pal_logical_to_phys(0, &info);
312 if (status == -1) {
313 printk(KERN_INFO "No logical to physical processor mapping "
314 "available\n");
315 return;
316 }
317 if (status) {
318 printk(KERN_ERR "ia64_pal_logical_to_phys failed with %ld\n",
319 status);
320 return;
321 }
322 /*
323 * Total number of siblings that BSP has. Though not all of them
324 * may have booted successfully. The correct number of siblings
325 * booted is in info.overview_num_log.
326 */
327 smp_num_siblings = info.overview_tpc;
328 smp_num_cpucores = info.overview_cpp;
329}
330#endif
331
299void __init 332void __init
300setup_arch (char **cmdline_p) 333setup_arch (char **cmdline_p)
301{ 334{
@@ -356,6 +389,19 @@ setup_arch (char **cmdline_p)
356 389
357#ifdef CONFIG_SMP 390#ifdef CONFIG_SMP
358 cpu_physical_id(0) = hard_smp_processor_id(); 391 cpu_physical_id(0) = hard_smp_processor_id();
392
393 cpu_set(0, cpu_sibling_map[0]);
394 cpu_set(0, cpu_core_map[0]);
395
396 check_for_logical_procs();
397 if (smp_num_cpucores > 1)
398 printk(KERN_INFO
399 "cpu package is Multi-Core capable: number of cores=%d\n",
400 smp_num_cpucores);
401 if (smp_num_siblings > 1)
402 printk(KERN_INFO
403 "cpu package is Multi-Threading capable: number of siblings=%d\n",
404 smp_num_siblings);
359#endif 405#endif
360 406
361 cpu_init(); /* initialize the bootstrap CPU */ 407 cpu_init(); /* initialize the bootstrap CPU */
@@ -459,12 +505,23 @@ show_cpuinfo (struct seq_file *m, void *v)
459 "cpu regs : %u\n" 505 "cpu regs : %u\n"
460 "cpu MHz : %lu.%06lu\n" 506 "cpu MHz : %lu.%06lu\n"
461 "itc MHz : %lu.%06lu\n" 507 "itc MHz : %lu.%06lu\n"
462 "BogoMIPS : %lu.%02lu\n\n", 508 "BogoMIPS : %lu.%02lu\n",
463 cpunum, c->vendor, family, c->model, c->revision, c->archrev, 509 cpunum, c->vendor, family, c->model, c->revision, c->archrev,
464 features, c->ppn, c->number, 510 features, c->ppn, c->number,
465 c->proc_freq / 1000000, c->proc_freq % 1000000, 511 c->proc_freq / 1000000, c->proc_freq % 1000000,
466 c->itc_freq / 1000000, c->itc_freq % 1000000, 512 c->itc_freq / 1000000, c->itc_freq % 1000000,
467 lpj*HZ/500000, (lpj*HZ/5000) % 100); 513 lpj*HZ/500000, (lpj*HZ/5000) % 100);
514#ifdef CONFIG_SMP
515 seq_printf(m, "siblings : %u\n", c->num_log);
516 if (c->threads_per_core > 1 || c->cores_per_socket > 1)
517 seq_printf(m,
518 "physical id: %u\n"
519 "core id : %u\n"
520 "thread id : %u\n",
521 c->socket_id, c->core_id, c->thread_id);
522#endif
523 seq_printf(m,"\n");
524
468 return 0; 525 return 0;
469} 526}
470 527
@@ -533,6 +590,14 @@ identify_cpu (struct cpuinfo_ia64 *c)
533 memcpy(c->vendor, cpuid.field.vendor, 16); 590 memcpy(c->vendor, cpuid.field.vendor, 16);
534#ifdef CONFIG_SMP 591#ifdef CONFIG_SMP
535 c->cpu = smp_processor_id(); 592 c->cpu = smp_processor_id();
593
594 /* below default values will be overwritten by identify_siblings()
595 * for Multi-Threading/Multi-Core capable cpu's
596 */
597 c->threads_per_core = c->cores_per_socket = c->num_log = 1;
598 c->socket_id = -1;
599
600 identify_siblings(c);
536#endif 601#endif
537 c->ppn = cpuid.field.ppn; 602 c->ppn = cpuid.field.ppn;
538 c->number = cpuid.field.number; 603 c->number = cpuid.field.number;
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index ca1536db3394..0d5ee57c9865 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -1,8 +1,13 @@
1/* 1/*
2 * SMP boot-related support 2 * SMP boot-related support
3 * 3 *
4 * Copyright (C) 1998-2003 Hewlett-Packard Co 4 * Copyright (C) 1998-2003, 2005 Hewlett-Packard Co
5 * David Mosberger-Tang <davidm@hpl.hp.com> 5 * David Mosberger-Tang <davidm@hpl.hp.com>
6 * Copyright (C) 2001, 2004-2005 Intel Corp
7 * Rohit Seth <rohit.seth@intel.com>
8 * Suresh Siddha <suresh.b.siddha@intel.com>
9 * Gordon Jin <gordon.jin@intel.com>
10 * Ashok Raj <ashok.raj@intel.com>
6 * 11 *
7 * 01/05/16 Rohit Seth <rohit.seth@intel.com> Moved SMP booting functions from smp.c to here. 12 * 01/05/16 Rohit Seth <rohit.seth@intel.com> Moved SMP booting functions from smp.c to here.
8 * 01/04/27 David Mosberger <davidm@hpl.hp.com> Added ITC synching code. 13 * 01/04/27 David Mosberger <davidm@hpl.hp.com> Added ITC synching code.
@@ -10,6 +15,11 @@
10 * smp_boot_cpus()/smp_commence() is replaced by 15 * smp_boot_cpus()/smp_commence() is replaced by
11 * smp_prepare_cpus()/__cpu_up()/smp_cpus_done(). 16 * smp_prepare_cpus()/__cpu_up()/smp_cpus_done().
12 * 04/06/21 Ashok Raj <ashok.raj@intel.com> Added CPU Hotplug Support 17 * 04/06/21 Ashok Raj <ashok.raj@intel.com> Added CPU Hotplug Support
18 * 04/12/26 Jin Gordon <gordon.jin@intel.com>
19 * 04/12/26 Rohit Seth <rohit.seth@intel.com>
20 * Add multi-threading and multi-core detection
21 * 05/01/30 Suresh Siddha <suresh.b.siddha@intel.com>
22 * Setup cpu_sibling_map and cpu_core_map
13 */ 23 */
14#include <linux/config.h> 24#include <linux/config.h>
15 25
@@ -122,6 +132,11 @@ EXPORT_SYMBOL(cpu_online_map);
122cpumask_t cpu_possible_map; 132cpumask_t cpu_possible_map;
123EXPORT_SYMBOL(cpu_possible_map); 133EXPORT_SYMBOL(cpu_possible_map);
124 134
135cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
136cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
137int smp_num_siblings = 1;
138int smp_num_cpucores = 1;
139
125/* which logical CPU number maps to which CPU (physical APIC ID) */ 140/* which logical CPU number maps to which CPU (physical APIC ID) */
126volatile int ia64_cpu_to_sapicid[NR_CPUS]; 141volatile int ia64_cpu_to_sapicid[NR_CPUS];
127EXPORT_SYMBOL(ia64_cpu_to_sapicid); 142EXPORT_SYMBOL(ia64_cpu_to_sapicid);
@@ -156,7 +171,8 @@ sync_master (void *arg)
156 local_irq_save(flags); 171 local_irq_save(flags);
157 { 172 {
158 for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) { 173 for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) {
159 while (!go[MASTER]); 174 while (!go[MASTER])
175 cpu_relax();
160 go[MASTER] = 0; 176 go[MASTER] = 0;
161 go[SLAVE] = ia64_get_itc(); 177 go[SLAVE] = ia64_get_itc();
162 } 178 }
@@ -179,7 +195,8 @@ get_delta (long *rt, long *master)
179 for (i = 0; i < NUM_ITERS; ++i) { 195 for (i = 0; i < NUM_ITERS; ++i) {
180 t0 = ia64_get_itc(); 196 t0 = ia64_get_itc();
181 go[MASTER] = 1; 197 go[MASTER] = 1;
182 while (!(tm = go[SLAVE])); 198 while (!(tm = go[SLAVE]))
199 cpu_relax();
183 go[SLAVE] = 0; 200 go[SLAVE] = 0;
184 t1 = ia64_get_itc(); 201 t1 = ia64_get_itc();
185 202
@@ -258,7 +275,8 @@ ia64_sync_itc (unsigned int master)
258 return; 275 return;
259 } 276 }
260 277
261 while (go[MASTER]); /* wait for master to be ready */ 278 while (go[MASTER])
279 cpu_relax(); /* wait for master to be ready */
262 280
263 spin_lock_irqsave(&itc_sync_lock, flags); 281 spin_lock_irqsave(&itc_sync_lock, flags);
264 { 282 {
@@ -595,7 +613,68 @@ void __devinit smp_prepare_boot_cpu(void)
595 cpu_set(smp_processor_id(), cpu_callin_map); 613 cpu_set(smp_processor_id(), cpu_callin_map);
596} 614}
597 615
616/*
617 * mt_info[] is a temporary store for all info returned by
618 * PAL_LOGICAL_TO_PHYSICAL, to be copied into cpuinfo_ia64 when the
619 * specific cpu comes.
620 */
621static struct {
622 __u32 socket_id;
623 __u16 core_id;
624 __u16 thread_id;
625 __u16 proc_fixed_addr;
626 __u8 valid;
627}mt_info[NR_CPUS] __devinit;
628
598#ifdef CONFIG_HOTPLUG_CPU 629#ifdef CONFIG_HOTPLUG_CPU
630static inline void
631remove_from_mtinfo(int cpu)
632{
633 int i;
634
635 for_each_cpu(i)
636 if (mt_info[i].valid && mt_info[i].socket_id ==
637 cpu_data(cpu)->socket_id)
638 mt_info[i].valid = 0;
639}
640
641static inline void
642clear_cpu_sibling_map(int cpu)
643{
644 int i;
645
646 for_each_cpu_mask(i, cpu_sibling_map[cpu])
647 cpu_clear(cpu, cpu_sibling_map[i]);
648 for_each_cpu_mask(i, cpu_core_map[cpu])
649 cpu_clear(cpu, cpu_core_map[i]);
650
651 cpu_sibling_map[cpu] = cpu_core_map[cpu] = CPU_MASK_NONE;
652}
653
654static void
655remove_siblinginfo(int cpu)
656{
657 int last = 0;
658
659 if (cpu_data(cpu)->threads_per_core == 1 &&
660 cpu_data(cpu)->cores_per_socket == 1) {
661 cpu_clear(cpu, cpu_core_map[cpu]);
662 cpu_clear(cpu, cpu_sibling_map[cpu]);
663 return;
664 }
665
666 last = (cpus_weight(cpu_core_map[cpu]) == 1 ? 1 : 0);
667
668 /* remove it from all sibling map's */
669 clear_cpu_sibling_map(cpu);
670
671 /* if this cpu is the last in the core group, remove all its info
672 * from mt_info structure
673 */
674 if (last)
675 remove_from_mtinfo(cpu);
676}
677
599extern void fixup_irqs(void); 678extern void fixup_irqs(void);
600/* must be called with cpucontrol mutex held */ 679/* must be called with cpucontrol mutex held */
601int __cpu_disable(void) 680int __cpu_disable(void)
@@ -608,6 +687,7 @@ int __cpu_disable(void)
608 if (cpu == 0) 687 if (cpu == 0)
609 return -EBUSY; 688 return -EBUSY;
610 689
690 remove_siblinginfo(cpu);
611 fixup_irqs(); 691 fixup_irqs();
612 local_flush_tlb_all(); 692 local_flush_tlb_all();
613 cpu_clear(cpu, cpu_callin_map); 693 cpu_clear(cpu, cpu_callin_map);
@@ -660,6 +740,23 @@ smp_cpus_done (unsigned int dummy)
660 (int)num_online_cpus(), bogosum/(500000/HZ), (bogosum/(5000/HZ))%100); 740 (int)num_online_cpus(), bogosum/(500000/HZ), (bogosum/(5000/HZ))%100);
661} 741}
662 742
743static inline void __devinit
744set_cpu_sibling_map(int cpu)
745{
746 int i;
747
748 for_each_online_cpu(i) {
749 if ((cpu_data(cpu)->socket_id == cpu_data(i)->socket_id)) {
750 cpu_set(i, cpu_core_map[cpu]);
751 cpu_set(cpu, cpu_core_map[i]);
752 if (cpu_data(cpu)->core_id == cpu_data(i)->core_id) {
753 cpu_set(i, cpu_sibling_map[cpu]);
754 cpu_set(cpu, cpu_sibling_map[i]);
755 }
756 }
757 }
758}
759
663int __devinit 760int __devinit
664__cpu_up (unsigned int cpu) 761__cpu_up (unsigned int cpu)
665{ 762{
@@ -682,6 +779,15 @@ __cpu_up (unsigned int cpu)
682 if (ret < 0) 779 if (ret < 0)
683 return ret; 780 return ret;
684 781
782 if (cpu_data(cpu)->threads_per_core == 1 &&
783 cpu_data(cpu)->cores_per_socket == 1) {
784 cpu_set(cpu, cpu_sibling_map[cpu]);
785 cpu_set(cpu, cpu_core_map[cpu]);
786 return 0;
787 }
788
789 set_cpu_sibling_map(cpu);
790
685 return 0; 791 return 0;
686} 792}
687 793
@@ -709,3 +815,106 @@ init_smp_config(void)
709 ia64_sal_strerror(sal_ret)); 815 ia64_sal_strerror(sal_ret));
710} 816}
711 817
818static inline int __devinit
819check_for_mtinfo_index(void)
820{
821 int i;
822
823 for_each_cpu(i)
824 if (!mt_info[i].valid)
825 return i;
826
827 return -1;
828}
829
830/*
831 * Search the mt_info to find out if this socket's cid/tid information is
832 * cached or not. If the socket exists, fill in the core_id and thread_id
833 * in cpuinfo
834 */
835static int __devinit
836check_for_new_socket(__u16 logical_address, struct cpuinfo_ia64 *c)
837{
838 int i;
839 __u32 sid = c->socket_id;
840
841 for_each_cpu(i) {
842 if (mt_info[i].valid && mt_info[i].proc_fixed_addr == logical_address
843 && mt_info[i].socket_id == sid) {
844 c->core_id = mt_info[i].core_id;
845 c->thread_id = mt_info[i].thread_id;
846 return 1; /* not a new socket */
847 }
848 }
849 return 0;
850}
851
852/*
853 * identify_siblings(cpu) gets called from identify_cpu. This populates the
854 * information related to logical execution units in per_cpu_data structure.
855 */
856void __devinit
857identify_siblings(struct cpuinfo_ia64 *c)
858{
859 s64 status;
860 u16 pltid;
861 u64 proc_fixed_addr;
862 int count, i;
863 pal_logical_to_physical_t info;
864
865 if (smp_num_cpucores == 1 && smp_num_siblings == 1)
866 return;
867
868 if ((status = ia64_pal_logical_to_phys(0, &info)) != PAL_STATUS_SUCCESS) {
869 printk(KERN_ERR "ia64_pal_logical_to_phys failed with %ld\n",
870 status);
871 return;
872 }
873 if ((status = ia64_sal_physical_id_info(&pltid)) != PAL_STATUS_SUCCESS) {
874 printk(KERN_ERR "ia64_sal_pltid failed with %ld\n", status);
875 return;
876 }
877 if ((status = ia64_pal_fixed_addr(&proc_fixed_addr)) != PAL_STATUS_SUCCESS) {
878 printk(KERN_ERR "ia64_pal_fixed_addr failed with %ld\n", status);
879 return;
880 }
881
882 c->socket_id = (pltid << 8) | info.overview_ppid;
883 c->cores_per_socket = info.overview_cpp;
884 c->threads_per_core = info.overview_tpc;
885 count = c->num_log = info.overview_num_log;
886
887 /* If the thread and core id information is already cached, then
888 * we will simply update cpu_info and return. Otherwise, we will
889 * do the PAL calls and cache core and thread id's of all the siblings.
890 */
891 if (check_for_new_socket(proc_fixed_addr, c))
892 return;
893
894 for (i = 0; i < count; i++) {
895 int index;
896
897 if (i && (status = ia64_pal_logical_to_phys(i, &info))
898 != PAL_STATUS_SUCCESS) {
899 printk(KERN_ERR "ia64_pal_logical_to_phys failed"
900 " with %ld\n", status);
901 return;
902 }
903 if (info.log2_la == proc_fixed_addr) {
904 c->core_id = info.log1_cid;
905 c->thread_id = info.log1_tid;
906 }
907
908 index = check_for_mtinfo_index();
909 /* We will not do the mt_info caching optimization in this case.
910 */
911 if (index < 0)
912 continue;
913
914 mt_info[index].valid = 1;
915 mt_info[index].socket_id = c->socket_id;
916 mt_info[index].core_id = info.log1_cid;
917 mt_info[index].thread_id = info.log1_tid;
918 mt_info[index].proc_fixed_addr = info.log2_la;
919 }
920}
diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
index d494ff647cac..2776a074c6f1 100644
--- a/arch/ia64/kernel/unwind.c
+++ b/arch/ia64/kernel/unwind.c
@@ -1943,23 +1943,30 @@ EXPORT_SYMBOL(unw_unwind);
1943int 1943int
1944unw_unwind_to_user (struct unw_frame_info *info) 1944unw_unwind_to_user (struct unw_frame_info *info)
1945{ 1945{
1946 unsigned long ip, sp; 1946 unsigned long ip, sp, pr = 0;
1947 1947
1948 while (unw_unwind(info) >= 0) { 1948 while (unw_unwind(info) >= 0) {
1949 if (unw_get_rp(info, &ip) < 0) {
1950 unw_get_ip(info, &ip);
1951 UNW_DPRINT(0, "unwind.%s: failed to read return pointer (ip=0x%lx)\n",
1952 __FUNCTION__, ip);
1953 return -1;
1954 }
1955 unw_get_sp(info, &sp); 1949 unw_get_sp(info, &sp);
1956 if (sp >= (unsigned long)info->task + IA64_STK_OFFSET) 1950 if ((long)((unsigned long)info->task + IA64_STK_OFFSET - sp)
1951 < IA64_PT_REGS_SIZE) {
1952 UNW_DPRINT(0, "unwind.%s: ran off the top of the kernel stack\n",
1953 __FUNCTION__);
1957 break; 1954 break;
1958 if (ip < FIXADDR_USER_END) 1955 }
1956 if (unw_is_intr_frame(info) &&
1957 (pr & (1UL << PRED_USER_STACK)))
1959 return 0; 1958 return 0;
1959 if (unw_get_pr (info, &pr) < 0) {
1960 unw_get_rp(info, &ip);
1961 UNW_DPRINT(0, "unwind.%s: failed to read "
1962 "predicate register (ip=0x%lx)\n",
1963 __FUNCTION__, ip);
1964 return -1;
1965 }
1960 } 1966 }
1961 unw_get_ip(info, &ip); 1967 unw_get_ip(info, &ip);
1962 UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", __FUNCTION__, ip); 1968 UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n",
1969 __FUNCTION__, ip);
1963 return -1; 1970 return -1;
1964} 1971}
1965EXPORT_SYMBOL(unw_unwind_to_user); 1972EXPORT_SYMBOL(unw_unwind_to_user);