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:
parent
4c79185cdb
commit
31dce14a32
3 changed files with 37 additions and 111 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue