Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 18000
b: refs/heads/master
c: 1008fdd
h: refs/heads/master
v: v3
  • Loading branch information
Eric W. Biederman authored and Linus Torvalds committed Jan 12, 2006
1 parent fcdbada commit 7f1628c
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 38 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 60923df35edab273d0bd8e829cdfdc5cfbb4fd2c
refs/heads/master: 1008fddcaed7ad3e69f72939c87b24d0d3387ca2
2 changes: 1 addition & 1 deletion trunk/arch/i386/kernel/io_apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1649,7 +1649,7 @@ static void __init enable_IO_APIC(void)
for(apic = 0; apic < nr_ioapics; apic++) {
int pin;
/* See if any of the pins is in ExtINT mode */
for(pin = 0; pin < nr_ioapic_registers[i]; pin++) {
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
struct IO_APIC_route_entry entry;
spin_lock_irqsave(&ioapic_lock, flags);
*(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
Expand Down
144 changes: 108 additions & 36 deletions trunk/arch/x86_64/kernel/io_apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ static int no_timer_check;

int disable_timer_pin_1 __initdata;

/* Where if anywhere is the i8259 connect in external int mode */
static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };

static DEFINE_SPINLOCK(ioapic_lock);

/*
Expand Down Expand Up @@ -361,7 +364,7 @@ static int find_irq_entry(int apic, int pin, int type)
/*
* Find the pin to which IRQ[irq] (ISA) is connected
*/
static int find_isa_irq_pin(int irq, int type)
static int __init find_isa_irq_pin(int irq, int type)
{
int i;

Expand All @@ -379,6 +382,31 @@ static int find_isa_irq_pin(int irq, int type)
return -1;
}

static int __init find_isa_irq_apic(int irq, int type)
{
int i;

for (i = 0; i < mp_irq_entries; i++) {
int lbus = mp_irqs[i].mpc_srcbus;

if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
mp_bus_id_to_type[lbus] == MP_BUS_MCA) &&
(mp_irqs[i].mpc_irqtype == type) &&
(mp_irqs[i].mpc_srcbusirq == irq))
break;
}
if (i < mp_irq_entries) {
int apic;
for(apic = 0; apic < nr_ioapics; apic++) {
if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic)
return apic;
}
}

return -1;
}

/*
* Find a specific PCI IRQ entry.
* Not an __init, possibly needed by modules
Expand Down Expand Up @@ -872,7 +900,7 @@ static void __init setup_IO_APIC_irqs(void)
* Set up the 8259A-master output pin as broadcast to all
* CPUs.
*/
static void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector)
{
struct IO_APIC_route_entry entry;
unsigned long flags;
Expand Down Expand Up @@ -906,8 +934,8 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
* Add it to the IO-APIC irq-routing table:
*/
spin_lock_irqsave(&ioapic_lock, flags);
io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));
io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
spin_unlock_irqrestore(&ioapic_lock, flags);

