Unverified Commit 6028d8a5 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!777 update patches for sw64 architecture

Merge Pull Request from: @guzitao 
 
These patches generally cover the following tasks:

1.optimize kernel cores, remove unused codes, fix compile errors
2.fixes for perf, iommu, kvm, cpufreq, efi, struct pt_regs
3.add support, add support for restartable sequences, trace user task unalignment, add libbfd support in perf
4.optimize DIV and MOD instructions for bpf 
 
Link:https://gitee.com/openeuler/kernel/pulls/777

 

Reviewed-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
Acked-by: default avatarXie XiuQi <xiexiuqi@huawei.com>
parents 4489c3c7 7cb1078b
Loading
Loading
Loading
Loading
+27 −262
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ config SW64
	select ARCH_USE_CMPXCHG_LOCKREF
	select ARCH_USE_QUEUED_RWLOCKS
	select ARCH_USE_QUEUED_SPINLOCKS
	select ARCH_WANT_DEFAULT_BPF_JIT
	select ARCH_WANT_FRAME_POINTERS
	select ARCH_WANT_IPC_PARSE_VERSION
	select AUDIT_ARCH
@@ -96,6 +97,7 @@ config SW64
	select HAVE_PERF_USER_STACK_DUMP
	select HAVE_REGS_AND_STACK_ACCESS_API
	select HAVE_RELIABLE_STACKTRACE if STACKTRACE
	select HAVE_RSEQ
	select HAVE_SYSCALL_TRACEPOINTS
	select IRQ_FORCED_THREADING
	select MEMORY_HOTPLUG_SPARSE if MEMORY_HOTPLUG
@@ -266,32 +268,7 @@ config LOCK_MEMB
	bool "Insert mem barrier before lock instruction"
	default y

menu "CPU Frequency scaling"

config CPU_FREQ
	bool "CPU Frequency scaling"
	select SRCU
	help
	  CPU Frequency scaling allows you to change the clock speed of
	  CPUs on the fly. This is a nice method to save power, because
	  the lower the CPU clock speed, the less power the CPU consumes.

	  Note that this driver doesn't automatically change the CPU
	  clock speed, you need to either enable a dynamic cpufreq governor
	  (see below) after boot, or use a userspace tool.

	  For details, take a look at <file:Documentation/cpu-freq>.

	  If in doubt, say N.

if CPU_FREQ

config SW64_CPUFREQ
        bool "sw64 CPU Frequency interface for Chip3 Asic"
	depends on SW64_CHIP3
	default y
        help
          Turns on the interface for SW64_CPU Frequency.
source "drivers/cpufreq/Kconfig"

config SW64_CPUAUTOPLUG
	bool "sw64 CPU Autoplug interface"
@@ -300,218 +277,6 @@ config SW64_CPUAUTOPLUG
	help
	  Turns on the interface for SW64_CPU CPUAUTOPLUG.

config CPU_FREQ_GOV_ATTR_SET
	bool

config CPU_FREQ_GOV_COMMON
	select CPU_FREQ_GOV_ATTR_SET
	select IRQ_WORK
	bool

config CPU_FREQ_BOOST_SW
	bool
	depends on THERMAL

config CPU_FREQ_STAT
	bool "CPU frequency transition statistics"
	help
	  Export CPU frequency statistics information through sysfs.

	  If in doubt, say N.

choice
	prompt "Default CPUFreq governor"
	default CPU_FREQ_DEFAULT_GOV_USERSPACE if ARM_SA1100_CPUFREQ || ARM_SA1110_CPUFREQ
	default CPU_FREQ_DEFAULT_GOV_PERFORMANCE
	help
	  This option sets which CPUFreq governor shall be loaded at
	  startup. If in doubt, select 'performance'.

config CPU_FREQ_DEFAULT_GOV_PERFORMANCE
	bool "performance"
	select CPU_FREQ_GOV_PERFORMANCE
	help
	  Use the CPUFreq governor 'performance' as default. This sets
	  the frequency statically to the highest frequency supported by
	  the CPU.

config CPU_FREQ_DEFAULT_GOV_POWERSAVE
	bool "powersave"
	select CPU_FREQ_GOV_POWERSAVE
	help
	  Use the CPUFreq governor 'powersave' as default. This sets
	  the frequency statically to the lowest frequency supported by
	  the CPU.

