Skip to content

Commit

Permalink
Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/tip/linux-2.6-tip

* 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  x86, apic: Include module.h header in apic_flat_64.c
  x86, apic: Make apic drivers static
  x86, apic: Clean up bigsmp apic selection code
  x86, apic: Use .apicdrivers section for the apic drivers list
  x86, apic: Introduce .apicdrivers section to find the list of apic drivers
  x86, x2apic: Move the common bits to x2apic.h
  x86, x2apic: Minimize IPI register writes using cluster groups
  x86, x2apic: Track the x2apic cluster sibling map
  x86, x2apic: Remove duplicate code for IPI mask routines
  x86, apic: Use probe routines to simplify apic selection
  x86, ioapic: Consolidate mp_ioapic_routing[] into 'struct ioapic'
  x86, ioapic: Consolidate gsi routing info into 'struct ioapic'
  x86, ioapic: Consolidate mp_ioapics[] into 'struct ioapic'
  x86, ioapic: Consolidate ioapic_saved_data[] into 'struct ioapic'
  x86, ioapic: Add struct ioapic
  x86, ioapic: Remove duplicate code for saving/restoring RTEs
  x86, ioapic: Use ioapic_saved_data while enabling intr-remapping
  x86, ioapic: Allocate ioapic_saved_data early
  x86, ioapic: Fix potential resume deadlock
  • Loading branch information
torvalds committed May 23, 2011
2 parents 15a3d11 + b18bf09 commit ea2b50e
Show file tree
Hide file tree
Showing 20 changed files with 539 additions and 563 deletions.
29 changes: 21 additions & 8 deletions arch/x86/include/asm/apic.h
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,26 @@ struct apic {
*/
extern struct apic *apic;

/*
* APIC drivers are probed based on how they are listed in the .apicdrivers
* section. So the order is important and enforced by the ordering
* of different apic driver files in the Makefile.
*
* For the files having two apic drivers, we use apic_drivers()
* to enforce the order with in them.
*/
#define apic_driver(sym) \
static struct apic *__apicdrivers_##sym __used \
__aligned(sizeof(struct apic *)) \
__section(.apicdrivers) = { &sym }

#define apic_drivers(sym1, sym2) \
static struct apic *__apicdrivers_##sym1##sym2[2] __used \
__aligned(sizeof(struct apic *)) \
__section(.apicdrivers) = { &sym1, &sym2 }

extern struct apic *__apicdrivers[], *__apicdrivers_end[];

/*
* APIC functionality to boot other CPUs - only used on SMP:
*/
Expand Down Expand Up @@ -458,15 +478,10 @@ static inline unsigned default_get_apic_id(unsigned long x)
#define DEFAULT_TRAMPOLINE_PHYS_HIGH 0x469

#ifdef CONFIG_X86_64
extern struct apic apic_flat;
extern struct apic apic_physflat;
extern struct apic apic_x2apic_cluster;
extern struct apic apic_x2apic_phys;
extern int default_acpi_madt_oem_check(char *, char *);

extern void apic_send_IPI_self(int vector);

extern struct apic apic_x2apic_uv_x;
DECLARE_PER_CPU(int, x2apic_extra_bits);

extern int default_cpu_present_to_apicid(int mps_cpu);
Expand All @@ -480,7 +495,7 @@ static inline void default_wait_for_init_deassert(atomic_t *deassert)
return;
}

extern void generic_bigsmp_probe(void);
extern struct apic *generic_bigsmp_probe(void);


#ifdef CONFIG_X86_LOCAL_APIC
Expand Down Expand Up @@ -516,8 +531,6 @@ extern struct apic apic_noop;

#ifdef CONFIG_X86_32

extern struct apic apic_default;

