Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 31dce14a authored by Suresh Siddha's avatar Suresh Siddha Committed by Ingo Molnar
Browse files

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: default avatarDaniel J Blueman <daniel.blueman@gmail.com>
Signed-off-by: default avatarSuresh Siddha <suresh.b.siddha@intel.com>
Link: http://lkml.kernel.org/r/20110518233157.574469296@sbsiddha-MOBL3.sc.intel.com


Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 4c79185c
Loading
Loading
Loading
Loading
+6 −14
Original line number Diff line number Diff line
@@ -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);

@@ -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;
}
+13 −35
Original line number Diff line number Diff line
@@ -1461,7 +1461,6 @@ 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;

@@ -1469,13 +1468,7 @@ void __init enable_IR_x2apic(void)
	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;
@@ -1483,7 +1476,7 @@ void __init enable_IR_x2apic(void)

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

	if (dmar_table_init_ret)
		ret = 0;
@@ -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;

@@ -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();
	}

@@ -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);
}

+18 −62
Original line number Diff line number Diff line
@@ -101,7 +101,7 @@ int mp_irq_entries;
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];

@@ -628,74 +628,43 @@ static int __init ioapic_pirq_setup(char *str)
__setup("pirq=", ioapic_pirq_setup);
#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
 */
int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)
int save_ioapic_entries(void)
{
	int apic, pin;

	if (!ioapic_entries)
		return -ENOMEM;
	int err = 0;

	for (apic = 0; apic < nr_ioapics; apic++) {
		if (!ioapic_entries[apic])
			return -ENOMEM;
		if (!ioapic_saved_data[apic]) {
			err = -ENOMEM;
			continue;
		}

		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
			ioapic_entries[apic][pin] =
			ioapic_saved_data[apic][pin] =
				ioapic_read_entry(apic, pin);
	}

	return 0;
	return err;
}

/*
 * 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;

	if (!ioapic_entries)
		return;

	for (apic = 0; apic < nr_ioapics; apic++) {
		if (!ioapic_entries[apic])
			break;
		if (!ioapic_saved_data[apic])
			continue;

		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
			struct IO_APIC_route_entry entry;

			entry = ioapic_entries[apic][pin];
			entry = ioapic_saved_data[apic][pin];
			if (!entry.mask) {
				entry.mask = 1;
				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;

	if (!ioapic_entries)
		return -ENOMEM;

	for (apic = 0; apic < nr_ioapics; apic++) {
		if (!ioapic_entries[apic])
			return -ENOMEM;
		if (!ioapic_saved_data[apic])
			continue;

		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
			ioapic_write_entry(apic, pin,
					ioapic_entries[apic][pin]);
					   ioapic_saved_data[apic][pin]);
	}
	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.
 */