x86, ioapic: Use ioapic_saved_data while enabling intr-remapping

Code flow for enabling interrupt-remapping was
allocating/freeing buffers for saving/restoring io-apic RTE's.
ioapic suspend/resume code uses boot time allocated
ioapic_saved_data that is a perfect match for reuse here.

This will remove the unnecessary allocation/free of the
temporary buffers during suspend/resume of interrupt-remapping
enabled platforms aswell as paving the way for further code
consolidation.

Tested-by: Daniel J Blueman <daniel.blueman@gmail.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Link: http://lkml.kernel.org/r/20110518233157.574469296@sbsiddha-MOBL3.sc.intel.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
Suresh Siddha 2011-05-18 16:31:33 -07:00 committed by Ingo Molnar
parent 4c79185cdb
commit 31dce14a32
3 changed files with 37 additions and 111 deletions

View file

@ -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); 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 int save_ioapic_entries(void);
extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries); extern void mask_ioapic_entries(void);
extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); extern int restore_ioapic_entries(void);
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 get_nr_irqs_gsi(void); extern int get_nr_irqs_gsi(void);
@ -192,19 +190,13 @@ struct io_apic_irq_attr;
static inline int io_apic_set_pci_routing(struct device *dev, int irq, static inline int io_apic_set_pci_routing(struct device *dev, int irq,
struct io_apic_irq_attr *irq_attr) { return 0; } struct io_apic_irq_attr *irq_attr) { return 0; }
static inline struct IO_APIC_route_entry **alloc_ioapic_entries(void) static inline int save_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)
{ {
return -ENOMEM; return -ENOMEM;
} }
static inline void mask_IO_APIC_setup(struct IO_APIC_route_entry **ent) { } static inline void mask_ioapic_entries(void) { }
static inline int restore_IO_APIC_setup(struct IO_APIC_route_entry **ent) static inline int restore_ioapic_entries(void)
{ {
return -ENOMEM; return -ENOMEM;
} }

View file

@ -1461,7 +1461,6 @@ int __init enable_IR(void)
void __init enable_IR_x2apic(void) void __init enable_IR_x2apic(void)
{ {
unsigned long flags; unsigned long flags;
struct IO_APIC_route_entry **ioapic_entries;
int ret, x2apic_enabled = 0; int ret, x2apic_enabled = 0;
int dmar_table_init_ret; int dmar_table_init_ret;
@ -1469,13 +1468,7 @@ void __init enable_IR_x2apic(void)
if (dmar_table_init_ret && !x2apic_supported()) if (dmar_table_init_ret && !x2apic_supported())
return; return;
ioapic_entries = alloc_ioapic_entries(); ret = save_ioapic_entries();
if (!ioapic_entries) {
pr_err("Allocate ioapic_entries failed\n");
goto out;
}
ret = save_IO_APIC_setup(ioapic_entries);
if (ret) { if (ret) {
pr_info("Saving IO-APIC state failed: %d\n", ret); pr_info("Saving IO-APIC state failed: %d\n", ret);
goto out; goto out;
@ -1483,7 +1476,7 @@ void __init enable_IR_x2apic(void)
local_irq_save(flags); local_irq_save(flags);
legacy_pic->mask_all(); legacy_pic->mask_all();
mask_IO_APIC_setup(ioapic_entries); mask_ioapic_entries();
if (dmar_table_init_ret) if (dmar_table_init_ret)
ret = 0; ret = 0;
@ -1514,14 +1507,11 @@ void __init enable_IR_x2apic(void)
nox2apic: nox2apic:
if (!ret) /* IR enabling failed */ if (!ret) /* IR enabling failed */
restore_IO_APIC_setup(ioapic_entries); restore_ioapic_entries();
legacy_pic->restore_mask(); legacy_pic->restore_mask();
local_irq_restore(flags); local_irq_restore(flags);
out: out:
if (ioapic_entries)
free_ioapic_entries(ioapic_entries);
if (x2apic_enabled) if (x2apic_enabled)
return; return;
@ -2095,28 +2085,20 @@ static void lapic_resume(void)
{ {
unsigned int l, h; unsigned int l, h;
unsigned long flags; unsigned long flags;
int maxlvt, ret; int maxlvt;
struct IO_APIC_route_entry **ioapic_entries = NULL;
if (!apic_pm_state.active) if (!apic_pm_state.active)
return; return;
local_irq_save(flags); local_irq_save(flags);
if (intr_remapping_enabled) { if (intr_remapping_enabled) {
ioapic_entries = alloc_ioapic_entries(); /*
if (!ioapic_entries) { * IO-APIC and PIC have their own resume routines.
WARN(1, "Alloc ioapic_entries in lapic resume failed."); * We just mask them here to make sure the interrupt
goto restore; * subsystem is completely quiet while we enable x2apic
} * and interrupt-remapping.
*/
ret = save_IO_APIC_setup(ioapic_entries); mask_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);
legacy_pic->mask_all(); legacy_pic->mask_all();
} }
@ -2159,13 +2141,9 @@ static void lapic_resume(void)
apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0);
apic_read(APIC_ESR); apic_read(APIC_ESR);
if (intr_remapping_enabled) { if (intr_remapping_enabled)
reenable_intr_remapping(x2apic_mode); 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); local_irq_restore(flags);
} }

View file

@ -101,7 +101,7 @@ int mp_irq_entries;
static int nr_irqs_gsi = NR_IRQS_LEGACY; static int nr_irqs_gsi = NR_IRQS_LEGACY;
/* /*
* Saved I/O APIC state during suspend/resume. * Saved I/O APIC state during suspend/resume, or while enabling intr-remap.
*/ */
static struct IO_APIC_route_entry *ioapic_saved_data[MAX_IO_APICS]; static struct IO_APIC_route_entry *ioapic_saved_data[MAX_IO_APICS];
@ -628,74 +628,43 @@ static int __init ioapic_pirq_setup(char *str)
__setup("pirq=", ioapic_pirq_setup); __setup("pirq=", ioapic_pirq_setup);
#endif /* CONFIG_X86_32 */ #endif /* CONFIG_X86_32 */
struct IO_APIC_route_entry **alloc_ioapic_entries(void)
{
int apic;
struct IO_APIC_route_entry **ioapic_entries;
ioapic_entries = kzalloc(sizeof(*ioapic_entries) * nr_ioapics,
GFP_ATOMIC);
if (!ioapic_entries)
return 0;
for (apic = 0; apic < nr_ioapics; apic++) {
ioapic_entries[apic] =
kzalloc(sizeof(struct IO_APIC_route_entry) *
nr_ioapic_registers[apic], GFP_ATOMIC);
if (!ioapic_entries[apic])
goto nomem;
}
return ioapic_entries;
nomem:
while (--apic >= 0)
kfree(ioapic_entries[apic]);
kfree(ioapic_entries);
return 0;
}
/* /*
* Saves all the IO-APIC RTE's * Saves all the IO-APIC RTE's
*/ */
int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries) int save_ioapic_entries(void)
{ {
int apic, pin; int apic, pin;
int err = 0;
if (!ioapic_entries)
return -ENOMEM;
for (apic = 0; apic < nr_ioapics; apic++) { for (apic = 0; apic < nr_ioapics; apic++) {
if (!ioapic_entries[apic]) if (!ioapic_saved_data[apic]) {
return -ENOMEM; err = -ENOMEM;
continue;
}
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
ioapic_entries[apic][pin] = ioapic_saved_data[apic][pin] =
ioapic_read_entry(apic, pin); ioapic_read_entry(apic, pin);
} }
return 0; return err;
} }
/* /*
* Mask all IO APIC entries. * Mask all IO APIC entries.
*/ */
void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries) void mask_ioapic_entries(void)
{ {
int apic, pin; int apic, pin;
if (!ioapic_entries)
return;
for (apic = 0; apic < nr_ioapics; apic++) { for (apic = 0; apic < nr_ioapics; apic++) {
if (!ioapic_entries[apic]) if (!ioapic_saved_data[apic])
break; continue;
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
struct IO_APIC_route_entry entry; struct IO_APIC_route_entry entry;
entry = ioapic_entries[apic][pin]; entry = ioapic_saved_data[apic][pin];
if (!entry.mask) { if (!entry.mask) {
entry.mask = 1; entry.mask = 1;
ioapic_write_entry(apic, pin, entry); ioapic_write_entry(apic, pin, entry);
@ -705,36 +674,23 @@ void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)
} }
/* /*
* Restore IO APIC entries which was saved in ioapic_entries. * Restore IO APIC entries which was saved in ioapic_saved_data
*/ */
int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries) int restore_ioapic_entries(void)
{ {
int apic, pin; int apic, pin;
if (!ioapic_entries)
return -ENOMEM;
for (apic = 0; apic < nr_ioapics; apic++) { for (apic = 0; apic < nr_ioapics; apic++) {
if (!ioapic_entries[apic]) if (!ioapic_saved_data[apic])
return -ENOMEM; continue;
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
ioapic_write_entry(apic, pin, ioapic_write_entry(apic, pin,
ioapic_entries[apic][pin]); ioapic_saved_data[apic][pin]);
} }
return 0; return 0;
} }
void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries)
{
int apic;
for (apic = 0; apic < nr_ioapics; apic++)
kfree(ioapic_entries[apic]);
kfree(ioapic_entries);
}
/* /*
* Find the IRQ entry number of a certain pin. * Find the IRQ entry number of a certain pin.
*/ */