config CPU_FREQ_DEFAULT_GOV_USERSPACE
	bool "userspace"
	select CPU_FREQ_GOV_USERSPACE
	help
	  Use the CPUFreq governor 'userspace' as default. This allows
	  you to set the CPU frequency manually or when a userspace
	  program shall be able to set the CPU dynamically without having
	  to enable the userspace governor manually.

config CPU_FREQ_DEFAULT_GOV_ONDEMAND
	bool "ondemand"
	select CPU_FREQ_GOV_ONDEMAND
	select CPU_FREQ_GOV_PERFORMANCE
	help
	  Use the CPUFreq governor 'ondemand' as default. This allows
	  you to get a full dynamic frequency capable system by simply
	  loading your cpufreq low-level hardware driver.
	  Be aware that not all cpufreq drivers support the ondemand
	  governor. If unsure have a look at the help section of the
	  driver. Fallback governor will be the performance governor.

config CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
	bool "conservative"
	select CPU_FREQ_GOV_CONSERVATIVE
	select CPU_FREQ_GOV_PERFORMANCE
	help
	  Use the CPUFreq governor 'conservative' as default. This allows
	  you to get a full dynamic frequency capable system by simply
	  loading your cpufreq low-level hardware driver.
	  Be aware that not all cpufreq drivers support the conservative
	  governor. If unsure have a look at the help section of the
	  driver. Fallback governor will be the performance governor.

config CPU_FREQ_DEFAULT_GOV_SCHEDUTIL
	bool "schedutil"
	depends on SMP
	select CPU_FREQ_GOV_SCHEDUTIL
	select CPU_FREQ_GOV_PERFORMANCE
	help
	  Use the 'schedutil' CPUFreq governor by default. If unsure,
	  have a look at the help section of that governor. The fallback
	  governor will be 'performance'.

endchoice

config CPU_FREQ_GOV_PERFORMANCE
	tristate "'performance' governor"
	help
	  This cpufreq governor sets the frequency statically to the
	  highest available CPU frequency.

	  To compile this driver as a module, choose M here: the
	  module will be called cpufreq_performance.

	  If in doubt, say Y.

config CPU_FREQ_GOV_POWERSAVE
	tristate "'powersave' governor"
	help
	  This cpufreq governor sets the frequency statically to the
	  lowest available CPU frequency.

	  To compile this driver as a module, choose M here: the
	  module will be called cpufreq_powersave.

	  If in doubt, say Y.

config CPU_FREQ_GOV_USERSPACE
	tristate "'userspace' governor for userspace frequency scaling"
	help
	  Enable this cpufreq governor when you either want to set the
	  CPU frequency manually or when a userspace program shall
	  be able to set the CPU dynamically, like on LART
	  <http://www.lartmaker.nl/>.

	  To compile this driver as a module, choose M here: the
	  module will be called cpufreq_userspace.

	  For details, take a look at <file:Documentation/cpu-freq/>.

	  If in doubt, say Y.

config CPU_FREQ_GOV_ONDEMAND
	tristate "'ondemand' cpufreq policy governor"
	select CPU_FREQ_GOV_COMMON
	help
	  'ondemand' - This driver adds a dynamic cpufreq policy governor.
	  The governor does a periodic polling and
	  changes frequency based on the CPU utilization.
	  The support for this governor depends on CPU capability to
	  do fast frequency switching (i.e, very low latency frequency
	  transitions).

	  To compile this driver as a module, choose M here: the
	  module will be called cpufreq_ondemand.

	  For details, take a look at linux/Documentation/cpu-freq.

	  If in doubt, say N.

config CPU_FREQ_GOV_CONSERVATIVE
	tristate "'conservative' cpufreq governor"
	depends on CPU_FREQ
	select CPU_FREQ_GOV_COMMON
	help
	  'conservative' - this driver is rather similar to the 'ondemand'
	  governor both in its source code and its purpose, the difference is
	  its optimisation for better suitability in a battery powered
	  environment.  The frequency is gracefully increased and decreased
	  rather than jumping to 100% when speed is required.

	  If you have a desktop machine then you should really be considering
	  the 'ondemand' governor instead, however if you are using a laptop,
	  PDA or even an AMD64 based computer (due to the unacceptable
	  step-by-step latency issues between the minimum and maximum frequency
	  transitions in the CPU) you will probably want to use this governor.

	  To compile this driver as a module, choose M here: the
	  module will be called cpufreq_conservative.

	  For details, take a look at linux/Documentation/cpu-freq.

	  If in doubt, say N.