static inline int noop_x86_32_early_logical_apicid(int cpu)
{
return BAD_APICID;
Expand Down
28 changes: 10 additions & 18 deletions arch/x86/include/asm/io_apic.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,12 @@ struct IR_IO_APIC_route_entry {
* # of IO-APICs and # of IRQ routing registers
*/
extern int nr_ioapics;
extern int nr_ioapic_registers[MAX_IO_APICS];

#define MP_MAX_IOAPIC_PIN 127
extern int mpc_ioapic_id(int ioapic);
extern unsigned int mpc_ioapic_addr(int ioapic);
extern struct mp_ioapic_gsi *mp_ioapic_gsi_routing(int ioapic);

/* I/O APIC entries */
extern struct mpc_ioapic mp_ioapics[MAX_IO_APICS];
#define MP_MAX_IOAPIC_PIN 127

/* # of MP IRQ source entries */
extern int mp_irq_entries;
Expand Down Expand Up @@ -152,11 +152,9 @@ extern void ioapic_insert_resources(void);

int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr);

extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
extern int save_ioapic_entries(void);
extern void mask_ioapic_entries(void);
extern int restore_ioapic_entries(void);

extern int get_nr_irqs_gsi(void);

Expand Down Expand Up @@ -192,19 +190,13 @@ struct io_apic_irq_attr;
static inline int io_apic_set_pci_routing(struct device *dev, int irq,
struct io_apic_irq_attr *irq_attr) { return 0; }

static inline struct IO_APIC_route_entry **alloc_ioapic_entries(void)
{
return NULL;
}

static inline void free_ioapic_entries(struct IO_APIC_route_entry **ent) { }
static inline int save_IO_APIC_setup(struct IO_APIC_route_entry **ent)
static inline int save_ioapic_entries(void)
{
return -ENOMEM;
}

static inline void mask_IO_APIC_setup(struct IO_APIC_route_entry **ent) { }
static inline int restore_IO_APIC_setup(struct IO_APIC_route_entry **ent)
static inline void mask_ioapic_entries(void) { }
static inline int restore_ioapic_entries(void)
{
return -ENOMEM;
}
Expand Down
62 changes: 62 additions & 0 deletions arch/x86/include/asm/x2apic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Common bits for X2APIC cluster/physical modes.
*/

#ifndef _ASM_X86_X2APIC_H
#define _ASM_X86_X2APIC_H

#include <asm/apic.h>
#include <asm/ipi.h>
#include <linux/cpumask.h>

/*
* Need to use more than cpu 0, because we need more vectors
* when MSI-X are used.
*/
static const struct cpumask *x2apic_target_cpus(void)
{
return cpu_online_mask;
}

static int x2apic_apic_id_registered(void)
{
return 1;
}

/*
* For now each logical cpu is in its own vector allocation domain.
*/
static void x2apic_vector_allocation_domain(int cpu, struct cpumask *retmask)
{
cpumask_clear(retmask);
cpumask_set_cpu(cpu, retmask);
}

static void
__x2apic_send_IPI_dest(unsigned int apicid, int vector, unsigned int dest)
{
unsigned long cfg = __prepare_ICR(0, vector, dest);
native_x2apic_icr_write(cfg, apicid);
}

static unsigned int x2apic_get_apic_id(unsigned long id)
{
return id;
}

static unsigned long x2apic_set_apic_id(unsigned int id)
{
return id;
}

static int x2apic_phys_pkg_id(int initial_apicid, int index_msb)
{
return initial_apicid >> index_msb;
}

static void x2apic_send_IPI_self(int vector)
{
apic_write(APIC_SELF_IPI, vector);
}

#endif /* _ASM_X86_X2APIC_H */
8 changes: 4 additions & 4 deletions arch/x86/kernel/acpi/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
mp_irq.irqflag = (trigger << 2) | polarity;
mp_irq.srcbus = MP_ISA_BUS;
mp_irq.srcbusirq = bus_irq; /* IRQ */
mp_irq.dstapic = mp_ioapics[ioapic].apicid; /* APIC ID */
mp_irq.dstapic = mpc_ioapic_id(ioapic); /* APIC ID */
mp_irq.dstirq = pin; /* INTIN# */

mp_save_irq(&mp_irq);
Expand Down Expand Up @@ -1021,7 +1021,7 @@ void __init mp_config_acpi_legacy_irqs(void)
if (ioapic < 0)
continue;
pin = mp_find_ioapic_pin(ioapic, gsi);
dstapic = mp_ioapics[ioapic].apicid;
dstapic = mpc_ioapic_id(ioapic);

for (idx = 0; idx < mp_irq_entries; idx++) {
struct mpc_intsrc *irq = mp_irqs + idx;
Expand Down Expand Up @@ -1082,7 +1082,7 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
mp_irq.srcbus = number;
mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
ioapic = mp_find_ioapic(gsi);
mp_irq.dstapic = mp_ioapics[ioapic].apicid;
mp_irq.dstapic = mpc_ioapic_id(ioapic);
mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);

mp_save_irq(&mp_irq);
Expand Down Expand Up @@ -1113,7 +1113,7 @@ int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)

if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
printk(KERN_ERR "Invalid reference to IOAPIC pin "
"%d-%d\n", mp_ioapics[ioapic].apicid,
"%d-%d\n", mpc_ioapic_id(ioapic),
ioapic_pin);
return gsi;
}
Expand Down
17 changes: 11 additions & 6 deletions arch/x86/kernel/apic/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,25 @@
# Makefile for local APIC drivers and for the IO-APIC code
#

