Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 14186
b: refs/heads/master
c: 6004e1b
h: refs/heads/master
v: v3
  • Loading branch information
James Cleverdon authored and Linus Torvalds committed Nov 15, 2005
1 parent c31a721 commit 9d170e5
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 18 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: 89b831ef8bf5cfbb357dbc0a2e07700d7f20eec5
refs/heads/master: 6004e1b7effcbb385a6b7c790e4b8008682cf679
15 changes: 7 additions & 8 deletions trunk/arch/i386/kernel/acpi/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,24 +39,23 @@

#ifdef CONFIG_X86_64

static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
}
extern void __init clustered_apic_check(void);
static inline int ioapic_setup_disabled(void)
{
return 0;
}

extern int gsi_irq_sharing(int gsi);
#include <asm/proto.h>

static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { return 0; }


#else /* X86 */

#ifdef CONFIG_X86_LOCAL_APIC
#include <mach_apic.h>
#include <mach_mpparse.h>
#endif /* CONFIG_X86_LOCAL_APIC */

static inline int gsi_irq_sharing(int gsi) { return gsi; }

#endif /* X86 */

#define BAD_MADT_ENTRY(entry, end) ( \
Expand Down Expand Up @@ -459,7 +458,7 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
*irq = IO_APIC_VECTOR(gsi);
else
#endif
*irq = gsi;
*irq = gsi_irq_sharing(gsi);
return 0;
}

Expand Down
80 changes: 73 additions & 7 deletions trunk/arch/x86_64/kernel/io_apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ int nr_ioapic_registers[MAX_IO_APICS];
* Rough estimation of how many shared IRQs there are, can
* be changed anytime.
*/
#define MAX_PLUS_SHARED_IRQS NR_IRQS
#define MAX_PLUS_SHARED_IRQS NR_IRQ_VECTORS
#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)

/*
Expand Down Expand Up @@ -85,6 +85,7 @@ int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
int pin; \
struct irq_pin_list *entry = irq_2_pin + irq; \
\
BUG_ON(irq >= NR_IRQS); \
for (;;) { \
unsigned int reg; \
pin = entry->pin; \
Expand Down Expand Up @@ -127,6 +128,8 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
}
#endif

static u8 gsi_2_irq[NR_IRQ_VECTORS] = { [0 ... NR_IRQ_VECTORS-1] = 0xFF };

/*
* The common case is 1:1 IRQ<->pin mappings. Sometimes there are
* shared ISA-space IRQs, so we have to support them. We are super
Expand All @@ -137,14 +140,15 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin)
static int first_free_entry = NR_IRQS;
struct irq_pin_list *entry = irq_2_pin + irq;

BUG_ON(irq >= NR_IRQS);
while (entry->next)
entry = irq_2_pin + entry->next;

if (entry->pin != -1) {
entry->next = first_free_entry;
entry = irq_2_pin + entry->next;
if (++first_free_entry >= PIN_MAP_SIZE)
panic("io_apic.c: whoops");
panic("io_apic.c: ran out of irq_2_pin entries!");
}
entry->apic = apic;
entry->pin = pin;
Expand Down Expand Up @@ -420,6 +424,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
best_guess = irq;
}
}
BUG_ON(best_guess >= NR_IRQS);
return best_guess;
}

Expand Down Expand Up @@ -610,6 +615,64 @@ static inline int irq_trigger(int idx)
return MPBIOS_trigger(idx);
}

static int next_irq = 16;

/*
* gsi_irq_sharing -- Name overload! "irq" can be either a legacy IRQ
* in the range 0-15, a linux IRQ in the range 0-223, or a GSI number
* from ACPI, which can reach 800 in large boxen.
*
* Compact the sparse GSI space into a sequential IRQ series and reuse
* vectors if possible.
*/
int gsi_irq_sharing(int gsi)
{
int i, tries, vector;

BUG_ON(gsi >= NR_IRQ_VECTORS);

if (platform_legacy_irq(gsi))
return gsi;

if (gsi_2_irq[gsi] != 0xFF)
return (int)gsi_2_irq[gsi];

tries = NR_IRQS;
try_again:
vector = assign_irq_vector(gsi);

/*
* Sharing vectors means sharing IRQs, so scan irq_vectors for previous
* use of vector and if found, return that IRQ. However, we never want
* to share legacy IRQs, which usually have a different trigger mode
* than PCI.
*/
for (i = 0; i < NR_IRQS; i++)
if (IO_APIC_VECTOR(i) == vector)
break;
if (platform_legacy_irq(i)) {
if (--tries >= 0) {
IO_APIC_VECTOR(i) = 0;
goto try_again;
}
panic("gsi_irq_sharing: didn't find an IRQ using vector 0x%02X for GSI %d", vector, gsi);
}
if (i < NR_IRQS) {
gsi_2_irq[gsi] = i;
printk(KERN_INFO "GSI %d sharing vector 0x%02X and IRQ %d\n",
gsi, vector, i);
return i;
}

i = next_irq++;
BUG_ON(i >= NR_IRQS);
gsi_2_irq[gsi] = i;
IO_APIC_VECTOR(i) = vector;
printk(KERN_INFO "GSI %d assigned vector 0x%02X and IRQ %d\n",
gsi, vector, i);
return i;
}