config CPU_FREQ_GOV_SCHEDUTIL
	bool "'schedutil' cpufreq policy governor"
	depends on CPU_FREQ && SMP
	select CPU_FREQ_GOV_ATTR_SET
	select IRQ_WORK
	help
	  This governor makes decisions based on the utilization data provided
	  by the scheduler.  It sets the CPU frequency to be proportional to
	  the utilization/capacity ratio coming from the scheduler.  If the
	  utilization is frequency-invariant, the new frequency is also
	  proportional to the maximum available frequency.  If that is not the
	  case, it is proportional to the current frequency of the CPU.  The
	  frequency tipping point is at utilization/capacity equal to 80% in
	  both cases.

	  If in doubt, say N.

comment "CPU frequency scaling drivers"

config CPUFREQ_DT
	tristate "Generic DT based cpufreq driver"
	depends on HAVE_CLK && OF
	# if CPU_THERMAL is on and THERMAL=m, CPUFREQ_DT cannot be =y:
	depends on !CPU_THERMAL || THERMAL
	select CPUFREQ_DT_PLATDEV
	select PM_OPP
	help
	  This adds a generic DT based cpufreq driver for frequency management.
	  It supports both uniprocessor (UP) and symmetric multiprocessor (SMP)
	  systems.

	  If in doubt, say N.

config CPUFREQ_DT_PLATDEV
	bool
	help
	  This adds a generic DT based cpufreq platdev driver for frequency
	  management.  This creates a 'cpufreq-dt' platform device, on the
	  supported platforms.

	  If in doubt, say N.

endif
endmenu

# clear all implied options (don't want default values for those):
# Most of these machines have ISA slots; not exactly sure which don't,
# and this doesn't activate hordes of code, so do it always.
+41 −36
Original line number Diff line number Diff line
@@ -124,6 +124,18 @@ static int chip3_get_cpu_nums(void)
	return cpus;
}

static void chip3_get_vt_smp_info(void)
{
	unsigned long smp_info;

	smp_info = sw64_io_read(0, SMP_INFO);
	if (smp_info == -1UL)
		smp_info = 0;
	topo_nr_threads = (smp_info >> VT_THREADS_SHIFT) & VT_THREADS_MASK;
	topo_nr_cores = (smp_info >> VT_CORES_SHIFT) & VT_CORES_MASK;
	topo_nr_maxcpus = (smp_info >> VT_MAX_CPUS_SHIFT) & VT_MAX_CPUS_MASK;
}

static unsigned long chip3_get_vt_node_mem(int nodeid)
{
	return *(unsigned long *)MMSIZE & MMSIZE_MASK;
@@ -528,6 +540,18 @@ static void chip3_pcie_save(void)
			piu_save->msiconfig[i] = read_piu_ior0(node, index,
					MSICONFIG0 + (i << 7));
		}

		piu_save->iommuexcpt_ctrl = read_piu_ior0(node, index, IOMMUEXCPT_CTRL);
		piu_save->dtbaseaddr = read_piu_ior0(node, index, DTBASEADDR);

		piu_save->intaconfig = read_piu_ior0(node, index, INTACONFIG);
		piu_save->intbconfig = read_piu_ior0(node, index, INTBCONFIG);
		piu_save->intcconfig = read_piu_ior0(node, index, INTCCONFIG);
		piu_save->intdconfig = read_piu_ior0(node, index, INTDCONFIG);
		piu_save->pmeintconfig = read_piu_ior0(node, index, PMEINTCONFIG);
		piu_save->aererrintconfig = read_piu_ior0(node, index, AERERRINTCONFIG);
		piu_save->hpintconfig = read_piu_ior0(node, index, HPINTCONFIG);

	}
}

