diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-05 13:13:03 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-05 13:13:03 -0400 |
| commit | 5e66dd6d66ffe758b39b6dcadf2330753ee1159b (patch) | |
| tree | a72cdcff4448e4af9425cc213ddf56ab23e697fe /arch/powerpc/sysdev/mpic.c | |
| parent | 026477c1141b67e98e3bd8bdedb7d4b88a3ecd09 (diff) | |
| parent | ca78f6baca863afe2e6a244a0fe94b3a70211d46 (diff) | |
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
| -rw-r--r-- | arch/powerpc/sysdev/mpic.c | 482 |
1 files changed, 292 insertions, 190 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 7e469358895f..7d31d7cc392d 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
| @@ -100,8 +100,8 @@ static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg) | |||
| 100 | 100 | ||
| 101 | if (mpic->flags & MPIC_PRIMARY) | 101 | if (mpic->flags & MPIC_PRIMARY) |
| 102 | cpu = hard_smp_processor_id(); | 102 | cpu = hard_smp_processor_id(); |
| 103 | 103 | return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, | |
| 104 | return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg); | 104 | mpic->cpuregs[cpu], reg); |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value) | 107 | static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value) |
| @@ -340,27 +340,19 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) | |||
| 340 | #endif /* CONFIG_MPIC_BROKEN_U3 */ | 340 | #endif /* CONFIG_MPIC_BROKEN_U3 */ |
| 341 | 341 | ||
| 342 | 342 | ||
| 343 | #define mpic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) | ||
| 344 | |||
| 343 | /* Find an mpic associated with a given linux interrupt */ | 345 | /* Find an mpic associated with a given linux interrupt */ |
| 344 | static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi) | 346 | static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi) |
| 345 | { | 347 | { |
| 346 | struct mpic *mpic = mpics; | 348 | unsigned int src = mpic_irq_to_hw(irq); |
| 347 | 349 | ||
| 348 | while(mpic) { | 350 | if (irq < NUM_ISA_INTERRUPTS) |
| 349 | /* search IPIs first since they may override the main interrupts */ | 351 | return NULL; |
| 350 | if (irq >= mpic->ipi_offset && irq < (mpic->ipi_offset + 4)) { | 352 | if (is_ipi) |
| 351 | if (is_ipi) | 353 | *is_ipi = (src >= MPIC_VEC_IPI_0 && src <= MPIC_VEC_IPI_3); |
| 352 | *is_ipi = 1; | 354 | |
| 353 | return mpic; | 355 | return irq_desc[irq].chip_data; |
| 354 | } | ||
| 355 | if (irq >= mpic->irq_offset && | ||
| 356 | irq < (mpic->irq_offset + mpic->irq_count)) { | ||
| 357 | if (is_ipi) | ||
| 358 | *is_ipi = 0; | ||
| 359 | return mpic; | ||
| 360 | } | ||
| 361 | mpic = mpic -> next; | ||
| 362 | } | ||
| 363 | return NULL; | ||
| 364 | } | 356 | } |
| 365 | 357 | ||
| 366 | /* Convert a cpu mask from logical to physical cpu numbers. */ | 358 | /* Convert a cpu mask from logical to physical cpu numbers. */ |
| @@ -378,14 +370,14 @@ static inline u32 mpic_physmask(u32 cpumask) | |||
| 378 | /* Get the mpic structure from the IPI number */ | 370 | /* Get the mpic structure from the IPI number */ |
| 379 | static inline struct mpic * mpic_from_ipi(unsigned int ipi) | 371 | static inline struct mpic * mpic_from_ipi(unsigned int ipi) |
| 380 | { | 372 | { |
| 381 | return container_of(irq_desc[ipi].chip, struct mpic, hc_ipi); | 373 | return irq_desc[ipi].chip_data; |
| 382 | } | 374 | } |
| 383 | #endif | 375 | #endif |
| 384 | 376 | ||
| 385 | /* Get the mpic structure from the irq number */ | 377 | /* Get the mpic structure from the irq number */ |
| 386 | static inline struct mpic * mpic_from_irq(unsigned int irq) | 378 | static inline struct mpic * mpic_from_irq(unsigned int irq) |
| 387 | { | 379 | { |
| 388 | return container_of(irq_desc[irq].chip, struct mpic, hc_irq); | 380 | return irq_desc[irq].chip_data; |
| 389 | } | 381 | } |
| 390 | 382 | ||
| 391 | /* Send an EOI */ | 383 | /* Send an EOI */ |
| @@ -398,9 +390,7 @@ static inline void mpic_eoi(struct mpic *mpic) | |||
| 398 | #ifdef CONFIG_SMP | 390 | #ifdef CONFIG_SMP |
| 399 | static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs) | 391 | static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs) |
| 400 | { | 392 | { |
| 401 | struct mpic *mpic = dev_id; | 393 | smp_message_recv(mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0, regs); |
| 402 | |||
| 403 | smp_message_recv(irq - mpic->ipi_offset, regs); | ||
| 404 | return IRQ_HANDLED; | 394 | return IRQ_HANDLED; |
| 405 | } | 395 | } |
| 406 | #endif /* CONFIG_SMP */ | 396 | #endif /* CONFIG_SMP */ |
| @@ -410,11 +400,11 @@ static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs) | |||
| 410 | */ | 400 | */ |
| 411 | 401 | ||
| 412 | 402 | ||
| 413 | static void mpic_enable_irq(unsigned int irq) | 403 | static void mpic_unmask_irq(unsigned int irq) |
| 414 | { | 404 | { |
| 415 | unsigned int loops = 100000; | 405 | unsigned int loops = 100000; |
| 416 | struct mpic *mpic = mpic_from_irq(irq); | 406 | struct mpic *mpic = mpic_from_irq(irq); |
| 417 | unsigned int src = irq - mpic->irq_offset; | 407 | unsigned int src = mpic_irq_to_hw(irq); |
| 418 | 408 | ||
| 419 | DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src); | 409 | DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src); |
| 420 | 410 | ||
| @@ -429,39 +419,13 @@ static void mpic_enable_irq(unsigned int irq) | |||
| 429 | break; | 419 | break; |
| 430 | } | 420 | } |
| 431 | } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK); | 421 | } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK); |
| 432 | |||
| 433 | #ifdef CONFIG_MPIC_BROKEN_U3 | ||
| 434 | if (mpic->flags & MPIC_BROKEN_U3) { | ||
| 435 | unsigned int src = irq - mpic->irq_offset; | ||
| 436 | if (mpic_is_ht_interrupt(mpic, src) && | ||
| 437 | (irq_desc[irq].status & IRQ_LEVEL)) | ||
| 438 | mpic_ht_end_irq(mpic, src); | ||
| 439 | } | ||
| 440 | #endif /* CONFIG_MPIC_BROKEN_U3 */ | ||
| 441 | } | ||
| 442 | |||
| 443 | static unsigned int mpic_startup_irq(unsigned int irq) | ||
| 444 | { | ||
| 445 | #ifdef CONFIG_MPIC_BROKEN_U3 | ||
| 446 | struct mpic *mpic = mpic_from_irq(irq); | ||
| 447 | unsigned int src = irq - mpic->irq_offset; | ||
| 448 | #endif /* CONFIG_MPIC_BROKEN_U3 */ | ||
| 449 | |||
| 450 | mpic_enable_irq(irq); | ||
| 451 | |||
| 452 | #ifdef CONFIG_MPIC_BROKEN_U3 | ||
| 453 | if (mpic_is_ht_interrupt(mpic, src)) | ||
| 454 | mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status); | ||
| 455 | #endif /* CONFIG_MPIC_BROKEN_U3 */ | ||
| 456 | |||
| 457 | return 0; | ||
| 458 | } | 422 | } |
| 459 | 423 | ||
| 460 | static void mpic_disable_irq(unsigned int irq) | 424 | static void mpic_mask_irq(unsigned int irq) |
| 461 | { | 425 | { |
| 462 | unsigned int loops = 100000; | 426 | unsigned int loops = 100000; |
| 463 | struct mpic *mpic = mpic_from_irq(irq); | 427 | struct mpic *mpic = mpic_from_irq(irq); |
| 464 | unsigned int src = irq - mpic->irq_offset; | 428 | unsigned int src = mpic_irq_to_hw(irq); |
| 465 | 429 | ||
| 466 | DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src); | 430 | DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src); |
| 467 | 431 | ||
| @@ -478,23 +442,58 @@ static void mpic_disable_irq(unsigned int irq) | |||
| 478 | } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK)); | 442 | } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK)); |
| 479 | } | 443 | } |
| 480 | 444 | ||
| 481 | static void mpic_shutdown_irq(unsigned int irq) | 445 | static void mpic_end_irq(unsigned int irq) |
| 482 | { | 446 | { |
| 447 | struct mpic *mpic = mpic_from_irq(irq); | ||
| 448 | |||
| 449 | #ifdef DEBUG_IRQ | ||
| 450 | DBG("%s: end_irq: %d\n", mpic->name, irq); | ||
| 451 | #endif | ||
| 452 | /* We always EOI on end_irq() even for edge interrupts since that | ||
| 453 | * should only lower the priority, the MPIC should have properly | ||
| 454 | * latched another edge interrupt coming in anyway | ||
| 455 | */ | ||
| 456 | |||
| 457 | mpic_eoi(mpic); | ||
| 458 | } | ||
| 459 | |||
| 483 | #ifdef CONFIG_MPIC_BROKEN_U3 | 460 | #ifdef CONFIG_MPIC_BROKEN_U3 |
| 461 | |||
| 462 | static void mpic_unmask_ht_irq(unsigned int irq) | ||
| 463 | { | ||
| 484 | struct mpic *mpic = mpic_from_irq(irq); | 464 | struct mpic *mpic = mpic_from_irq(irq); |
| 485 | unsigned int src = irq - mpic->irq_offset; | 465 | unsigned int src = mpic_irq_to_hw(irq); |
| 486 | 466 | ||
| 487 | if (mpic_is_ht_interrupt(mpic, src)) | 467 | mpic_unmask_irq(irq); |
| 488 | mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status); | ||
| 489 | 468 | ||
| 490 | #endif /* CONFIG_MPIC_BROKEN_U3 */ | 469 | if (irq_desc[irq].status & IRQ_LEVEL) |
| 470 | mpic_ht_end_irq(mpic, src); | ||
| 471 | } | ||
| 472 | |||
| 473 | static unsigned int mpic_startup_ht_irq(unsigned int irq) | ||
| 474 | { | ||
| 475 | struct mpic *mpic = mpic_from_irq(irq); | ||
| 476 | unsigned int src = mpic_irq_to_hw(irq); | ||
| 477 | |||
| 478 | mpic_unmask_irq(irq); | ||
| 479 | mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status); | ||
| 491 | 480 | ||
| 492 | mpic_disable_irq(irq); | 481 | return 0; |
| 493 | } | 482 | } |
| 494 | 483 | ||
| 495 | static void mpic_end_irq(unsigned int irq) | 484 | static void mpic_shutdown_ht_irq(unsigned int irq) |
| 496 | { | 485 | { |
| 497 | struct mpic *mpic = mpic_from_irq(irq); | 486 | struct mpic *mpic = mpic_from_irq(irq); |
| 487 | unsigned int src = mpic_irq_to_hw(irq); | ||
| 488 | |||
| 489 | mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status); | ||
| 490 | mpic_mask_irq(irq); | ||
| 491 | } | ||
| 492 | |||
| 493 | static void mpic_end_ht_irq(unsigned int irq) | ||
| 494 | { | ||
| 495 | struct mpic *mpic = mpic_from_irq(irq); | ||
| 496 | unsigned int src = mpic_irq_to_hw(irq); | ||
| 498 | 497 | ||
| 499 | #ifdef DEBUG_IRQ | 498 | #ifdef DEBUG_IRQ |
| 500 | DBG("%s: end_irq: %d\n", mpic->name, irq); | 499 | DBG("%s: end_irq: %d\n", mpic->name, irq); |
| @@ -504,30 +503,25 @@ static void mpic_end_irq(unsigned int irq) | |||
| 504 | * latched another edge interrupt coming in anyway | 503 | * latched another edge interrupt coming in anyway |
| 505 | */ | 504 | */ |
| 506 | 505 | ||
| 507 | #ifdef CONFIG_MPIC_BROKEN_U3 | 506 | if (irq_desc[irq].status & IRQ_LEVEL) |
| 508 | if (mpic->flags & MPIC_BROKEN_U3) { | 507 | mpic_ht_end_irq(mpic, src); |
| 509 | unsigned int src = irq - mpic->irq_offset; | ||
| 510 | if (mpic_is_ht_interrupt(mpic, src) && | ||
| 511 | (irq_desc[irq].status & IRQ_LEVEL)) | ||
| 512 | mpic_ht_end_irq(mpic, src); | ||
| 513 | } | ||
| 514 | #endif /* CONFIG_MPIC_BROKEN_U3 */ | ||
| 515 | |||
| 516 | mpic_eoi(mpic); | 508 | mpic_eoi(mpic); |
| 517 | } | 509 | } |
| 518 | 510 | ||
| 511 | #endif /* CONFIG_MPIC_BROKEN_U3 */ | ||
| 512 | |||
| 519 | #ifdef CONFIG_SMP | 513 | #ifdef CONFIG_SMP |
| 520 | 514 | ||
| 521 | static void mpic_enable_ipi(unsigned int irq) | 515 | static void mpic_unmask_ipi(unsigned int irq) |
| 522 | { | 516 | { |
| 523 | struct mpic *mpic = mpic_from_ipi(irq); | 517 | struct mpic *mpic = mpic_from_ipi(irq); |
| 524 | unsigned int src = irq - mpic->ipi_offset; | 518 | unsigned int src = mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0; |
| 525 | 519 | ||
| 526 | DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src); | 520 | DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src); |
| 527 | mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK); | 521 | mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK); |
| 528 | } | 522 | } |
| 529 | 523 | ||
| 530 | static void mpic_disable_ipi(unsigned int irq) | 524 | static void mpic_mask_ipi(unsigned int irq) |
| 531 | { | 525 | { |
| 532 | /* NEVER disable an IPI... that's just plain wrong! */ | 526 | /* NEVER disable an IPI... that's just plain wrong! */ |
| 533 | } | 527 | } |
| @@ -551,29 +545,176 @@ static void mpic_end_ipi(unsigned int irq) | |||
| 551 | static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask) | 545 | static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask) |
| 552 | { | 546 | { |
| 553 | struct mpic *mpic = mpic_from_irq(irq); | 547 | struct mpic *mpic = mpic_from_irq(irq); |
| 548 | unsigned int src = mpic_irq_to_hw(irq); | ||
| 554 | 549 | ||
| 555 | cpumask_t tmp; | 550 | cpumask_t tmp; |
| 556 | 551 | ||
| 557 | cpus_and(tmp, cpumask, cpu_online_map); | 552 | cpus_and(tmp, cpumask, cpu_online_map); |
| 558 | 553 | ||
| 559 | mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_DESTINATION, | 554 | mpic_irq_write(src, MPIC_IRQ_DESTINATION, |
| 560 | mpic_physmask(cpus_addr(tmp)[0])); | 555 | mpic_physmask(cpus_addr(tmp)[0])); |
| 561 | } | 556 | } |
| 562 | 557 | ||
| 558 | static unsigned int mpic_flags_to_vecpri(unsigned int flags, int *level) | ||
| 559 | { | ||
| 560 | unsigned int vecpri; | ||
| 561 | |||
| 562 | /* Now convert sense value */ | ||
| 563 | switch(flags & IRQ_TYPE_SENSE_MASK) { | ||
| 564 | case IRQ_TYPE_EDGE_RISING: | ||
| 565 | vecpri = MPIC_VECPRI_SENSE_EDGE | | ||
| 566 | MPIC_VECPRI_POLARITY_POSITIVE; | ||
| 567 | *level = 0; | ||
| 568 | break; | ||
| 569 | case IRQ_TYPE_EDGE_FALLING: | ||
| 570 | vecpri = MPIC_VECPRI_SENSE_EDGE | | ||
| 571 | MPIC_VECPRI_POLARITY_NEGATIVE; | ||
| 572 | *level = 0; | ||
| 573 | break; | ||
| 574 | case IRQ_TYPE_LEVEL_HIGH: | ||
| 575 | vecpri = MPIC_VECPRI_SENSE_LEVEL | | ||
| 576 | MPIC_VECPRI_POLARITY_POSITIVE; | ||
| 577 | *level = 1; | ||
| 578 | break; | ||
| 579 | case IRQ_TYPE_LEVEL_LOW: | ||
| 580 | default: | ||
| 581 | vecpri = MPIC_VECPRI_SENSE_LEVEL | | ||
| 582 | MPIC_VECPRI_POLARITY_NEGATIVE; | ||
| 583 | *level = 1; | ||
| 584 | } | ||
| 585 | return vecpri; | ||
| 586 | } | ||
| 587 | |||
| 588 | static struct irq_chip mpic_irq_chip = { | ||
| 589 | .mask = mpic_mask_irq, | ||
| 590 | .unmask = mpic_unmask_irq, | ||
| 591 | .eoi = mpic_end_irq, | ||
| 592 | }; | ||
| 593 | |||
| 594 | #ifdef CONFIG_SMP | ||
| 595 | static struct irq_chip mpic_ipi_chip = { | ||
| 596 | .mask = mpic_mask_ipi, | ||
| 597 | .unmask = mpic_unmask_ipi, | ||
| 598 | .eoi = mpic_end_ipi, | ||
| 599 | }; | ||
| 600 | #endif /* CONFIG_SMP */ | ||
| 601 | |||
| 602 | #ifdef CONFIG_MPIC_BROKEN_U3 | ||
| 603 | static struct irq_chip mpic_irq_ht_chip = { | ||
| 604 | .startup = mpic_startup_ht_irq, | ||
| 605 | .shutdown = mpic_shutdown_ht_irq, | ||
| 606 | .mask = mpic_mask_irq, | ||
| 607 | .unmask = mpic_unmask_ht_irq, | ||
| 608 | .eoi = mpic_end_ht_irq, | ||
| 609 | }; | ||
| 610 | #endif /* CONFIG_MPIC_BROKEN_U3 */ | ||
| 611 | |||
| 612 | |||
| 613 | static int mpic_host_match(struct irq_host *h, struct device_node *node) | ||
| 614 | { | ||
| 615 | struct mpic *mpic = h->host_data; | ||
| 616 | |||
| 617 | /* Exact match, unless mpic node is NULL */ | ||
| 618 | return mpic->of_node == NULL || mpic->of_node == node; | ||
| 619 | } | ||
| 620 | |||
| 621 | static int mpic_host_map(struct irq_host *h, unsigned int virq, | ||
| 622 | irq_hw_number_t hw, unsigned int flags) | ||
| 623 | { | ||
| 624 | struct irq_desc *desc = get_irq_desc(virq); | ||
| 625 | struct irq_chip *chip; | ||
| 626 | struct mpic *mpic = h->host_data; | ||
| 627 | unsigned int vecpri = MPIC_VECPRI_SENSE_LEVEL | | ||
| 628 | MPIC_VECPRI_POLARITY_NEGATIVE; | ||
| 629 | int level; | ||
| 630 | |||
| 631 | pr_debug("mpic: map virq %d, hwirq 0x%lx, flags: 0x%x\n", | ||
| 632 | virq, hw, flags); | ||
| 633 | |||
| 634 | if (hw == MPIC_VEC_SPURRIOUS) | ||
| 635 | return -EINVAL; | ||
| 636 | #ifdef CONFIG_SMP | ||
| 637 | else if (hw >= MPIC_VEC_IPI_0) { | ||
| 638 | WARN_ON(!(mpic->flags & MPIC_PRIMARY)); | ||
| 639 | |||
| 640 | pr_debug("mpic: mapping as IPI\n"); | ||
| 641 | set_irq_chip_data(virq, mpic); | ||
| 642 | set_irq_chip_and_handler(virq, &mpic->hc_ipi, | ||
| 643 | handle_percpu_irq); | ||
| 644 | return 0; | ||
| 645 | } | ||
| 646 | #endif /* CONFIG_SMP */ | ||
| 647 | |||
| 648 | if (hw >= mpic->irq_count) | ||
| 649 | return -EINVAL; | ||
| 650 | |||
| 651 | /* If no sense provided, check default sense array */ | ||
| 652 | if (((flags & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_NONE) && | ||
| 653 | mpic->senses && hw < mpic->senses_count) | ||
| 654 | flags |= mpic->senses[hw]; | ||
| 655 | |||
| 656 | vecpri = mpic_flags_to_vecpri(flags, &level); | ||
| 657 | if (level) | ||
| 658 | desc->status |= IRQ_LEVEL; | ||
| 659 | chip = &mpic->hc_irq; | ||
| 660 | |||
| 661 | #ifdef CONFIG_MPIC_BROKEN_U3 | ||
| 662 | /* Check for HT interrupts, override vecpri */ | ||
| 663 | if (mpic_is_ht_interrupt(mpic, hw)) { | ||
| 664 | vecpri &= ~(MPIC_VECPRI_SENSE_MASK | | ||
| 665 | MPIC_VECPRI_POLARITY_MASK); | ||
| 666 | vecpri |= MPIC_VECPRI_POLARITY_POSITIVE; | ||
| 667 | chip = &mpic->hc_ht_irq; | ||
| 668 | } | ||
| 669 | #endif | ||
| 670 | |||
| 671 | /* Reconfigure irq */ | ||
| 672 | vecpri |= MPIC_VECPRI_MASK | hw | (8 << MPIC_VECPRI_PRIORITY_SHIFT); | ||
| 673 | mpic_irq_write(hw, MPIC_IRQ_VECTOR_PRI, vecpri); | ||
| 674 | |||
| 675 | pr_debug("mpic: mapping as IRQ\n"); | ||
| 676 | |||
| 677 | set_irq_chip_data(virq, mpic); | ||
| 678 | set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq); | ||
| 679 | return 0; | ||
| 680 | } | ||
| 681 | |||
| 682 | static int mpic_host_xlate(struct irq_host *h, struct device_node *ct, | ||
| 683 | u32 *intspec, unsigned int intsize, | ||
| 684 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) | ||
| 685 | |||
| 686 | { | ||
| 687 | static unsigned char map_mpic_senses[4] = { | ||
| 688 | IRQ_TYPE_EDGE_RISING, | ||
| 689 | IRQ_TYPE_LEVEL_LOW, | ||
| 690 | IRQ_TYPE_LEVEL_HIGH, | ||
| 691 | IRQ_TYPE_EDGE_FALLING, | ||
| 692 | }; | ||
| 693 | |||
| 694 | *out_hwirq = intspec[0]; | ||
| 695 | if (intsize > 1 && intspec[1] < 4) | ||
| 696 | *out_flags = map_mpic_senses[intspec[1]]; | ||
| 697 | else | ||
| 698 | *out_flags = IRQ_TYPE_NONE; | ||
| 699 | |||
| 700 | return 0; | ||
| 701 | } | ||
| 702 | |||
| 703 | static struct irq_host_ops mpic_host_ops = { | ||
| 704 | .match = mpic_host_match, | ||
| 705 | .map = mpic_host_map, | ||
| 706 | .xlate = mpic_host_xlate, | ||
| 707 | }; | ||
| 563 | 708 | ||
| 564 | /* | 709 | /* |
| 565 | * Exported functions | 710 | * Exported functions |
| 566 | */ | 711 | */ |
| 567 | 712 | ||
| 568 | 713 | struct mpic * __init mpic_alloc(struct device_node *node, | |
| 569 | struct mpic * __init mpic_alloc(unsigned long phys_addr, | 714 | unsigned long phys_addr, |
| 570 | unsigned int flags, | 715 | unsigned int flags, |
| 571 | unsigned int isu_size, | 716 | unsigned int isu_size, |
| 572 | unsigned int irq_offset, | ||
| 573 | unsigned int irq_count, | 717 | unsigned int irq_count, |
| 574 | unsigned int ipi_offset, | ||
| 575 | unsigned char *senses, | ||
| 576 | unsigned int senses_count, | ||
| 577 | const char *name) | 718 | const char *name) |
| 578 | { | 719 | { |
| 579 | struct mpic *mpic; | 720 | struct mpic *mpic; |
| @@ -585,33 +726,38 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr, | |||
| 585 | if (mpic == NULL) | 726 | if (mpic == NULL) |
| 586 | return NULL; | 727 | return NULL; |
| 587 | 728 | ||
| 588 | |||
| 589 | memset(mpic, 0, sizeof(struct mpic)); | 729 | memset(mpic, 0, sizeof(struct mpic)); |
| 590 | mpic->name = name; | 730 | mpic->name = name; |
| 731 | mpic->of_node = node ? of_node_get(node) : NULL; | ||
| 591 | 732 | ||
| 733 | mpic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 256, | ||
| 734 | &mpic_host_ops, | ||
| 735 | MPIC_VEC_SPURRIOUS); | ||
| 736 | if (mpic->irqhost == NULL) { | ||
| 737 | of_node_put(node); | ||
| 738 | return NULL; | ||
| 739 | } | ||
| 740 | |||
| 741 | mpic->irqhost->host_data = mpic; | ||
| 742 | mpic->hc_irq = mpic_irq_chip; | ||
| 592 | mpic->hc_irq.typename = name; | 743 | mpic->hc_irq.typename = name; |
| 593 | mpic->hc_irq.startup = mpic_startup_irq; | ||
| 594 | mpic->hc_irq.shutdown = mpic_shutdown_irq; | ||
| 595 | mpic->hc_irq.enable = mpic_enable_irq; | ||
| 596 | mpic->hc_irq.disable = mpic_disable_irq; | ||
| 597 | mpic->hc_irq.end = mpic_end_irq; | ||
| 598 | if (flags & MPIC_PRIMARY) | 744 | if (flags & MPIC_PRIMARY) |
| 599 | mpic->hc_irq.set_affinity = mpic_set_affinity; | 745 | mpic->hc_irq.set_affinity = mpic_set_affinity; |
| 746 | #ifdef CONFIG_MPIC_BROKEN_U3 | ||
| 747 | mpic->hc_ht_irq = mpic_irq_ht_chip; | ||
| 748 | mpic->hc_ht_irq.typename = name; | ||
| 749 | if (flags & MPIC_PRIMARY) | ||
| 750 | mpic->hc_ht_irq.set_affinity = mpic_set_affinity; | ||
| 751 | #endif /* CONFIG_MPIC_BROKEN_U3 */ | ||
| 600 | #ifdef CONFIG_SMP | 752 | #ifdef CONFIG_SMP |
| 753 | mpic->hc_ipi = mpic_ipi_chip; | ||
| 601 | mpic->hc_ipi.typename = name; | 754 | mpic->hc_ipi.typename = name; |
| 602 | mpic->hc_ipi.enable = mpic_enable_ipi; | ||
| 603 | mpic->hc_ipi.disable = mpic_disable_ipi; | ||
| 604 | mpic->hc_ipi.end = mpic_end_ipi; | ||
| 605 | #endif /* CONFIG_SMP */ | 755 | #endif /* CONFIG_SMP */ |
| 606 | 756 | ||
| 607 | mpic->flags = flags; | 757 | mpic->flags = flags; |
| 608 | mpic->isu_size = isu_size; | 758 | mpic->isu_size = isu_size; |
| 609 | mpic->irq_offset = irq_offset; | ||
| 610 | mpic->irq_count = irq_count; | 759 | mpic->irq_count = irq_count; |
| 611 | mpic->ipi_offset = ipi_offset; | ||
| 612 | mpic->num_sources = 0; /* so far */ | 760 | mpic->num_sources = 0; /* so far */ |
| 613 | mpic->senses = senses; | ||
| 614 | mpic->senses_count = senses_count; | ||
| 615 | 761 | ||
| 616 | /* Map the global registers */ | 762 | /* Map the global registers */ |
| 617 | mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000); | 763 | mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000); |
| @@ -679,8 +825,10 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr, | |||
| 679 | mpic->next = mpics; | 825 | mpic->next = mpics; |
| 680 | mpics = mpic; | 826 | mpics = mpic; |
| 681 | 827 | ||
| 682 | if (flags & MPIC_PRIMARY) | 828 | if (flags & MPIC_PRIMARY) { |
| 683 | mpic_primary = mpic; | 829 | mpic_primary = mpic; |
| 830 | irq_set_default_host(mpic->irqhost); | ||
| 831 | } | ||
| 684 | 832 | ||
| 685 | return mpic; | 833 | return mpic; |
| 686 | } | 834 | } |
| @@ -697,26 +845,10 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, | |||
| 697 | mpic->num_sources = isu_first + mpic->isu_size; | 845 | mpic->num_sources = isu_first + mpic->isu_size; |
| 698 | } | 846 | } |
| 699 | 847 | ||
| 700 | void __init mpic_setup_cascade(unsigned int irq, mpic_cascade_t handler, | 848 | void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count) |
| 701 | void *data) | ||
| 702 | { | 849 | { |
| 703 | struct mpic *mpic = mpic_find(irq, NULL); | 850 | mpic->senses = senses; |
| 704 | unsigned long flags; | 851 | mpic->senses_count = count; |
| 705 | |||
| 706 | /* Synchronization here is a bit dodgy, so don't try to replace cascade | ||
| 707 | * interrupts on the fly too often ... but normally it's set up at boot. | ||
| 708 | */ | ||
| 709 | spin_lock_irqsave(&mpic_lock, flags); | ||
| 710 | if (mpic->cascade) | ||
| 711 | mpic_disable_irq(mpic->cascade_vec + mpic->irq_offset); | ||
| 712 | mpic->cascade = NULL; | ||
| 713 | wmb(); | ||
| 714 | mpic->cascade_vec = irq - mpic->irq_offset; | ||
| 715 | mpic->cascade_data = data; | ||
| 716 | wmb(); | ||
| 717 | mpic->cascade = handler; | ||
| 718 | mpic_enable_irq(irq); | ||
| 719 | spin_unlock_irqrestore(&mpic_lock, flags); | ||
| 720 | } | 852 | } |
| 721 | 853 | ||
| 722 | void __init mpic_init(struct mpic *mpic) | 854 | void __init mpic_init(struct mpic *mpic) |
| @@ -724,6 +856,11 @@ void __init mpic_init(struct mpic *mpic) | |||
| 724 | int i; | 856 | int i; |
| 725 | 857 | ||
| 726 | BUG_ON(mpic->num_sources == 0); | 858 | BUG_ON(mpic->num_sources == 0); |
| 859 | WARN_ON(mpic->num_sources > MPIC_VEC_IPI_0); | ||
| 860 | |||
| 861 | /* Sanitize source count */ | ||
| 862 | if (mpic->num_sources > MPIC_VEC_IPI_0) | ||
| 863 | mpic->num_sources = MPIC_VEC_IPI_0; | ||
| 727 | 864 | ||
| 728 | printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources); | 865 | printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources); |
| 729 | 866 | ||
| @@ -747,12 +884,6 @@ void __init mpic_init(struct mpic *mpic) | |||
| 747 | MPIC_VECPRI_MASK | | 884 | MPIC_VECPRI_MASK | |
| 748 | (10 << MPIC_VECPRI_PRIORITY_SHIFT) | | 885 | (10 << MPIC_VECPRI_PRIORITY_SHIFT) | |
| 749 | (MPIC_VEC_IPI_0 + i)); | 886 | (MPIC_VEC_IPI_0 + i)); |
| 750 | #ifdef CONFIG_SMP | ||
| 751 | if (!(mpic->flags & MPIC_PRIMARY)) | ||
| 752 | continue; | ||
| 753 | irq_desc[mpic->ipi_offset+i].status |= IRQ_PER_CPU; | ||
| 754 | irq_desc[mpic->ipi_offset+i].chip = &mpic->hc_ipi; | ||
| 755 | #endif /* CONFIG_SMP */ | ||
| 756 | } | 887 | } |
| 757 | 888 | ||
| 758 | /* Initialize interrupt sources */ | 889 | /* Initialize interrupt sources */ |
| @@ -763,31 +894,21 @@ void __init mpic_init(struct mpic *mpic) | |||
| 763 | /* Do the HT PIC fixups on U3 broken mpic */ | 894 | /* Do the HT PIC fixups on U3 broken mpic */ |
| 764 | DBG("MPIC flags: %x\n", mpic->flags); | 895 | DBG("MPIC flags: %x\n", mpic->flags); |
| 765 | if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY)) | 896 | if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY)) |
| 766 | mpic_scan_ht_pics(mpic); | 897 | mpic_scan_ht_pics(mpic); |
| 767 | #endif /* CONFIG_MPIC_BROKEN_U3 */ | 898 | #endif /* CONFIG_MPIC_BROKEN_U3 */ |
| 768 | 899 | ||
| 769 | for (i = 0; i < mpic->num_sources; i++) { | 900 | for (i = 0; i < mpic->num_sources; i++) { |
| 770 | /* start with vector = source number, and masked */ | 901 | /* start with vector = source number, and masked */ |
| 771 | u32 vecpri = MPIC_VECPRI_MASK | i | (8 << MPIC_VECPRI_PRIORITY_SHIFT); | 902 | u32 vecpri = MPIC_VECPRI_MASK | i | (8 << MPIC_VECPRI_PRIORITY_SHIFT); |
| 772 | int level = 0; | 903 | int level = 1; |
| 773 | 904 | ||
| 774 | /* if it's an IPI, we skip it */ | ||
| 775 | if ((mpic->irq_offset + i) >= (mpic->ipi_offset + i) && | ||
| 776 | (mpic->irq_offset + i) < (mpic->ipi_offset + i + 4)) | ||
| 777 | continue; | ||
| 778 | |||
| 779 | /* do senses munging */ | 905 | /* do senses munging */ |
| 780 | if (mpic->senses && i < mpic->senses_count) { | 906 | if (mpic->senses && i < mpic->senses_count) |
| 781 | if (mpic->senses[i] & IRQ_SENSE_LEVEL) | 907 | vecpri = mpic_flags_to_vecpri(mpic->senses[i], |
| 782 | vecpri |= MPIC_VECPRI_SENSE_LEVEL; | 908 | &level); |
| 783 | if (mpic->senses[i] & IRQ_POLARITY_POSITIVE) | 909 | else |
| 784 | vecpri |= MPIC_VECPRI_POLARITY_POSITIVE; | ||
| 785 | } else | ||
| 786 | vecpri |= MPIC_VECPRI_SENSE_LEVEL; | 910 | vecpri |= MPIC_VECPRI_SENSE_LEVEL; |
| 787 | 911 | ||
| 788 | /* remember if it was a level interrupts */ | ||
| 789 | level = (vecpri & MPIC_VECPRI_SENSE_LEVEL); | ||
| 790 | |||
| 791 | /* deal with broken U3 */ | 912 | /* deal with broken U3 */ |
| 792 | if (mpic->flags & MPIC_BROKEN_U3) { | 913 | if (mpic->flags & MPIC_BROKEN_U3) { |
| 793 | #ifdef CONFIG_MPIC_BROKEN_U3 | 914 | #ifdef CONFIG_MPIC_BROKEN_U3 |
| @@ -808,12 +929,6 @@ void __init mpic_init(struct mpic *mpic) | |||
| 808 | mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri); | 929 | mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri); |
| 809 | mpic_irq_write(i, MPIC_IRQ_DESTINATION, | 930 | mpic_irq_write(i, MPIC_IRQ_DESTINATION, |
| 810 | 1 << hard_smp_processor_id()); | 931 | 1 << hard_smp_processor_id()); |
| 811 | |||
| 812 | /* init linux descriptors */ | ||
| 813 | if (i < mpic->irq_count) { | ||
| 814 | irq_desc[mpic->irq_offset+i].status = level ? IRQ_LEVEL : 0; | ||
| 815 | irq_desc[mpic->irq_offset+i].chip = &mpic->hc_irq; | ||
| 816 | } | ||
| 817 | } | 932 | } |
| 818 | 933 | ||
| 819 | /* Init spurrious vector */ | 934 | /* Init spurrious vector */ |
| @@ -854,19 +969,20 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri) | |||
| 854 | { | 969 | { |
| 855 | int is_ipi; | 970 | int is_ipi; |
| 856 | struct mpic *mpic = mpic_find(irq, &is_ipi); | 971 | struct mpic *mpic = mpic_find(irq, &is_ipi); |
| 972 | unsigned int src = mpic_irq_to_hw(irq); | ||
| 857 | unsigned long flags; | 973 | unsigned long flags; |
| 858 | u32 reg; | 974 | u32 reg; |
| 859 | 975 | ||
| 860 | spin_lock_irqsave(&mpic_lock, flags); | 976 | spin_lock_irqsave(&mpic_lock, flags); |
| 861 | if (is_ipi) { | 977 | if (is_ipi) { |
| 862 | reg = mpic_ipi_read(irq - mpic->ipi_offset) & | 978 | reg = mpic_ipi_read(src - MPIC_VEC_IPI_0) & |
| 863 | ~MPIC_VECPRI_PRIORITY_MASK; | 979 | ~MPIC_VECPRI_PRIORITY_MASK; |
| 864 | mpic_ipi_write(irq - mpic->ipi_offset, | 980 | mpic_ipi_write(src - MPIC_VEC_IPI_0, |
| 865 | reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); | 981 | reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); |
| 866 | } else { | 982 | } else { |
| 867 | reg = mpic_irq_read(irq - mpic->irq_offset,MPIC_IRQ_VECTOR_PRI) | 983 | reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) |
| 868 | & ~MPIC_VECPRI_PRIORITY_MASK; | 984 | & ~MPIC_VECPRI_PRIORITY_MASK; |
| 869 | mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI, | 985 | mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, |
| 870 | reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); | 986 | reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); |
| 871 | } | 987 | } |
| 872 | spin_unlock_irqrestore(&mpic_lock, flags); | 988 | spin_unlock_irqrestore(&mpic_lock, flags); |
| @@ -876,14 +992,15 @@ unsigned int mpic_irq_get_priority(unsigned int irq) | |||
| 876 | { | 992 | { |
| 877 | int is_ipi; | 993 | int is_ipi; |
| 878 | struct mpic *mpic = mpic_find(irq, &is_ipi); | 994 | struct mpic *mpic = mpic_find(irq, &is_ipi); |
| 995 | unsigned int src = mpic_irq_to_hw(irq); | ||
| 879 | unsigned long flags; | 996 | unsigned long flags; |
| 880 | u32 reg; | 997 | u32 reg; |
| 881 | 998 | ||
| 882 | spin_lock_irqsave(&mpic_lock, flags); | 999 | spin_lock_irqsave(&mpic_lock, flags); |
| 883 | if (is_ipi) | 1000 | if (is_ipi) |
| 884 | reg = mpic_ipi_read(irq - mpic->ipi_offset); | 1001 | reg = mpic_ipi_read(src = MPIC_VEC_IPI_0); |
| 885 | else | 1002 | else |
| 886 | reg = mpic_irq_read(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI); | 1003 | reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI); |
| 887 | spin_unlock_irqrestore(&mpic_lock, flags); | 1004 | spin_unlock_irqrestore(&mpic_lock, flags); |
| 888 | return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT; | 1005 | return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT; |
| 889 | } | 1006 | } |
| @@ -978,37 +1095,20 @@ void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask) | |||
| 978 | mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0])); | 1095 | mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0])); |
| 979 | } | 1096 | } |
| 980 | 1097 | ||
| 981 | int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs) | 1098 | unsigned int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs) |
| 982 | { | 1099 | { |
| 983 | u32 irq; | 1100 | u32 src; |
| 984 | 1101 | ||
| 985 | irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK; | 1102 | src = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK; |
| 986 | #ifdef DEBUG_LOW | 1103 | #ifdef DEBUG_LOW |
| 987 | DBG("%s: get_one_irq(): %d\n", mpic->name, irq); | 1104 | DBG("%s: get_one_irq(): %d\n", mpic->name, src); |
| 988 | #endif | 1105 | #endif |
| 989 | if (mpic->cascade && irq == mpic->cascade_vec) { | 1106 | if (unlikely(src == MPIC_VEC_SPURRIOUS)) |
| 990 | #ifdef DEBUG_LOW | 1107 | return NO_IRQ; |
| 991 | DBG("%s: cascading ...\n", mpic->name); | 1108 | return irq_linear_revmap(mpic->irqhost, src); |
| 992 | #endif | ||
| 993 | irq = mpic->cascade(regs, mpic->cascade_data); | ||
| 994 | mpic_eoi(mpic); | ||
| 995 | return irq; | ||
| 996 | } | ||
| 997 | if (unlikely(irq == MPIC_VEC_SPURRIOUS)) | ||
| 998 | return -1; | ||
| 999 | if (irq < MPIC_VEC_IPI_0) { | ||
| 1000 | #ifdef DEBUG_IRQ | ||
| 1001 | DBG("%s: irq %d\n", mpic->name, irq + mpic->irq_offset); | ||
| 1002 | #endif | ||
| 1003 | return irq + mpic->irq_offset; | ||
| 1004 | } | ||
| 1005 | #ifdef DEBUG_IPI | ||
| 1006 | DBG("%s: ipi %d !\n", mpic->name, irq - MPIC_VEC_IPI_0); | ||
| 1007 | #endif | ||
| 1008 | return irq - MPIC_VEC_IPI_0 + mpic->ipi_offset; | ||
| 1009 | } | 1109 | } |
| 1010 | 1110 | ||
| 1011 | int mpic_get_irq(struct pt_regs *regs) | 1111 | unsigned int mpic_get_irq(struct pt_regs *regs) |
| 1012 | { | 1112 | { |
| 1013 | struct mpic *mpic = mpic_primary; | 1113 | struct mpic *mpic = mpic_primary; |
| 1014 | 1114 | ||
| @@ -1022,25 +1122,27 @@ int mpic_get_irq(struct pt_regs *regs) | |||
| 1022 | void mpic_request_ipis(void) | 1122 | void mpic_request_ipis(void) |
| 1023 | { | 1123 | { |
| 1024 | struct mpic *mpic = mpic_primary; | 1124 | struct mpic *mpic = mpic_primary; |
| 1025 | 1125 | int i; | |
| 1126 | static char *ipi_names[] = { | ||
| 1127 | "IPI0 (call function)", | ||
| 1128 | "IPI1 (reschedule)", | ||
| 1129 | "IPI2 (unused)", | ||
| 1130 | "IPI3 (debugger break)", | ||
| 1131 | }; | ||
| 1026 | BUG_ON(mpic == NULL); | 1132 | BUG_ON(mpic == NULL); |
| 1027 | |||
| 1028 | printk("requesting IPIs ... \n"); | ||
| 1029 | 1133 | ||
| 1030 | /* | 1134 | printk(KERN_INFO "mpic: requesting IPIs ... \n"); |
| 1031 | * IPIs are marked IRQF_DISABLED as they must run with irqs | 1135 | |
| 1032 | * disabled | 1136 | for (i = 0; i < 4; i++) { |
| 1033 | */ | 1137 | unsigned int vipi = irq_create_mapping(mpic->irqhost, |
| 1034 | request_irq(mpic->ipi_offset+0, mpic_ipi_action, IRQF_DISABLED, | 1138 | MPIC_VEC_IPI_0 + i, 0); |
| 1035 | "IPI0 (call function)", mpic); | 1139 | if (vipi == NO_IRQ) { |
| 1036 | request_irq(mpic->ipi_offset+1, mpic_ipi_action, IRQF_DISABLED, | 1140 | printk(KERN_ERR "Failed to map IPI %d\n", i); |
| 1037 | "IPI1 (reschedule)", mpic); | 1141 | break; |
| 1038 | request_irq(mpic->ipi_offset+2, mpic_ipi_action, IRQF_DISABLED, | 1142 | } |
| 1039 | "IPI2 (unused)", mpic); | 1143 | request_irq(vipi, mpic_ipi_action, IRQF_DISABLED, |
| 1040 | request_irq(mpic->ipi_offset+3, mpic_ipi_action, IRQF_DISABLED, | 1144 | ipi_names[i], mpic); |
| 1041 | "IPI3 (debugger break)", mpic); | 1145 | } |
| 1042 | |||
| 1043 | printk("IPIs requested... \n"); | ||
| 1044 | } | 1146 | } |
| 1045 | 1147 | ||
| 1046 | void smp_mpic_message_pass(int target, int msg) | 1148 | void smp_mpic_message_pass(int target, int msg) |
