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

Commit 948a7b2b authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge branch 'irq/sparseirq' into cpus4096

Conflicts:
	arch/x86/kernel/io_apic.c

Merge irq/sparseirq here, to resolve conflicts.
parents 9466d603 17483a1f
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -243,7 +243,7 @@ config X86_HAS_BOOT_CPU_ID

config SPARSE_IRQ
	bool "Support sparse irq numbering"
	depends on (PCI_MSI || HT_IRQ) && SMP
	depends on PCI_MSI || HT_IRQ
	default y
	help
	  This enables support for sparse irq, esp for msi/msi-x. You may need
@@ -251,6 +251,15 @@ config SPARSE_IRQ

	  If you don't know what to do here, say Y.

config NUMA_MIGRATE_IRQ_DESC
	bool "Move irq desc when changing irq smp_affinity"
	depends on SPARSE_IRQ && SMP
	default n
	help
	  This enables moving irq_desc to cpu/node that irq will use handled.

	  If you don't know what to do here, say N.

config X86_FIND_SMP_CONFIG
	def_bool y
	depends on X86_MPPARSE || X86_VOYAGER
+141 −1
Original line number Diff line number Diff line
@@ -141,6 +141,9 @@ struct irq_cfg {
	unsigned move_cleanup_count;
	u8 vector;
	u8 move_in_progress : 1;
#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
	u8 move_desc_pending : 1;
#endif
};

/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
@@ -241,6 +244,121 @@ void arch_init_chip_data(struct irq_desc *desc, int cpu)
	}
}

#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC

static void
init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int cpu)
{
	struct irq_pin_list *old_entry, *head, *tail, *entry;

	cfg->irq_2_pin = NULL;
	old_entry = old_cfg->irq_2_pin;
	if (!old_entry)
		return;

	entry = get_one_free_irq_2_pin(cpu);
	if (!entry)
		return;

	entry->apic	= old_entry->apic;
	entry->pin	= old_entry->pin;
	head		= entry;
	tail		= entry;
	old_entry	= old_entry->next;
	while (old_entry) {
		entry = get_one_free_irq_2_pin(cpu);
		if (!entry) {
			entry = head;
			while (entry) {
				head = entry->next;
				kfree(entry);
				entry = head;
			}
			/* still use the old one */
			return;
		}
		entry->apic	= old_entry->apic;
		entry->pin	= old_entry->pin;
		tail->next	= entry;
		tail		= entry;
		old_entry	= old_entry->next;
	}

	tail->next = NULL;
	cfg->irq_2_pin = head;
}

static void free_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg)
{
	struct irq_pin_list *entry, *next;

	if (old_cfg->irq_2_pin == cfg->irq_2_pin)
		return;

	entry = old_cfg->irq_2_pin;

	while (entry) {
		next = entry->next;
		kfree(entry);
		entry = next;
	}
	old_cfg->irq_2_pin = NULL;
}

void arch_init_copy_chip_data(struct irq_desc *old_desc,
				 struct irq_desc *desc, int cpu)
{
	struct irq_cfg *cfg;
	struct irq_cfg *old_cfg;

	cfg = get_one_free_irq_cfg(cpu);

	if (!cfg)
		return;

	desc->chip_data = cfg;

	old_cfg = old_desc->chip_data;

	memcpy(cfg, old_cfg, sizeof(struct irq_cfg));

	init_copy_irq_2_pin(old_cfg, cfg, cpu);
}

static void free_irq_cfg(struct irq_cfg *old_cfg)
{
	kfree(old_cfg);
}

void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
{
	struct irq_cfg *old_cfg, *cfg;

	old_cfg = old_desc->chip_data;
	cfg = desc->chip_data;

	if (old_cfg == cfg)
		return;

	if (old_cfg) {
		free_irq_2_pin(old_cfg, cfg);
		free_irq_cfg(old_cfg);
		old_desc->chip_data = NULL;
	}
}

static void set_extra_move_desc(struct irq_desc *desc, cpumask_t mask)
{
	struct irq_cfg *cfg = desc->chip_data;

	if (!cfg->move_in_progress) {
		/* it means that domain is not changed */
		if (!cpus_intersects(desc->affinity, mask))
			cfg->move_desc_pending = 1;
	}
}
#endif

#else
static struct irq_cfg *irq_cfg(unsigned int irq)
{
@@ -249,10 +367,12 @@ static struct irq_cfg *irq_cfg(unsigned int irq)

#endif

#ifndef CONFIG_NUMA_MIGRATE_IRQ_DESC
static inline void
set_extra_move_desc(struct irq_desc *desc, const struct cpumask *mask)
{
}
#endif

struct io_apic {
	unsigned int index;
@@ -2397,11 +2517,31 @@ static void irq_complete_move(struct irq_desc **descp)
	struct irq_cfg *cfg = desc->chip_data;
	unsigned vector, me;

	if (likely(!cfg->move_in_progress))
	if (likely(!cfg->move_in_progress)) {
#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
		if (likely(!cfg->move_desc_pending))
			return;

		/* domain is not change, but affinity is changed */
		me = smp_processor_id();
		if (cpu_isset(me, desc->affinity)) {
			*descp = desc = move_irq_desc(desc, me);
			/* get the new one */
			cfg = desc->chip_data;
			cfg->move_desc_pending = 0;
		}
#endif
		return;
	}

	vector = ~get_irq_regs()->orig_ax;
	me = smp_processor_id();
#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
		*descp = desc = move_irq_desc(desc, me);
		/* get the new one */
		cfg = desc->chip_data;
#endif

	if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
		send_cleanup_vector(cfg);
}
+1 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
#include <linux/pci.h>
#include <linux/irq.h>
#include <asm/io_apic.h>
#include <asm/smp.h>
#include <linux/intel-iommu.h>
#include "intr_remapping.h"

+2 −5
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ static int show_stat(struct seq_file *p, void *v)
	u64 sum = 0;
	struct timespec boottime;
	unsigned int per_irq_sum;
	struct irq_desc *desc;

	user = nice = system = idle = iowait =
		irq = softirq = steal = cputime64_zero;
@@ -47,8 +46,7 @@ static int show_stat(struct seq_file *p, void *v)
		guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest);
		for_each_irq_nr(j) {
#ifdef CONFIG_SPARSE_IRQ
			desc = irq_to_desc(j);
			if (!desc)
			if (!irq_to_desc(j))
				continue;
#endif
			sum += kstat_irqs_cpu(j, i);
@@ -98,8 +96,7 @@ static int show_stat(struct seq_file *p, void *v)
	for_each_irq_nr(j) {
		per_irq_sum = 0;
#ifdef CONFIG_SPARSE_IRQ
		desc = irq_to_desc(j);
		if (!desc) {
		if (!irq_to_desc(j)) {
			seq_printf(p, " %u", per_irq_sum);
			continue;
		}
+10 −0
Original line number Diff line number Diff line
@@ -228,6 +228,16 @@ extern struct irq_desc *move_irq_desc(struct irq_desc *old_desc, int cpu);

#endif

static inline struct irq_desc *
irq_remap_to_desc(unsigned int irq, struct irq_desc *desc)
{
#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
	return irq_to_desc(irq);
#else
	return desc;
#endif
}

/*
 * Migration helpers for obsolete names, they will go away:
 */
Loading