obj-$(CONFIG_X86_LOCAL_APIC) += apic.o apic_noop.o probe_$(BITS).o ipi.o
obj-$(CONFIG_X86_LOCAL_APIC) += apic.o apic_noop.o ipi.o
obj-y += hw_nmi.o

obj-$(CONFIG_X86_IO_APIC) += io_apic.o
obj-$(CONFIG_SMP) += ipi.o

ifeq ($(CONFIG_X86_64),y)
obj-y += apic_flat_64.o
obj-$(CONFIG_X86_X2APIC) += x2apic_cluster.o
obj-$(CONFIG_X86_X2APIC) += x2apic_phys.o
# APIC probe will depend on the listing order here
obj-$(CONFIG_X86_UV) += x2apic_uv_x.o
obj-$(CONFIG_X86_X2APIC) += x2apic_phys.o
obj-$(CONFIG_X86_X2APIC) += x2apic_cluster.o
obj-y += apic_flat_64.o
endif

obj-$(CONFIG_X86_BIGSMP) += bigsmp_32.o
# APIC probe will depend on the listing order here
obj-$(CONFIG_X86_NUMAQ) += numaq_32.o
obj-$(CONFIG_X86_ES7000) += es7000_32.o
obj-$(CONFIG_X86_SUMMIT) += summit_32.o
obj-$(CONFIG_X86_BIGSMP) += bigsmp_32.o
obj-$(CONFIG_X86_ES7000) += es7000_32.o

# For 32bit, probe_32 need to be listed last
obj-$(CONFIG_X86_LOCAL_APIC) += probe_$(BITS).o
48 changes: 13 additions & 35 deletions arch/x86/kernel/apic/apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1461,29 +1461,22 @@ int __init enable_IR(void)
void __init enable_IR_x2apic(void)
{
unsigned long flags;
struct IO_APIC_route_entry **ioapic_entries;
int ret, x2apic_enabled = 0;
int dmar_table_init_ret;

dmar_table_init_ret = dmar_table_init();
if (dmar_table_init_ret && !x2apic_supported())
return;

ioapic_entries = alloc_ioapic_entries();
if (!ioapic_entries) {
pr_err("Allocate ioapic_entries failed\n");
goto out;
}

ret = save_IO_APIC_setup(ioapic_entries);
ret = save_ioapic_entries();
if (ret) {
pr_info("Saving IO-APIC state failed: %d\n", ret);
goto out;
}

local_irq_save(flags);
legacy_pic->mask_all();
mask_IO_APIC_setup(ioapic_entries);
mask_ioapic_entries();

if (dmar_table_init_ret)
ret = 0;
Expand Down Expand Up @@ -1514,14 +1507,11 @@ void __init enable_IR_x2apic(void)

nox2apic:
if (!ret) /* IR enabling failed */
restore_IO_APIC_setup(ioapic_entries);
restore_ioapic_entries();
legacy_pic->restore_mask();
local_irq_restore(flags);

out:
if (ioapic_entries)
free_ioapic_entries(ioapic_entries);

if (x2apic_enabled)
return;

Expand Down Expand Up @@ -2095,28 +2085,20 @@ static void lapic_resume(void)
{
unsigned int l, h;
unsigned long flags;
int maxlvt, ret;
struct IO_APIC_route_entry **ioapic_entries = NULL;
int maxlvt;

if (!apic_pm_state.active)
return;

local_irq_save(flags);
if (intr_remapping_enabled) {
ioapic_entries = alloc_ioapic_entries();
if (!ioapic_entries) {
WARN(1, "Alloc ioapic_entries in lapic resume failed.");
goto restore;
}

ret = save_IO_APIC_setup(ioapic_entries);
if (ret) {
WARN(1, "Saving IO-APIC state failed: %d\n", ret);
free_ioapic_entries(ioapic_entries);
goto restore;
}

mask_IO_APIC_setup(ioapic_entries);
/*
* IO-APIC and PIC have their own resume routines.
* We just mask them here to make sure the interrupt
* subsystem is completely quiet while we enable x2apic
* and interrupt-remapping.
*/
mask_ioapic_entries();
legacy_pic->mask_all();
}

Expand Down Expand Up @@ -2159,13 +2141,9 @@ static void lapic_resume(void)
apic_write(APIC_ESR, 0);
apic_read(APIC_ESR);

if (intr_remapping_enabled) {
if (intr_remapping_enabled)
reenable_intr_remapping(x2apic_mode);
legacy_pic->restore_mask();
restore_IO_APIC_setup(ioapic_entries);
free_ioapic_entries(ioapic_entries);
}
restore:

local_irq_restore(flags);
}

Expand Down
Loading

0 comments on commit ea2b50e

Please sign in to comment.