diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-06-14 18:09:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-06-14 18:09:26 -0400 |
commit | 0127d6d5d925321650e7b92364420325689a03ef (patch) | |
tree | 341c0d70c0c21829bc69d28dcdad55d8a90f2153 /arch | |
parent | 1e0e76cf1376a0a1b49a23396e945456c329814e (diff) | |
parent | fc395f8d589f4f0b3fcdd9b8bb84b7cacf711a4f (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.S | 5 | ||||
-rw-r--r-- | arch/sparc64/kernel/irq.c | 131 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_common.c | 12 |
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 | ||
383 | static 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 | |||
411 | static 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 | |||
432 | static 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 | |||
383 | static void run_pre_handler(unsigned int virt_irq) | 453 | static 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 | ||
507 | static 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 | |||
514 | static 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 | |||
437 | void irq_install_pre_handler(int virt_irq, | 522 | void 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 | ||
495 | unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) | 583 | static 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 | ||
619 | unsigned 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 | |||
626 | unsigned 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 |
533 | unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p, | 646 | unsigned 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; |