aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-06-14 18:09:26 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-06-14 18:09:26 -0400
commit0127d6d5d925321650e7b92364420325689a03ef (patch)
tree341c0d70c0c21829bc69d28dcdad55d8a90f2153 /arch
parent1e0e76cf1376a0a1b49a23396e945456c329814e (diff)
parentfc395f8d589f4f0b3fcdd9b8bb84b7cacf711a4f (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6: [SPARC64]: Fix args to sun4v_ldc_revoke(). [SPARC64]: Really fix parport. [SPARC64]: Fix IO/MEM space sizing for PCI. [SPARC64]: Wire up cookie based sun4v interrupt registry.
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc64/kernel/entry.S5
-rw-r--r--arch/sparc64/kernel/irq.c131
-rw-r--r--arch/sparc64/kernel/pci_common.c12
3 files changed, 134 insertions, 14 deletions
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index 7d1a11822a1e..8059531bf0ac 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -2357,8 +2357,9 @@ sun4v_ldc_unmap:
2357 nop 2357 nop
2358 .size sun4v_ldc_unmap, .-sun4v_ldc_unmap 2358 .size sun4v_ldc_unmap, .-sun4v_ldc_unmap
2359 2359
2360 /* %o0: cookie 2360 /* %o0: channel
2361 * %o1: mte_cookie 2361 * %o1: cookie
2362 * %o2: mte_cookie
2362 * 2363 *
2363 * returns %o0: status 2364 * returns %o0: status
2364 */ 2365 */
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index a36f8dd0c021..e60d283f60bc 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -1,7 +1,6 @@
1/* $Id: irq.c,v 1.114 2002/01/11 08:45:38 davem Exp $ 1/* irq.c: UltraSparc IRQ handling/init/registry.
2 * irq.c: UltraSparc IRQ handling/init/registry.
3 * 2 *
4 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) 3 * Copyright (C) 1997, 2007 David S. Miller (davem@davemloft.net)
5 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) 4 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
6 * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) 5 * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
7 */ 6 */
@@ -43,6 +42,7 @@
43#include <asm/cpudata.h> 42#include <asm/cpudata.h>
44#include <asm/auxio.h> 43#include <asm/auxio.h>
45#include <asm/head.h> 44#include <asm/head.h>
45#include <asm/hypervisor.h>
46 46
47/* UPA nodes send interrupt packet to UltraSparc with first data reg 47/* UPA nodes send interrupt packet to UltraSparc with first data reg
48 * value low 5 (7 on Starfire) bits holding the IRQ identifier being 48 * value low 5 (7 on Starfire) bits holding the IRQ identifier being
@@ -380,6 +380,76 @@ static void sun4v_irq_end(unsigned int virt_irq)
380 } 380 }
381} 381}
382 382
383static void sun4v_virq_enable(unsigned int virt_irq)
384{
385 struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
386 unsigned int ino = bucket - &ivector_table[0];
387
388 if (likely(bucket)) {
389 unsigned long cpuid, dev_handle, dev_ino;
390 int err;
391
392 cpuid = irq_choose_cpu(virt_irq);
393
394 dev_handle = ino & IMAP_IGN;
395 dev_ino = ino & IMAP_INO;
396
397 err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
398 if (err != HV_EOK)
399 printk("sun4v_vintr_set_target(%lx,%lx,%lu): "
400 "err(%d)\n",
401 dev_handle, dev_ino, cpuid, err);
402 err = sun4v_vintr_set_state(dev_handle, dev_ino,
403 HV_INTR_ENABLED);
404 if (err != HV_EOK)
405 printk("sun4v_vintr_set_state(%lx,%lx,"
406 "HV_INTR_ENABLED): err(%d)\n",
407 dev_handle, dev_ino, err);
408 }
409}
410
411static void sun4v_virq_disable(unsigned int virt_irq)
412{
413 struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
414 unsigned int ino = bucket - &ivector_table[0];
415
416 if (likely(bucket)) {
417 unsigned long dev_handle, dev_ino;
418 int err;
419
420 dev_handle = ino & IMAP_IGN;
421 dev_ino = ino & IMAP_INO;
422
423 err = sun4v_vintr_set_state(dev_handle, dev_ino,
424 HV_INTR_DISABLED);
425 if (err != HV_EOK)
426 printk("sun4v_vintr_set_state(%lx,%lx,"
427 "HV_INTR_DISABLED): err(%d)\n",
428 dev_handle, dev_ino, err);
429 }
430}
431
432static void sun4v_virq_end(unsigned int virt_irq)
433{
434 struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
435 unsigned int ino = bucket - &ivector_table[0];
436
437 if (likely(bucket)) {
438 unsigned long dev_handle, dev_ino;
439 int err;
440
441 dev_handle = ino & IMAP_IGN;
442 dev_ino = ino & IMAP_INO;
443
444 err = sun4v_vintr_set_state(dev_handle, dev_ino,
445 HV_INTR_STATE_IDLE);
446 if (err != HV_EOK)
447 printk("sun4v_vintr_set_state(%lx,%lx,"
448 "HV_INTR_STATE_IDLE): err(%d)\n",
449 dev_handle, dev_ino, err);
450 }
451}
452
383static void run_pre_handler(unsigned int virt_irq) 453static void run_pre_handler(unsigned int virt_irq)
384{ 454{
385 struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); 455 struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
@@ -434,6 +504,21 @@ static struct irq_chip sun4v_msi = {
434}; 504};
435#endif 505#endif
436 506
507static struct irq_chip sun4v_virq = {
508 .typename = "vsun4v",
509 .enable = sun4v_virq_enable,
510 .disable = sun4v_virq_disable,
511 .end = sun4v_virq_end,
512};
513
514static struct irq_chip sun4v_virq_ack = {
515 .typename = "vsun4v+ack",
516 .enable = sun4v_virq_enable,
517 .disable = sun4v_virq_disable,
518 .ack = run_pre_handler,
519 .end = sun4v_virq_end,
520};
521
437void irq_install_pre_handler(int virt_irq, 522void irq_install_pre_handler(int virt_irq,
438 void (*func)(unsigned int, void *, void *), 523 void (*func)(unsigned int, void *, void *),
439 void *arg1, void *arg2) 524 void *arg1, void *arg2)
@@ -447,7 +532,8 @@ void irq_install_pre_handler(int virt_irq,
447 532
448 chip = get_irq_chip(virt_irq); 533 chip = get_irq_chip(virt_irq);
449 if (chip == &sun4u_irq_ack || 534 if (chip == &sun4u_irq_ack ||
450 chip == &sun4v_irq_ack 535 chip == &sun4v_irq_ack ||
536 chip == &sun4v_virq_ack
451#ifdef CONFIG_PCI_MSI 537#ifdef CONFIG_PCI_MSI
452 || chip == &sun4v_msi 538 || chip == &sun4v_msi
453#endif 539#endif
@@ -455,7 +541,9 @@ void irq_install_pre_handler(int virt_irq,
455 return; 541 return;
456 542
457 chip = (chip == &sun4u_irq ? 543 chip = (chip == &sun4u_irq ?
458 &sun4u_irq_ack : &sun4v_irq_ack); 544 &sun4u_irq_ack :
545 (chip == &sun4v_irq ?
546 &sun4v_irq_ack : &sun4v_virq_ack));
459 set_irq_chip(virt_irq, chip); 547 set_irq_chip(virt_irq, chip);
460} 548}
461 549
@@ -492,19 +580,18 @@ out:
492 return bucket->virt_irq; 580 return bucket->virt_irq;
493} 581}
494 582
495unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) 583static unsigned int sun4v_build_common(unsigned long sysino,
584 struct irq_chip *chip)
496{ 585{
497 struct ino_bucket *bucket; 586 struct ino_bucket *bucket;
498 struct irq_handler_data *data; 587 struct irq_handler_data *data;
499 unsigned long sysino;
500 588
501 BUG_ON(tlb_type != hypervisor); 589 BUG_ON(tlb_type != hypervisor);
502 590
503 sysino = sun4v_devino_to_sysino(devhandle, devino);
504 bucket = &ivector_table[sysino]; 591 bucket = &ivector_table[sysino];
505 if (!bucket->virt_irq) { 592 if (!bucket->virt_irq) {
506 bucket->virt_irq = virt_irq_alloc(__irq(bucket)); 593 bucket->virt_irq = virt_irq_alloc(__irq(bucket));
507 set_irq_chip(bucket->virt_irq, &sun4v_irq); 594 set_irq_chip(bucket->virt_irq, chip);
508 } 595 }
509 596
510 data = get_irq_chip_data(bucket->virt_irq); 597 data = get_irq_chip_data(bucket->virt_irq);
@@ -529,6 +616,32 @@ out:
529 return bucket->virt_irq; 616 return bucket->virt_irq;
530} 617}
531 618
619unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino)
620{
621 unsigned long sysino = sun4v_devino_to_sysino(devhandle, devino);
622
623 return sun4v_build_common(sysino, &sun4v_irq);
624}
625
626unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
627{
628 unsigned long sysino, hv_err;
629
630 BUG_ON(devhandle & ~IMAP_IGN);
631 BUG_ON(devino & ~IMAP_INO);
632
633 sysino = devhandle | devino;
634
635 hv_err = sun4v_vintr_set_cookie(devhandle, devino, sysino);
636 if (hv_err) {
637 prom_printf("IRQ: Fatal, cannot set cookie for [%x:%x] "
638 "err=%lu\n", devhandle, devino, hv_err);
639 prom_halt();
640 }
641
642 return sun4v_build_common(sysino, &sun4v_virq);
643}
644
532#ifdef CONFIG_PCI_MSI 645#ifdef CONFIG_PCI_MSI
533unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p, 646unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p,
534 unsigned int msi_start, unsigned int msi_end) 647 unsigned int msi_start, unsigned int msi_end)
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
index f974fefc3ebc..4249214608af 100644
--- a/arch/sparc64/kernel/pci_common.c
+++ b/arch/sparc64/kernel/pci_common.c
@@ -291,8 +291,9 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm)
291 291
292 for (i = 0; i < num_pbm_ranges; i++) { 292 for (i = 0; i < num_pbm_ranges; i++) {
293 const struct linux_prom_pci_ranges *pr = &pbm_ranges[i]; 293 const struct linux_prom_pci_ranges *pr = &pbm_ranges[i];
294 unsigned long a; 294 unsigned long a, size;
295 u32 parent_phys_hi, parent_phys_lo; 295 u32 parent_phys_hi, parent_phys_lo;
296 u32 size_hi, size_lo;
296 int type; 297 int type;
297 298
298 parent_phys_hi = pr->parent_phys_hi; 299 parent_phys_hi = pr->parent_phys_hi;
@@ -300,9 +301,14 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm)
300 if (tlb_type == hypervisor) 301 if (tlb_type == hypervisor)
301 parent_phys_hi &= 0x0fffffff; 302 parent_phys_hi &= 0x0fffffff;
302 303
304 size_hi = pr->size_hi;
305 size_lo = pr->size_lo;
306
303 type = (pr->child_phys_hi >> 24) & 0x3; 307 type = (pr->child_phys_hi >> 24) & 0x3;
304 a = (((unsigned long)parent_phys_hi << 32UL) | 308 a = (((unsigned long)parent_phys_hi << 32UL) |
305 ((unsigned long)parent_phys_lo << 0UL)); 309 ((unsigned long)parent_phys_lo << 0UL));
310 size = (((unsigned long)size_hi << 32UL) |
311 ((unsigned long)size_lo << 0UL));
306 312
307 switch (type) { 313 switch (type) {
308 case 0: 314 case 0:
@@ -313,7 +319,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm)
313 case 1: 319 case 1:
314 /* 16-bit IO space, 16MB */ 320 /* 16-bit IO space, 16MB */
315 pbm->io_space.start = a; 321 pbm->io_space.start = a;
316 pbm->io_space.end = a + ((16UL*1024UL*1024UL) - 1UL); 322 pbm->io_space.end = a + size - 1UL;
317 pbm->io_space.flags = IORESOURCE_IO; 323 pbm->io_space.flags = IORESOURCE_IO;
318 saw_io = 1; 324 saw_io = 1;
319 break; 325 break;
@@ -321,7 +327,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm)
321 case 2: 327 case 2:
322 /* 32-bit MEM space, 2GB */ 328 /* 32-bit MEM space, 2GB */
323 pbm->mem_space.start = a; 329 pbm->mem_space.start = a;
324 pbm->mem_space.end = a + (0x80000000UL - 1UL); 330 pbm->mem_space.end = a + size - 1UL;
325 pbm->mem_space.flags = IORESOURCE_MEM; 331 pbm->mem_space.flags = IORESOURCE_MEM;
326 saw_mem = 1; 332 saw_mem = 1;
327 break; 333 break;