enable_8259A_irq(0);
Expand Down Expand Up @@ -1186,7 +1214,8 @@ void __apicdebuginit print_PIC(void)
static void __init enable_IO_APIC(void)
{
union IO_APIC_reg_01 reg_01;
int i;
int i8259_apic, i8259_pin;
int i, apic;
unsigned long flags;

for (i = 0; i < PIN_MAP_SIZE; i++) {
Expand All @@ -1200,11 +1229,48 @@ static void __init enable_IO_APIC(void)
/*
* The number of IO-APIC IRQ registers (== #pins):
*/
for (i = 0; i < nr_ioapics; i++) {
for (apic = 0; apic < nr_ioapics; apic++) {
spin_lock_irqsave(&ioapic_lock, flags);
reg_01.raw = io_apic_read(i, 1);
reg_01.raw = io_apic_read(apic, 1);
spin_unlock_irqrestore(&ioapic_lock, flags);
nr_ioapic_registers[i] = reg_01.bits.entries+1;
nr_ioapic_registers[apic] = reg_01.bits.entries+1;
}
for(apic = 0; apic < nr_ioapics; apic++) {
int pin;
/* See if any of the pins is in ExtINT mode */
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
struct IO_APIC_route_entry entry;
spin_lock_irqsave(&ioapic_lock, flags);
*(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
*(((int *)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
spin_unlock_irqrestore(&ioapic_lock, flags);


/* If the interrupt line is enabled and in ExtInt mode
* I have found the pin where the i8259 is connected.
*/
if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
ioapic_i8259.apic = apic;
ioapic_i8259.pin = pin;
goto found_i8259;
}
}
}
found_i8259:
/* Look to see what if the MP table has reported the ExtINT */
i8259_pin = find_isa_irq_pin(0, mp_ExtINT);
i8259_apic = find_isa_irq_apic(0, mp_ExtINT);
/* Trust the MP table if nothing is setup in the hardware */
if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) {
printk(KERN_WARNING "ExtINT not setup in hardware but reported by MP table\n");
ioapic_i8259.pin = i8259_pin;
ioapic_i8259.apic = i8259_apic;
}
/* Complain if the MP table and the hardware disagree */
if (((ioapic_i8259.apic != i8259_apic) || (ioapic_i8259.pin != i8259_pin)) &&
(i8259_pin >= 0) && (ioapic_i8259.pin >= 0))
{
printk(KERN_WARNING "ExtINT in hardware and MP table differ\n");
}

/*
Expand All @@ -1218,7 +1284,6 @@ static void __init enable_IO_APIC(void)
*/
void disable_IO_APIC(void)
{
int pin;
/*
* Clear the IO-APIC before rebooting:
*/
Expand All @@ -1229,8 +1294,7 @@ void disable_IO_APIC(void)
* Put that IOAPIC in virtual wire mode
* so legacy interrupts can be delivered.
*/
pin = find_isa_irq_pin(0, mp_ExtINT);
if (pin != -1) {
if (ioapic_i8259.pin != -1) {
struct IO_APIC_route_entry entry;
unsigned long flags;

Expand All @@ -1241,21 +1305,22 @@ void disable_IO_APIC(void)
entry.polarity = 0; /* High */
entry.delivery_status = 0;
entry.dest_mode = 0; /* Physical */
entry.delivery_mode = 7; /* ExtInt */
entry.delivery_mode = dest_ExtINT; /* ExtInt */
entry.vector = 0;
entry.dest.physical.physical_dest = 0;


/*
* Add it to the IO-APIC irq-routing table:
*/
spin_lock_irqsave(&ioapic_lock, flags);
io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));
io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
io_apic_write(ioapic_i8259.apic, 0x11+2*ioapic_i8259.pin,
*(((int *)&entry)+1));
io_apic_write(ioapic_i8259.apic, 0x10+2*ioapic_i8259.pin,
*(((int *)&entry)+0));
spin_unlock_irqrestore(&ioapic_lock, flags);
}

disconnect_bsp_APIC(pin != -1);
disconnect_bsp_APIC(ioapic_i8259.pin != -1);
}

/*
Expand Down Expand Up @@ -1624,20 +1689,21 @@ static void setup_nmi (void)
*/
static inline void unlock_ExtINT_logic(void)
{
int pin, i;
int apic, pin, i;
struct IO_APIC_route_entry entry0, entry1;
unsigned char save_control, save_freq_select;
unsigned long flags;

pin = find_isa_irq_pin(8, mp_INT);
pin = find_isa_irq_pin(8, mp_INT);
apic = find_isa_irq_apic(8, mp_INT);
if (pin == -1)
return;

spin_lock_irqsave(&ioapic_lock, flags);
*(((int *)&entry0) + 1) = io_apic_read(0, 0x11 + 2 * pin);
*(((int *)&entry0) + 0) = io_apic_read(0, 0x10 + 2 * pin);
*(((int *)&entry0) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
*(((int *)&entry0) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
spin_unlock_irqrestore(&ioapic_lock, flags);
clear_IO_APIC_pin(0, pin);
clear_IO_APIC_pin(apic, pin);

memset(&entry1, 0, sizeof(entry1));

Expand All @@ -1650,8 +1716,8 @@ static inline void unlock_ExtINT_logic(void)
entry1.vector = 0;

spin_lock_irqsave(&ioapic_lock, flags);
io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
spin_unlock_irqrestore(&ioapic_lock, flags);

save_control = CMOS_READ(RTC_CONTROL);
Expand All @@ -1669,11 +1735,11 @@ static inline void unlock_ExtINT_logic(void)

CMOS_WRITE(save_control, RTC_CONTROL);
CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
clear_IO_APIC_pin(0, pin);
clear_IO_APIC_pin(apic, pin);

spin_lock_irqsave(&ioapic_lock, flags);
io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
spin_unlock_irqrestore(&ioapic_lock, flags);
}

Expand All @@ -1685,7 +1751,7 @@ static inline void unlock_ExtINT_logic(void)
*/
static inline void check_timer(void)
{
int pin1, pin2;
int apic1, pin1, apic2, pin2;
int vector;

/*
Expand All @@ -1706,10 +1772,13 @@ static inline void check_timer(void)
init_8259A(1);
enable_8259A_irq(0);

pin1 = find_isa_irq_pin(0, mp_INT);
pin2 = find_isa_irq_pin(0, mp_ExtINT);
pin1 = find_isa_irq_pin(0, mp_INT);
apic1 = find_isa_irq_apic(0, mp_INT);
pin2 = ioapic_i8259.pin;
apic2 = ioapic_i8259.apic;

apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2);
apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
vector, apic1, pin1, apic2, pin2);

if (pin1 != -1) {
/*
Expand All @@ -1727,17 +1796,20 @@ static inline void check_timer(void)
clear_IO_APIC_pin(0, pin1);
return;
}
clear_IO_APIC_pin(0, pin1);
apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n");
clear_IO_APIC_pin(apic1, pin1);
apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not "
"connected to IO-APIC\n");
}

apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... ");
apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) "
"through the 8259A ... ");
if (pin2 != -1) {
apic_printk(APIC_VERBOSE,"\n..... (found pin %d) ...", pin2);
apic_printk(APIC_VERBOSE,"\n..... (found apic %d pin %d) ...",
apic2, pin2);
/*
* legacy devices should be connected to IO APIC #0
*/
setup_ExtINT_IRQ0_pin(pin2, vector);
setup_ExtINT_IRQ0_pin(apic2, pin2, vector);
if (timer_irq_works()) {
printk("works.\n");
nmi_watchdog_default();
Expand All @@ -1749,7 +1821,7 @@ static inline void check_timer(void)
/*
* Cleanup, just in case ...
*/
clear_IO_APIC_pin(0, pin2);
clear_IO_APIC_pin(apic2, pin2);
}
printk(" failed.\n");

Expand Down

0 comments on commit 7f1628c

Please sign in to comment.