diff options
| -rw-r--r-- | arch/x86/kernel/visws_quirks.c | 140 |
1 files changed, 44 insertions, 96 deletions
diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c index e680ea52db9b..3371bd053b89 100644 --- a/arch/x86/kernel/visws_quirks.c +++ b/arch/x86/kernel/visws_quirks.c | |||
| @@ -66,10 +66,7 @@ static void __init visws_time_init(void) | |||
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | /* Replaces the default init_ISA_irqs in the generic setup */ | 68 | /* Replaces the default init_ISA_irqs in the generic setup */ |
| 69 | static void __init visws_pre_intr_init(void) | 69 | static void __init visws_pre_intr_init(void); |
| 70 | { | ||
| 71 | init_VISWS_APIC_irqs(); | ||
| 72 | } | ||
| 73 | 70 | ||
| 74 | /* Quirk for machine specific memory setup. */ | 71 | /* Quirk for machine specific memory setup. */ |
| 75 | 72 | ||
| @@ -429,67 +426,34 @@ static int is_co_apic(unsigned int irq) | |||
| 429 | /* | 426 | /* |
| 430 | * This is the SGI Cobalt (IO-)APIC: | 427 | * This is the SGI Cobalt (IO-)APIC: |
| 431 | */ | 428 | */ |
| 432 | 429 | static void enable_cobalt_irq(struct irq_data *data) | |
| 433 | static void enable_cobalt_irq(unsigned int irq) | ||
| 434 | { | 430 | { |
| 435 | co_apic_set(is_co_apic(irq), irq); | 431 | co_apic_set(is_co_apic(data->irq), data->irq); |
| 436 | } | 432 | } |
| 437 | 433 | ||
| 438 | static void disable_cobalt_irq(unsigned int irq) | 434 | static void disable_cobalt_irq(struct irq_data *data) |
| 439 | { | 435 | { |
| 440 | int entry = is_co_apic(irq); | 436 | int entry = is_co_apic(data->irq); |
| 441 | 437 | ||
| 442 | co_apic_write(CO_APIC_LO(entry), CO_APIC_MASK); | 438 | co_apic_write(CO_APIC_LO(entry), CO_APIC_MASK); |
| 443 | co_apic_read(CO_APIC_LO(entry)); | 439 | co_apic_read(CO_APIC_LO(entry)); |
| 444 | } | 440 | } |
| 445 | 441 | ||
| 446 | /* | 442 | static void ack_cobalt_irq(struct irq_data *data) |
| 447 | * "irq" really just serves to identify the device. Here is where we | ||
| 448 | * map this to the Cobalt APIC entry where it's physically wired. | ||
| 449 | * This is called via request_irq -> setup_irq -> irq_desc->startup() | ||
| 450 | */ | ||
| 451 | static unsigned int startup_cobalt_irq(unsigned int irq) | ||
| 452 | { | 443 | { |
| 453 | unsigned long flags; | 444 | unsigned long flags; |
| 454 | struct irq_desc *desc = irq_to_desc(irq); | ||
| 455 | 445 | ||
| 456 | spin_lock_irqsave(&cobalt_lock, flags); | 446 | spin_lock_irqsave(&cobalt_lock, flags); |
| 457 | if ((desc->status & (IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING))) | 447 | disable_cobalt_irq(data); |
| 458 | desc->status &= ~(IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING); | ||
| 459 | enable_cobalt_irq(irq); | ||
| 460 | spin_unlock_irqrestore(&cobalt_lock, flags); | ||
| 461 | return 0; | ||
| 462 | } | ||
| 463 | |||
| 464 | static void ack_cobalt_irq(unsigned int irq) | ||
| 465 | { | ||
| 466 | unsigned long flags; | ||
| 467 | |||
| 468 | spin_lock_irqsave(&cobalt_lock, flags); | ||
| 469 | disable_cobalt_irq(irq); | ||
| 470 | apic_write(APIC_EOI, APIC_EIO_ACK); | 448 | apic_write(APIC_EOI, APIC_EIO_ACK); |
| 471 | spin_unlock_irqrestore(&cobalt_lock, flags); | 449 | spin_unlock_irqrestore(&cobalt_lock, flags); |
| 472 | } | 450 | } |
| 473 | 451 | ||
| 474 | static void end_cobalt_irq(unsigned int irq) | ||
| 475 | { | ||
| 476 | unsigned long flags; | ||
| 477 | struct irq_desc *desc = irq_to_desc(irq); | ||
| 478 | |||
| 479 | spin_lock_irqsave(&cobalt_lock, flags); | ||
| 480 | if (!(desc->status & (IRQ_DISABLED | IRQ_INPROGRESS))) | ||
| 481 | enable_cobalt_irq(irq); | ||
| 482 | spin_unlock_irqrestore(&cobalt_lock, flags); | ||
| 483 | } | ||
| 484 | |||
| 485 | static struct irq_chip cobalt_irq_type = { | 452 | static struct irq_chip cobalt_irq_type = { |
| 486 | .name = "Cobalt-APIC", | 453 | .name = "Cobalt-APIC", |
| 487 | .startup = startup_cobalt_irq, | 454 | .irq_enable = enable_cobalt_irq, |
| 488 | .shutdown = disable_cobalt_irq, | 455 | .irq_disable = disable_cobalt_irq, |
| 489 | .enable = enable_cobalt_irq, | 456 | .irq_ack = ack_cobalt_irq, |
| 490 | .disable = disable_cobalt_irq, | ||
| 491 | .ack = ack_cobalt_irq, | ||
| 492 | .end = end_cobalt_irq, | ||
| 493 | }; | 457 | }; |
| 494 | 458 | ||
| 495 | 459 | ||
| @@ -503,35 +467,34 @@ static struct irq_chip cobalt_irq_type = { | |||
| 503 | * interrupt controller type, and through a special virtual interrupt- | 467 | * interrupt controller type, and through a special virtual interrupt- |
| 504 | * controller. Device drivers only see the virtual interrupt sources. | 468 | * controller. Device drivers only see the virtual interrupt sources. |
| 505 | */ | 469 | */ |
| 506 | static unsigned int startup_piix4_master_irq(unsigned int irq) | 470 | static unsigned int startup_piix4_master_irq(struct irq_data *data) |
| 507 | { | 471 | { |
| 508 | legacy_pic->init(0); | 472 | legacy_pic->init(0); |
| 509 | 473 | enable_cobalt_irq(data); | |
| 510 | return startup_cobalt_irq(irq); | ||
| 511 | } | 474 | } |
| 512 | 475 | ||
| 513 | static void end_piix4_master_irq(unsigned int irq) | 476 | static void end_piix4_master_irq(struct irq_data *data) |
| 514 | { | 477 | { |
| 515 | unsigned long flags; | 478 | unsigned long flags; |
| 516 | 479 | ||
| 517 | spin_lock_irqsave(&cobalt_lock, flags); | 480 | spin_lock_irqsave(&cobalt_lock, flags); |
| 518 | enable_cobalt_irq(irq); | 481 | enable_cobalt_irq(data); |
| 519 | spin_unlock_irqrestore(&cobalt_lock, flags); | 482 | spin_unlock_irqrestore(&cobalt_lock, flags); |
| 520 | } | 483 | } |
| 521 | 484 | ||
| 522 | static struct irq_chip piix4_master_irq_type = { | 485 | static struct irq_chip piix4_master_irq_type = { |
| 523 | .name = "PIIX4-master", | 486 | .name = "PIIX4-master", |
| 524 | .startup = startup_piix4_master_irq, | 487 | .irq_startup = startup_piix4_master_irq, |
| 525 | .ack = ack_cobalt_irq, | 488 | .irq_ack = ack_cobalt_irq, |
| 526 | .end = end_piix4_master_irq, | ||
| 527 | }; | 489 | }; |
| 528 | 490 | ||
| 491 | static void pii4_mask(struct irq_data *data) { } | ||
| 529 | 492 | ||
| 530 | static struct irq_chip piix4_virtual_irq_type = { | 493 | static struct irq_chip piix4_virtual_irq_type = { |
| 531 | .name = "PIIX4-virtual", | 494 | .name = "PIIX4-virtual", |
| 495 | .mask = pii4_mask, | ||
| 532 | }; | 496 | }; |
| 533 | 497 | ||
| 534 | |||
| 535 | /* | 498 | /* |
| 536 | * PIIX4-8259 master/virtual functions to handle interrupt requests | 499 | * PIIX4-8259 master/virtual functions to handle interrupt requests |
| 537 | * from legacy devices: floppy, parallel, serial, rtc. | 500 | * from legacy devices: floppy, parallel, serial, rtc. |
| @@ -549,9 +512,8 @@ static struct irq_chip piix4_virtual_irq_type = { | |||
| 549 | */ | 512 | */ |
| 550 | static irqreturn_t piix4_master_intr(int irq, void *dev_id) | 513 | static irqreturn_t piix4_master_intr(int irq, void *dev_id) |
| 551 | { | 514 | { |
| 552 | int realirq; | ||
| 553 | struct irq_desc *desc; | ||
| 554 | unsigned long flags; | 515 | unsigned long flags; |
| 516 | int realirq; | ||
| 555 | 517 | ||
| 556 | raw_spin_lock_irqsave(&i8259A_lock, flags); | 518 | raw_spin_lock_irqsave(&i8259A_lock, flags); |
| 557 | 519 | ||
| @@ -592,18 +554,10 @@ static irqreturn_t piix4_master_intr(int irq, void *dev_id) | |||
| 592 | 554 | ||
| 593 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); | 555 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
| 594 | 556 | ||
| 595 | desc = irq_to_desc(realirq); | ||
| 596 | |||
| 597 | /* | 557 | /* |
| 598 | * handle this 'virtual interrupt' as a Cobalt one now. | 558 | * handle this 'virtual interrupt' as a Cobalt one now. |
| 599 | */ | 559 | */ |
| 600 | kstat_incr_irqs_this_cpu(realirq, desc); | 560 | generic_handle_irq(realirq); |
| 601 | |||
| 602 | if (likely(desc->action != NULL)) | ||
| 603 | handle_IRQ_event(realirq, desc->action); | ||
| 604 | |||
| 605 | if (!(desc->status & IRQ_DISABLED)) | ||
| 606 | legacy_pic->chip->unmask(realirq); | ||
| 607 | 561 | ||
| 608 | return IRQ_HANDLED; | 562 | return IRQ_HANDLED; |
| 609 | 563 | ||
| @@ -624,41 +578,35 @@ static struct irqaction cascade_action = { | |||
| 624 | 578 | ||
| 625 | static inline void set_piix4_virtual_irq_type(void) | 579 | static inline void set_piix4_virtual_irq_type(void) |
| 626 | { | 580 | { |
| 627 | piix4_virtual_irq_type.shutdown = i8259A_chip.mask; | ||
| 628 | piix4_virtual_irq_type.enable = i8259A_chip.unmask; | 581 | piix4_virtual_irq_type.enable = i8259A_chip.unmask; |
| 629 | piix4_virtual_irq_type.disable = i8259A_chip.mask; | 582 | piix4_virtual_irq_type.disable = i8259A_chip.mask; |
| 583 | piix4_virtual_irq_type.unmask = i8259A_chip.unmask; | ||
| 630 | } | 584 | } |
| 631 | 585 | ||
| 632 | void init_VISWS_APIC_irqs(void) | 586 | static void __init visws_pre_intr_init(void) |
| 633 | { | 587 | { |
| 634 | int i; | 588 | int i; |
| 635 | 589 | ||
| 636 | for (i = 0; i < CO_IRQ_APIC0 + CO_APIC_LAST + 1; i++) { | 590 | set_piix4_virtual_irq_type(); |
| 637 | struct irq_desc *desc = irq_to_desc(i); | ||
| 638 | |||
| 639 | desc->status = IRQ_DISABLED; | ||
| 640 | desc->action = 0; | ||
| 641 | desc->depth = 1; | ||
| 642 | 591 | ||
| 643 | if (i == 0) { | 592 | for (i = 0; i < CO_IRQ_APIC0 + CO_APIC_LAST + 1; i++) { |
| 644 | desc->chip = &cobalt_irq_type; | 593 | struct irq_chip *chip = NULL; |
| 645 | } | 594 | |
| 646 | else if (i == CO_IRQ_IDE0) { | 595 | if (i == 0) |
| 647 | desc->chip = &cobalt_irq_type; | 596 | chip = &cobalt_irq_type; |
| 648 | } | 597 | else if (i == CO_IRQ_IDE0) |
| 649 | else if (i == CO_IRQ_IDE1) { | 598 | chip = &cobalt_irq_type; |
| 650 | desc->chip = &cobalt_irq_type; | 599 | else if (i == CO_IRQ_IDE1) |
| 651 | } | 600 | >chip = &cobalt_irq_type; |
| 652 | else if (i == CO_IRQ_8259) { | 601 | else if (i == CO_IRQ_8259) |
| 653 | desc->chip = &piix4_master_irq_type; | 602 | chip = &piix4_master_irq_type; |
| 654 | } | 603 | else if (i < CO_IRQ_APIC0) |
| 655 | else if (i < CO_IRQ_APIC0) { | 604 | chip = &piix4_virtual_irq_type; |
| 656 | set_piix4_virtual_irq_type(); | 605 | else if (IS_CO_APIC(i)) |
| 657 | desc->chip = &piix4_virtual_irq_type; | 606 | chip = &cobalt_irq_type; |
| 658 | } | 607 | |
| 659 | else if (IS_CO_APIC(i)) { | 608 | if (chip) |
| 660 | desc->chip = &cobalt_irq_type; | 609 | set_irq_chip(i, chip); |
| 661 | } | ||
| 662 | } | 610 | } |
| 663 | 611 | ||
| 664 | setup_irq(CO_IRQ_8259, &master_action); | 612 | setup_irq(CO_IRQ_8259, &master_action); |