@@ -555,6 +579,17 @@ static void chip3_pcie_restore(void)
					piu_save->msiconfig[i]);
		}

		write_piu_ior0(node, index, IOMMUEXCPT_CTRL, piu_save->iommuexcpt_ctrl);
		write_piu_ior0(node, index, DTBASEADDR, piu_save->dtbaseaddr);

		write_piu_ior0(node, index, INTACONFIG, piu_save->intaconfig);
		write_piu_ior0(node, index, INTBCONFIG, piu_save->intbconfig);
		write_piu_ior0(node, index, INTCCONFIG, piu_save->intcconfig);
		write_piu_ior0(node, index, INTDCONFIG, piu_save->intdconfig);
		write_piu_ior0(node, index, PMEINTCONFIG, piu_save->pmeintconfig);
		write_piu_ior0(node, index, AERERRINTCONFIG, piu_save->aererrintconfig);
		write_piu_ior0(node, index, HPINTCONFIG, piu_save->hpintconfig);

		/* Enable DBI_RO_WR_EN */
		rc_misc_ctrl = read_rc_conf(node, index, RC_MISC_CONTROL_1);
		write_rc_conf(node, index, RC_MISC_CONTROL_1, rc_misc_ctrl | 0x1);
@@ -604,41 +639,6 @@ static inline void chip3_spbu_restore(void)
	sw64_io_write(0, MCU_DVC_INT_EN, saved_dvc_int);
}

#define BIOS_SECBIN	0x2F00000UL
#define BIOS_SECSIZE	0x40000UL
#define	BOUNCE_BUFFER	((1UL<<32) - BIOS_SECSIZE)
#define	BIOS_MEMSAVE	((1UL<<32) - 2 * BIOS_SECSIZE)

/*
 * Due to specific architecture PCI MEM32 addressing, we reserve 512M memory
 * size at PCI_32BIT_MEMIO (0xE000_0000) on SW64 platform.
 *
 * Since this memory region is still usable by OS, we implement a interface
 * contract between BIOS and kernel:
 *
 * Firstly BIOS should back up SEC relative code segment to BIOS_MEMSAVE region
 * with the length BIOS_SECSIZE in order to restore BIOS SEC phase binary during
 * S3 sleep.
 *
 * Secondly kernel should use a bounce buffer to save memory region which may be
 * overwritten by BIOS on resume from S3 sleep.
 */
static void chip3_mem_restore(void)
{
	void *dst, *src;
	unsigned long size = BIOS_SECSIZE;

	/* Firstly kernel back up to a bounce buffer */
	src = __va(BIOS_SECBIN);
	dst = __va(BOUNCE_BUFFER);
	memcpy(dst, src, size);

	/* Secondly restore BIOS SEC phase binary */
	src = __va(BIOS_MEMSAVE);
	dst = __va(BIOS_SECBIN);
	memcpy(dst, src, size);
}

extern void cpld_write(uint8_t slave_addr, uint8_t reg, uint8_t data);

static void chip3_suspend(bool wakeup)
@@ -655,7 +655,6 @@ static void chip3_suspend(bool wakeup)
		chip3_spbu_save();
		chip3_intpu_save();
		chip3_pcie_save();
		chip3_mem_restore();
	}
}