static int pin_2_irq(int idx, int apic, int pin)
{
int irq, i;
Expand Down Expand Up @@ -639,6 +702,7 @@ static int pin_2_irq(int idx, int apic, int pin)
while (i < apic)
irq += nr_ioapic_registers[i++];
irq += pin;
irq = gsi_irq_sharing(irq);
break;
}
default:
Expand All @@ -648,6 +712,7 @@ static int pin_2_irq(int idx, int apic, int pin)
break;
}
}
BUG_ON(irq >= NR_IRQS);

/*
* PCI IRQ command line redirection. Yes, limits are hardcoded.
Expand All @@ -663,6 +728,7 @@ static int pin_2_irq(int idx, int apic, int pin)
}
}
}
BUG_ON(irq >= NR_IRQS);
return irq;
}

Expand Down Expand Up @@ -690,18 +756,17 @@ int assign_irq_vector(int irq)
{
static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;

BUG_ON(irq >= NR_IRQ_VECTORS);
if (IO_APIC_VECTOR(irq) > 0)
BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
return IO_APIC_VECTOR(irq);
next:
current_vector += 8;
if (current_vector == IA32_SYSCALL_VECTOR)
goto next;

if (current_vector >= FIRST_SYSTEM_VECTOR) {
offset++;
if (!(offset%8))
return -ENOSPC;
/* If we run out of vectors on large boxen, must share them. */
offset = (offset + 1) % 8;
current_vector = FIRST_DEVICE_VECTOR + offset;
}

Expand Down Expand Up @@ -1917,6 +1982,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
entry.polarity = active_high_low;
entry.mask = 1; /* Disabled (masked) */

irq = gsi_irq_sharing(irq);
/*
* IRQs < 16 are already in the irq_2_pin[] map
*/
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/x86_64/kernel/mpparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ static void __init MP_intsrc_info (struct mpc_config_intsrc *m)
m->mpc_irqtype, m->mpc_irqflag & 3,
(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
if (++mp_irq_entries == MAX_IRQ_SOURCES)
if (++mp_irq_entries >= MAX_IRQ_SOURCES)
panic("Max # of irq sources exceeded!!\n");
}

Expand Down
3 changes: 3 additions & 0 deletions trunk/include/asm-x86_64/desc.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,16 +98,19 @@ static inline void _set_gate(void *adr, unsigned type, unsigned long func, unsig

static inline void set_intr_gate(int nr, void *func)
{
BUG_ON((unsigned)nr > 0xFF);
_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, 0);
}

static inline void set_intr_gate_ist(int nr, void *func, unsigned ist)
{
BUG_ON((unsigned)nr > 0xFF);
_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, ist);
}

static inline void set_system_gate(int nr, void *func)
{
BUG_ON((unsigned)nr > 0xFF);
_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, 0);
}

Expand Down
3 changes: 2 additions & 1 deletion trunk/include/asm-x86_64/mpspec.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ struct mpc_config_lintsrc
*/

#define MAX_MP_BUSSES 256
#define MAX_IRQ_SOURCES 256
/* Each PCI slot may be a combo card with its own bus. 4 IRQ pins per slot. */
#define MAX_IRQ_SOURCES (MAX_MP_BUSSES * 4)
enum mp_bustype {
MP_BUS_ISA = 1,
MP_BUS_EISA,
Expand Down

0 comments on commit 9d170e5

Please sign in to comment.