@@ -712,6 +711,7 @@ static void chip3_init_ops_fixup(void)
	if (is_guest_or_emul()) {
		sw64_chip_init->early_init.setup_core_start = chip3_setup_vt_core_start;
		sw64_chip_init->early_init.get_node_mem = chip3_get_vt_node_mem;
		sw64_chip_init->early_init.get_smp_info = chip3_get_vt_smp_info;
		sw64_chip_init->pci_init.check_pci_linkup = chip3_check_pci_vt_linkup;
	}
};
@@ -826,6 +826,7 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector,
			  unsigned long irq_arg, struct pt_regs *regs)
{
	struct pt_regs *old_regs;
	extern char __idle_start[], __idle_end[];

	if (is_guest_or_emul()) {
		if ((type & 0xffff) > 15) {
@@ -837,6 +838,10 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector,
		}
	}

	/* restart idle routine if it is interrupted */
	if (regs->pc > (u64)__idle_start && regs->pc < (u64)__idle_end)
		regs->pc = (u64)__idle_start;

	switch (type & 0xffff) {
	case INT_MSI:
		old_regs = set_irq_regs(regs);
+66 −68
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
#include <linux/irqdomain.h>

#include <asm/irq_impl.h>
#include <asm/kvm_emulate.h>

static struct irq_domain *msi_default_domain;
static DEFINE_RAW_SPINLOCK(vector_lock);
@@ -12,19 +13,6 @@ DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
	[0 ... PERCPU_MSI_IRQS - 1] = 0,
};

struct sw64_msi_chip_data {
	spinlock_t cdata_lock;
	unsigned long msi_config;
	unsigned long rc_node;
	unsigned long rc_index;
	unsigned int msi_config_index;
	unsigned int dst_coreid;
	unsigned int vector;
	unsigned int prev_coreid;
	unsigned int prev_vector;
	bool move_in_progress;
};

static struct sw64_msi_chip_data *alloc_sw_msi_chip_data(struct irq_data *irq_data)
{
	struct sw64_msi_chip_data *data;
@@ -48,52 +36,59 @@ static void irq_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
	msg->data = chip_data->msi_config_index;
}

static bool find_free_core_vector(const struct cpumask *search_mask, int *found_coreid, int *found_vector)
bool find_free_cpu_vector(const struct cpumask *search_mask,
			  int *found_cpu, int *found_vector)
{
	int vector, coreid;
	bool found = false, find_once_global = false;
	int vector, max_vector, cpu;
	bool find_once_global = false;

	coreid = cpumask_first(search_mask);
	cpu = cpumask_first(search_mask);
try_again:
	for (vector = 0; vector < 256; vector++) {
		while (per_cpu(vector_irq, coreid)[vector]) {
			coreid = cpumask_next(coreid, search_mask);
			if (coreid >= nr_cpu_ids) {
	if (is_guest_or_emul()) {
		vector = IRQ_PENDING_MSI_VECTORS_SHIFT;
		max_vector = SWVM_IRQS;
	} else {
		vector = 0;
		max_vector = 256;
	}
	for (; vector < max_vector; vector++) {
		while (per_cpu(vector_irq, cpu)[vector]) {
			cpu = cpumask_next(cpu, search_mask);
			if (cpu >= nr_cpu_ids) {
				if (vector == 255) {
					if (find_once_global) {
						printk("No global free vector\n");
						return found;
						return false;
					}
					printk("No local free vector\n");
					search_mask = cpu_online_mask;
					coreid = cpumask_first(search_mask);
					cpu = cpumask_first(search_mask);
					find_once_global = true;
					goto try_again;
				}
				coreid = cpumask_first(search_mask);
				cpu = cpumask_first(search_mask);
				break;
			}
		}
		if (!per_cpu(vector_irq, coreid)[vector])
		if (!per_cpu(vector_irq, cpu)[vector])
			break;
	}

	found = true;
	*found_coreid = coreid;
	*found_cpu = cpu;
	*found_vector = vector;
	return found;
	return true;
}

static unsigned long set_piu_msi_config(struct pci_controller *hose, int found_coreid,
		int msiconf_index, int found_vector)
static unsigned long set_piu_msi_config(struct pci_controller *hose, int cpu,
		int msiconf_index, int vector)
{
	unsigned int reg;
	unsigned long msi_config;
	int phy_coreid;
	int phy_cpu;

	msi_config = (1UL << 62) | ((unsigned long)found_vector << 10);
	phy_coreid = cpu_to_rcid(found_coreid);
	msi_config |= ((phy_coreid >> 5) << 6) | (phy_coreid & 0x1f);
	msi_config = (1UL << 62) | ((unsigned long)vector << 10);
	phy_cpu = cpu_to_rcid(cpu);
	msi_config |= ((phy_cpu >> 5) << 6) | (phy_cpu & 0x1f);
	reg = MSICONFIG0 + (unsigned long)(msiconf_index << 7);
	write_piu_ior0(hose->node, hose->index, reg, msi_config);
	msi_config = read_piu_ior0(hose->node, hose->index, reg);
@@ -110,7 +105,7 @@ static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
	struct msi_desc *entry;
	struct cpumask searchmask;
	unsigned long flags, msi_config;
	int found_vector, found_coreid;
	int vector, cpu;

	/* Is this valid ? */
	if (cpumask_any_and(cpumask, cpu_online_mask) >= nr_cpu_ids)
@@ -125,14 +120,17 @@ static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
	if (!cdata)
		return -ENOMEM;

	/* If existing target coreid is already in the new mask, and is online then do nothing.*/
	if (cpu_online(cdata->dst_coreid) && cpumask_test_cpu(cdata->dst_coreid, cpumask))
	/*
	 * If existing target cpu is already in the new mask and is online
	 * then do nothing.
	 */
	if (cpu_online(cdata->dst_cpu) && cpumask_test_cpu(cdata->dst_cpu, cpumask))
		return IRQ_SET_MASK_OK;

	raw_spin_lock_irqsave(&vector_lock, flags);

	cpumask_and(&searchmask, cpumask, cpu_online_mask);
	if (!find_free_core_vector(&searchmask, &found_coreid, &found_vector)) {
	if (!find_free_cpu_vector(&searchmask, &cpu, &vector)) {
		raw_spin_unlock_irqrestore(&vector_lock, flags);
		return -ENOSPC;
	}
@@ -141,12 +139,12 @@ static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
	entry = irq_get_msi_desc(irqd->irq);
	hose = (struct pci_controller *)msi_desc_to_pci_sysdata(entry);
	spin_lock(&cdata->cdata_lock);
	per_cpu(vector_irq, found_coreid)[found_vector] = irqd->irq;
	msi_config = set_piu_msi_config(hose, found_coreid, cdata->msi_config_index, found_vector);
	per_cpu(vector_irq, cpu)[vector] = irqd->irq;
	msi_config = set_piu_msi_config(hose, cpu, cdata->msi_config_index, vector);
	cdata->prev_vector = cdata->vector;
	cdata->prev_coreid = cdata->dst_coreid;
	cdata->dst_coreid = found_coreid;
	cdata->vector = found_vector;
	cdata->prev_cpu = cdata->dst_cpu;
	cdata->dst_cpu = cpu;
	cdata->vector = vector;
	cdata->msi_config = msi_config;
	cdata->move_in_progress = true;
	spin_unlock(&cdata->cdata_lock);
@@ -178,8 +176,8 @@ static int __assign_irq_vector(int virq, unsigned int nr_irqs,
	const struct cpumask *mask;
	struct cpumask searchmask;
	struct sw64_msi_chip_data *cdata;
	int msiconf_index, coreid, node;
	int i, found_vector, found_coreid;
	int msiconf_index, node;
	int i, vector, cpu;
	unsigned long msi_config;
	int start_index;

@@ -207,15 +205,14 @@ static int __assign_irq_vector(int virq, unsigned int nr_irqs,
		cpumask_copy(&searchmask, cpumask_of_node(node));
	}

	coreid = cpumask_first(&searchmask);
	if (coreid >= nr_cpu_ids)
	if (cpumask_first(&searchmask) >= nr_cpu_ids)
		cpumask_copy(&searchmask, cpu_online_mask);

	for (i = 0; i < nr_irqs; i++) {
		if (!find_free_core_vector(&searchmask, &found_coreid, &found_vector))
		if (!find_free_cpu_vector(&searchmask, &cpu, &vector))
			return -ENOSPC;

		per_cpu(vector_irq, found_coreid)[found_vector] = virq + i;
		per_cpu(vector_irq, cpu)[vector] = virq + i;

		if (i) {
			irq_data = irq_domain_get_irq_data(domain, virq + i);
@@ -230,16 +227,16 @@ static int __assign_irq_vector(int virq, unsigned int nr_irqs,

		irq_data->chip_data = cdata;
		msiconf_index = start_index + i;
		msi_config = set_piu_msi_config(hose, found_coreid, msiconf_index, found_vector);
		msi_config = set_piu_msi_config(hose, cpu, msiconf_index, vector);

		cdata->dst_coreid = found_coreid;
		cdata->vector = found_vector;
		cdata->dst_cpu = cpu;
		cdata->vector = vector;
		cdata->rc_index = hose->index;
		cdata->rc_node = hose->node;
		cdata->msi_config = msi_config;
		cdata->msi_config_index = msiconf_index;
		cdata->prev_coreid = found_coreid;
		cdata->prev_vector = found_vector;
		cdata->prev_cpu = cpu;
		cdata->prev_vector = vector;
		cdata->move_in_progress = false;
	}
	return 0;
@@ -279,7 +276,7 @@ static void sw64_vector_free_irqs(struct irq_domain *domain,
				clear_bit(cdata->msi_config_index, hose->piu_msiconfig);
			}
			irq_domain_reset_irq_data(irq_data);
			per_cpu(vector_irq, cdata->dst_coreid)[cdata->vector] = 0;
			per_cpu(vector_irq, cdata->dst_cpu)[cdata->vector] = 0;
			kfree(cdata);
			raw_spin_unlock_irqrestore(&vector_lock, flags);
		}
@@ -288,8 +285,10 @@ static void sw64_vector_free_irqs(struct irq_domain *domain,

static void sw64_irq_free_descs(unsigned int virq, unsigned int nr_irqs)
{
	if (is_guest_or_emul())
	if (is_guest_or_emul()) {
		vt_sw64_vector_free_irqs(virq, nr_irqs);
		return irq_free_descs(virq, nr_irqs);
	}

	return irq_domain_free_irqs(virq, nr_irqs);
}
@@ -399,22 +398,22 @@ void arch_init_msi_domain(struct irq_domain *parent)
		pr_warn("failed to initialize irqdomain for MSI/MSI-x.\n");
}

static void irq_move_complete(struct sw64_msi_chip_data *cdata, int coreid, int vector)
static void irq_move_complete(struct sw64_msi_chip_data *cdata, int cpu, int vector)
{
	if (likely(!cdata->move_in_progress))
		return;
	if (vector == cdata->vector && cdata->dst_coreid == coreid) {
	if (vector == cdata->vector && cdata->dst_cpu == cpu) {
		raw_spin_lock(&vector_lock);
		cdata->move_in_progress = 0;
		per_cpu(vector_irq, cdata->prev_coreid)[cdata->prev_vector] = 0;
		per_cpu(vector_irq, cdata->prev_cpu)[cdata->prev_vector] = 0;
		raw_spin_unlock(&vector_lock);
	}
}

void handle_pci_msi_interrupt(unsigned long type, unsigned long vector, unsigned long pci_msi1_addr)
{
	int i, msi_index = 0;
	int vector_index = 0, logical_cid;
	int i, irq, piu_index, msi_index = 0;
	int cpu, vector_index = 0;
	unsigned long value = 0;
	unsigned long int_pci_msi[3];
	unsigned long *ptr;
@@ -422,7 +421,9 @@ void handle_pci_msi_interrupt(unsigned long type, unsigned long vector, unsigned
	struct sw64_msi_chip_data *cdata;

	if (is_guest_or_emul()) {
		handle_irq(vector);
		cpu = smp_processor_id();
		irq = per_cpu(vector_irq, cpu)[vector];
		handle_irq(irq);
		return;
	}

@@ -431,25 +432,22 @@ void handle_pci_msi_interrupt(unsigned long type, unsigned long vector, unsigned
	int_pci_msi[1] = *(ptr + 1);
	int_pci_msi[2] = *(ptr + 2);

	logical_cid = smp_processor_id();
	cpu = smp_processor_id();

	for (i = 0; i < 4; i++) {
		vector_index = i * 64;
		while (vector != 0) {
			int irq = 0;
			int piu_index = 0;

			msi_index = find_next_bit(&vector, 64, msi_index);
			if (msi_index == 64) {
				msi_index = 0;
				continue;
			}

			irq = per_cpu(vector_irq, logical_cid)[vector_index + msi_index];
			irq = per_cpu(vector_irq, cpu)[vector_index + msi_index];
			irq_data = irq_domain_get_irq_data(msi_default_domain->parent, irq);
			cdata = irq_data_get_irq_chip_data(irq_data);
			spin_lock(&cdata->cdata_lock);
			irq_move_complete(cdata, logical_cid, vector_index + msi_index);
			irq_move_complete(cdata, cpu, vector_index + msi_index);
			piu_index = cdata->msi_config_index;
			value = cdata->msi_config | (1UL << 63);
			write_piu_ior0(cdata->rc_node, cdata->rc_index, MSICONFIG0 + (piu_index << 7), value);
+122 −28

File changed.

Preview size limit exceeded, changes collapsed.

+633 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading