Commit f0f2811d authored by Zheng Chongzhen's avatar Zheng Chongzhen Committed by guzitao
Browse files

sw64: msi: split the msi file

Sunway inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IBDJNZ



--------------------------------

Since C3B and C4 have different msi interrupt mechanisms, we decided to
implement them separately.

Signed-off-by: default avatarZheng Chongzhen <zhengchongzhen@wxiat.com>
Reviewed-by: default avatarHe Sheng <hesheng@wxiat.com>
Signed-off-by: default avatarGu Zitao <guzitao@wxiat.com>
parent 5c2d6d57
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -30,7 +30,13 @@ obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o
obj-$(CONFIG_SW64_INTC_V2)     		+= irq-sw64-intc-v2.o
obj-$(CONFIG_SW64_LPC_INTC)		+= irq-sw64-lpc-intc.o
obj-$(CONFIG_SW64_IRQ_CPU)		+= irq-sunway-cpu.o

ifeq ($(CONFIG_UNCORE_XUELANG),y)
obj-$(CONFIG_SW64_IRQ_MSI)		+= irq-sunway-msi.o
else
obj-$(CONFIG_SW64_IRQ_MSI)		+= irq-sunway-msi-v2.o
endif

obj-$(CONFIG_SW64_IRQ_MSI_VT)		+= irq-sunway-msi-vt.o
obj-$(CONFIG_ARM_GIC_PM)		+= irq-gic-pm.o
obj-$(CONFIG_ARCH_REALVIEW)		+= irq-gic-realview.o
+517 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/msi.h>
#include <linux/irqdomain.h>
#include <linux/smp.h>

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

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

static struct sw64_msi_chip_data *alloc_sw_msi_chip_data(struct irq_data *irq_data)
{
	struct sw64_msi_chip_data *data;
	int node;

	node = irq_data_get_node(irq_data);
	data = kzalloc_node(sizeof(*data), GFP_KERNEL, node);
	if (!data)
		return NULL;
	spin_lock_init(&data->cdata_lock);
	return data;
}

static void irq_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
{
	struct sw64_msi_chip_data *chip_data;
	int rcid;

	chip_data = irq_data_get_irq_chip_data(data->parent_data);
	rcid = cpu_to_rcid(chip_data->dst_cpu);
	msg->address_hi = MSI_ADDR_BASE_HI;
	msg->address_lo =
		(unsigned int)chip_data->msiaddr |
		(rcid_to_msicid(rcid) << MSI_ADDR_DEST_ID_SHIFT);
	msg->data = chip_data->vector;
}

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

	cpu = cpumask_first(search_mask);
try_again:
	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 false;
					}
					printk("No local free vector\n");
					search_mask = cpu_online_mask;
					cpu = cpumask_first(search_mask);
					find_once_global = true;
					goto try_again;
				}
				cpu = cpumask_first(search_mask);
				break;
			}
		}
		if (!per_cpu(vector_irq, cpu)[vector])
			break;
	}

	*found_cpu = cpu;
	*found_vector = vector;
	return true;
}

static bool find_free_cpu_vectors(const struct cpumask *search_mask, int *found_cpu, int *found_vector, unsigned int nr_irqs)
{
	int i, vector, cpu;
	bool found = false, find_once_global = false;

	cpu = cpumask_first(search_mask);
try_again:
	for (vector = 0; vector < 256; vector++) {
		for (i = 0; i < nr_irqs; i++)
			if (per_cpu(vector_irq, cpu)[vector + i])
				break;

		if (i == nr_irqs) {
			found = true;
			*found_cpu = cpu;
			*found_vector = vector;
			return found;
		}

		vector += i;
	}

	cpu = cpumask_next(cpu, search_mask);
	if (cpu < nr_cpu_ids)
		goto try_again;
	else {
		if (find_once_global) {
			printk("No global free vectors\n");
			return found;
		}
		printk("No local free vectors\n");
		search_mask = cpu_online_mask;
		cpu = cpumask_first(search_mask);
		find_once_global = true;
		goto try_again;
	}
}

static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask, bool force)
{
	struct sw64_msi_chip_data *cdata;
	struct irq_data *irqd;
	struct msi_desc *entry;
	struct cpumask searchmask;
	unsigned long flags;
	int vector, cpu;
	int i;
	struct msi_msg msg;

	/* Is this valid ? */
	if (cpumask_any_and(cpumask, cpu_online_mask) >= nr_cpu_ids)
		return -EINVAL;

	irqd = irq_domain_get_irq_data(msi_default_domain->parent, d->irq);
	/* Don't do anything if the interrupt isn't started */
	if (!irqd_is_started(irqd))
		return IRQ_SET_MASK_OK;

	cdata = irqd->chip_data;
	if (!cdata)
		return -ENOMEM;

	/*
	 * 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 (cdata->multi_msi > 1) {
		if (!find_free_cpu_vectors(&searchmask, &cpu,
					&vector, cdata->multi_msi)) {
			raw_spin_unlock_irqrestore(&vector_lock, flags);
			return -ENOSPC;
		}
	} else {
		if (!find_free_cpu_vector(&searchmask, &cpu, &vector)) {
			raw_spin_unlock_irqrestore(&vector_lock, flags);
			return -ENOSPC;
		}
	}

	/* update new setting */
	entry = irq_get_msi_desc(irqd->irq);
	spin_lock(&cdata->cdata_lock);
	for (i = 0; i < cdata->multi_msi; i++)
		per_cpu(vector_irq, cpu)[vector + i] = entry->irq + i;
	BUG_ON(irq_chip_compose_msi_msg(irqd, &msg));
	__pci_write_msi_msg(entry, &msg);
	cdata->prev_vector = cdata->vector;
	cdata->prev_cpu = cdata->dst_cpu;
	cdata->dst_cpu = cpu;
	cdata->vector = vector;
	cdata->move_in_progress = true;
	spin_unlock(&cdata->cdata_lock);
	cpumask_copy(irq_data_get_affinity_mask(irqd), &searchmask);

	raw_spin_unlock_irqrestore(&vector_lock, flags);

	return 0;
}

static void chip_irq_ack(struct irq_data *data)
{
}

static struct irq_chip pci_msi_controller = {
	.name                   = "PCI-MSI",
	.irq_unmask             = pci_msi_unmask_irq,
	.irq_mask               = pci_msi_mask_irq,
	.irq_ack                = chip_irq_ack,
	.irq_compose_msi_msg    = irq_msi_compose_msg,
	.flags                  = IRQCHIP_SKIP_SET_WAKE,
	.irq_set_affinity	= sw64_set_affinity,
};

static int __assign_irq_vector(int virq, unsigned int nr_irqs,
		struct irq_domain *domain, enum irq_alloc_type type)
{
	struct irq_data *irq_data;
	const struct cpumask *mask;
	struct cpumask searchmask;
	struct sw64_msi_chip_data *cdata;
	int node;
	int i, vector, cpu;
	unsigned long msiaddr;

	if (unlikely((nr_irqs > 1) && (!is_power_of_2(nr_irqs))))
		nr_irqs = __roundup_pow_of_two(nr_irqs);

	irq_data = irq_domain_get_irq_data(domain, virq);
	BUG_ON(!irq_data);
	irq_data->chip = &pci_msi_controller;

	if (irqd_affinity_is_managed(irq_data)) {
		mask = irq_data_get_affinity_mask(irq_data);
		cpumask_and(&searchmask, mask, cpu_online_mask);
	} else {
		node = irq_data_get_node(irq_data);
		cpumask_copy(&searchmask, cpumask_of_node(node));
	}

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

	if (type == IRQ_ALLOC_TYPE_MSI && nr_irqs > 1) {
		if (!find_free_cpu_vectors(&searchmask, &cpu,
					&vector, nr_irqs))
			return -ENOSPC;

		cdata = alloc_sw_msi_chip_data(irq_data);
		if (!cdata) {
			printk("error alloc irq chip data\n");
			return -ENOMEM;
		}

		for (i = 0; i < nr_irqs; i++) {
			per_cpu(vector_irq, cpu)[vector + i] = virq + i;

			if (i) {
				irq_data = irq_domain_get_irq_data(domain, virq + i);
				irq_data->chip = &pci_msi_controller;
			}

			irq_data->chip_data = cdata;
		}

		cdata->dst_cpu = cpu;
		cdata->vector = vector;
		cdata->msiaddr = MSIX_MSG_ADDR;
		cdata->prev_cpu = cpu;
		cdata->prev_vector = vector;
		cdata->multi_msi = nr_irqs;
		cdata->move_in_progress = false;
	} else {
		for (i = 0; i < nr_irqs; i++) {
			if (!find_free_cpu_vector(&searchmask, &cpu, &vector))
				return -ENOSPC;

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

			if (i) {
				irq_data = irq_domain_get_irq_data(domain, virq + i);
				irq_data->chip = &pci_msi_controller;
			}

			cdata = alloc_sw_msi_chip_data(irq_data);
			if (!cdata) {
				printk("error alloc irq chip data\n");
				return -ENOMEM;
			}

			irq_data->chip_data = cdata;

			cdata->dst_cpu = cpu;
			cdata->vector = vector;
			cdata->msiaddr = MSIX_MSG_ADDR;
			cdata->prev_cpu = cpu;
			cdata->prev_vector = vector;
			cdata->multi_msi = 1;
			cdata->move_in_progress = false;
		}
	}
	return 0;
}

static int assign_irq_vector(int irq, unsigned int nr_irqs,
		struct irq_domain *domain, enum irq_alloc_type type)
{
	int err;
	unsigned long flags;

	raw_spin_lock_irqsave(&vector_lock, flags);
	err = __assign_irq_vector(irq, nr_irqs, domain, type);
	raw_spin_unlock_irqrestore(&vector_lock, flags);
	return err;
}

static void sw64_vector_free_irqs(struct irq_domain *domain,
		unsigned int virq, unsigned int nr_irqs)
{
	int i, j;
	struct irq_data *irq_data;
	unsigned long flags;
	unsigned int multi_msi;

	for (i = 0; i < nr_irqs; i++) {
		irq_data = irq_domain_get_irq_data(domain, virq + i);
		if (irq_data && irq_data->chip_data) {
			struct sw64_msi_chip_data *cdata;

			raw_spin_lock_irqsave(&vector_lock, flags);
			cdata = irq_data->chip_data;
			irq_domain_reset_irq_data(irq_data);
			multi_msi = cdata->multi_msi;
			for (j = 0; j < multi_msi; j++)
				per_cpu(vector_irq, cdata->dst_cpu)[cdata->vector + j] = 0;
			kfree(cdata);
			raw_spin_unlock_irqrestore(&vector_lock, flags);
			if (multi_msi > 1)
				break;
		}
	}
}

static void sw64_irq_free_descs(unsigned int virq, unsigned int nr_irqs)
{
	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);
}

void arch_teardown_msi_irqs(struct pci_dev *dev)
{
	struct msi_desc *desc;
	int i;

	for_each_pci_msi_entry(desc, dev) {
		if (desc->irq) {
			for (i = 0; i < desc->nvec_used; i++)
				sw64_irq_free_descs(desc->irq + i, 1);
			desc->irq = 0;
		}
	}
}

static int sw64_vector_alloc_irqs(struct irq_domain *domain, unsigned int virq,
		unsigned int nr_irqs, void *arg)
{
	int err;
	struct irq_alloc_info *info = arg;
	enum irq_alloc_type msi_type;

	if (arg == NULL)
		return -ENODEV;
	msi_type = info->type;
	err = assign_irq_vector(virq, nr_irqs, domain, msi_type);
	if (err)
		goto error;
	return 0;
error:
	sw64_vector_free_irqs(domain, virq, nr_irqs);
	return err;
}

static int pci_msi_prepare(struct irq_domain *domain, struct device *dev,
		int nvec, msi_alloc_info_t *arg)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct msi_desc *desc = first_pci_msi_entry(pdev);

	memset(arg, 0, sizeof(*arg));
	arg->msi_dev = pdev;
	if (desc->msi_attrib.is_msix)
		arg->type = IRQ_ALLOC_TYPE_MSIX;
	else
		arg->type = IRQ_ALLOC_TYPE_MSI;
	return 0;
}

static struct msi_domain_ops pci_msi_domain_ops = {
	.msi_prepare    = pci_msi_prepare,
};

static struct msi_domain_info pci_msi_domain_info = {
	.flags          = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
			  MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX,
	.ops            = &pci_msi_domain_ops,
	.chip           = &pci_msi_controller,
	.handler        = handle_edge_irq,
	.handler_name   = "edge",
};

static int sw64_irq_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw)
{
	irq_set_chip_and_handler(virq, &sw64_irq_chip, handle_level_irq);
	irq_set_status_flags(virq, IRQ_LEVEL);
	return 0;
}

const struct irq_domain_ops sw64_msi_domain_ops = {
	.map    = sw64_irq_map,
	.alloc  = sw64_vector_alloc_irqs,
	.free   = sw64_vector_free_irqs,
};

int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
{
	struct irq_domain *domain;
	int err;

	if (is_guest_or_emul())
		return sw64_setup_vt_msi_irqs(pdev, nvec, type);

	domain = msi_default_domain;
	if (domain == NULL)
		return -ENOSYS;
	err = msi_domain_alloc_irqs(domain, &pdev->dev, nvec);
	return err;
}

void arch_init_msi_domain(struct irq_domain *parent)
{
	struct irq_domain *sw64_irq_domain;

	if (is_guest_or_emul())
		return;

	sw64_irq_domain = irq_domain_add_tree(NULL, &sw64_msi_domain_ops, NULL);
	BUG_ON(sw64_irq_domain == NULL);
	irq_set_default_host(sw64_irq_domain);
	msi_default_domain = pci_msi_create_irq_domain(NULL,
			&pci_msi_domain_info, sw64_irq_domain);
	if (!msi_default_domain)
		pr_warn("failed to initialize irqdomain for MSI/MSI-x.\n");
}

static void irq_move_complete(struct sw64_msi_chip_data *cdata, int cpu, int vector)
{
	if (likely(!cdata->move_in_progress))
		return;
	if (cdata->dst_cpu == cpu) {
		if (vector >= cdata->vector &&
				vector < cdata->vector + cdata->multi_msi) {
			int i;

			raw_spin_lock(&vector_lock);
			cdata->move_in_progress = false;
			for (i = 0; i < cdata->multi_msi; i++)
				per_cpu(vector_irq, cdata->prev_cpu)[cdata->prev_vector + i] = 0;
			raw_spin_unlock(&vector_lock);
		}
	}
}

void handle_pci_msi_interrupt(unsigned long type, unsigned long vector, unsigned long pci_msi1_addr)
{
	int i, irq, msi_index = 0;
	int cpu, vector_index = 0;
	unsigned long int_pci_msi[3];
	unsigned long *ptr;
	struct irq_data *irq_data;
	struct sw64_msi_chip_data *cdata;

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

	ptr = (unsigned long *)pci_msi1_addr;
	int_pci_msi[0] = *ptr;
	int_pci_msi[1] = *(ptr + 1);
	int_pci_msi[2] = *(ptr + 2);

	cpu = smp_processor_id();

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

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

			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, cpu, vector_index + msi_index);
			spin_unlock(&cdata->cdata_lock);
			handle_irq(irq);

			vector = vector & (~(1UL << msi_index));
		}

		vector = int_pci_msi[i % 3];
	}
}

MODULE_LICENSE("GPL v2");
+37 −179
Original line number Diff line number Diff line
@@ -3,7 +3,6 @@
#include <linux/module.h>
#include <linux/msi.h>
#include <linux/irqdomain.h>
#include <linux/smp.h>

#include <asm/irq_impl.h>
#include <asm/kvm_emulate.h>
@@ -30,22 +29,12 @@ static struct sw64_msi_chip_data *alloc_sw_msi_chip_data(struct irq_data *irq_da
static void irq_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
{
	struct sw64_msi_chip_data *chip_data;
	int rcid __maybe_unused;

	chip_data = irq_data_get_irq_chip_data(data->parent_data);
#if defined(CONFIG_UNCORE_XUELANG)

	msg->address_hi = MSI_ADDR_BASE_HI;
	msg->address_lo = MSI_ADDR_BASE_LO;
	msg->data = chip_data->msi_config_index;
#elif defined(CONFIG_UNCORE_JUNZHANG)
	rcid = cpu_to_rcid(chip_data->dst_cpu);
	msg->address_hi = MSI_ADDR_BASE_HI;
	msg->address_lo =
		(unsigned int)chip_data->msiaddr |
		(rcid_to_msicid(rcid) << MSI_ADDR_DEST_ID_SHIFT);
	msg->data = chip_data->vector;
	printk("%s msg->address_lo:%#x msg->data:%#x\n", __func__, msg->address_lo, msg->data);
#endif
}

bool find_free_cpu_vector(const struct cpumask *search_mask,
@@ -91,45 +80,6 @@ bool find_free_cpu_vector(const struct cpumask *search_mask,
	return true;
}

static bool find_free_cpu_vectors(const struct cpumask *search_mask, int *found_cpu, int *found_vector, unsigned int nr_irqs)
{
	int i, vector, cpu;
	bool found = false, find_once_global = false;

	cpu = cpumask_first(search_mask);
try_again:
	for (vector = 0; vector < 256; vector++) {
		for (i = 0; i < nr_irqs; i++)
			if (per_cpu(vector_irq, cpu)[vector + i])
				break;

		if (i == nr_irqs) {
			found = true;
			*found_cpu = cpu;
			*found_vector = vector;
			return found;
		}

		vector += i;
	}

	cpu = cpumask_next(cpu, search_mask);
	if (cpu < nr_cpu_ids)
		goto try_again;
	else {
		if (find_once_global) {
			printk("No global free vectors\n");
			return found;
		}
		printk("No local free vectors\n");
		search_mask = cpu_online_mask;
		cpu = cpumask_first(search_mask);
		find_once_global = true;
		goto try_again;
	}
}

#ifdef CONFIG_UNCORE_XUELANG
static unsigned long set_piu_msi_config(struct pci_controller *hose, int cpu,
		int msiconf_index, int vector)
{
@@ -147,20 +97,16 @@ static unsigned long set_piu_msi_config(struct pci_controller *hose, int cpu,

	return msi_config;
}
#endif

static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask, bool force)
{
	struct sw64_msi_chip_data *cdata;
	struct pci_controller *hose;
	struct irq_data *irqd;
	struct msi_desc *entry;
	struct cpumask searchmask;
	unsigned long flags;
	unsigned long flags, msi_config;
	int vector, cpu;
	struct pci_controller *hose __maybe_unused;
	unsigned long msi_config __maybe_unused;
	int i __maybe_unused;
	struct msi_msg msg __maybe_unused;

	/* Is this valid ? */
	if (cpumask_any_and(cpumask, cpu_online_mask) >= nr_cpu_ids)
@@ -185,37 +131,22 @@ static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
	raw_spin_lock_irqsave(&vector_lock, flags);

	cpumask_and(&searchmask, cpumask, cpu_online_mask);
	if (cdata->multi_msi > 1) {
		if (!find_free_cpu_vectors(&searchmask, &cpu,
					&vector, cdata->multi_msi)) {
			raw_spin_unlock_irqrestore(&vector_lock, flags);
			return -ENOSPC;
		}
	} else {
	if (!find_free_cpu_vector(&searchmask, &cpu, &vector)) {
		raw_spin_unlock_irqrestore(&vector_lock, flags);
		return -ENOSPC;
	}
	}

	/* update new setting */
	entry = irq_get_msi_desc(irqd->irq);
	spin_lock(&cdata->cdata_lock);
#if defined(CONFIG_UNCORE_XUELANG)
	hose = (struct pci_controller *)msi_desc_to_pci_sysdata(entry);
	spin_lock(&cdata->cdata_lock);
	per_cpu(vector_irq, cpu)[vector] = irqd->irq;
	msi_config = set_piu_msi_config(hose, cpu, cdata->msi_config_index, vector);
	cdata->msi_config = msi_config;
#elif defined(CONFIG_UNCORE_JUNZHANG)
	for (i = 0; i < cdata->multi_msi; i++)
		per_cpu(vector_irq, cpu)[vector + i] = entry->irq + i;
	BUG_ON(irq_chip_compose_msi_msg(irqd, &msg));
	__pci_write_msi_msg(entry, &msg);
#endif
	cdata->prev_vector = cdata->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);
	cpumask_copy(irq_data_get_affinity_mask(irqd), &searchmask);
@@ -240,24 +171,20 @@ static struct irq_chip pci_msi_controller = {
};

static int __assign_irq_vector(int virq, unsigned int nr_irqs,
		struct irq_domain *domain, struct pci_controller *hose,
		enum irq_alloc_type type)
		struct irq_domain *domain, struct pci_controller *hose)
{
	struct irq_data *irq_data;
	const struct cpumask *mask;
	struct cpumask searchmask;
	struct sw64_msi_chip_data *cdata;
	int node;
	int msiconf_index, node;
	int i, vector, cpu;
	unsigned long msi_config __maybe_unused;
	unsigned long msiaddr __maybe_unused;
	int msiconf_index __maybe_unused;
	int start_index __maybe_unused;
	unsigned long msi_config;
	int start_index;

	if (unlikely((nr_irqs > 1) && (!is_power_of_2(nr_irqs))))
		nr_irqs = __roundup_pow_of_two(nr_irqs);

#if defined(CONFIG_UNCORE_XUELANG)
	msiconf_index = bitmap_find_next_zero_area(hose->piu_msiconfig, 256, 0,
			nr_irqs, nr_irqs - 1);

@@ -267,9 +194,6 @@ static int __assign_irq_vector(int virq, unsigned int nr_irqs,
	}

	start_index = msiconf_index;
#elif defined(CONFIG_UNCORE_JUNZHANG)
	msiaddr = read_piu_ior0(hose->node, hose->index, MSIADDR);
#endif
	irq_data = irq_domain_get_irq_data(domain, virq);
	BUG_ON(!irq_data);
	irq_data->chip = &pci_msi_controller;
@@ -285,38 +209,6 @@ static int __assign_irq_vector(int virq, unsigned int nr_irqs,
	if (cpumask_first(&searchmask) >= nr_cpu_ids)
		cpumask_copy(&searchmask, cpu_online_mask);

	if (type == IRQ_ALLOC_TYPE_MSI && nr_irqs > 1) {
		if (!find_free_cpu_vectors(&searchmask, &cpu,
					&vector, nr_irqs))
			return -ENOSPC;

		cdata = alloc_sw_msi_chip_data(irq_data);
		if (!cdata) {
			printk("error alloc irq chip data\n");
			return -ENOMEM;
		}

		for (i = 0; i < nr_irqs; i++) {
			per_cpu(vector_irq, cpu)[vector + i] = virq + i;

			if (i) {
				irq_data = irq_domain_get_irq_data(domain, virq + i);
				irq_data->chip = &pci_msi_controller;
			}

			irq_data->chip_data = cdata;
		}

		cdata->dst_cpu = cpu;
		cdata->vector = vector;
		cdata->msiaddr = msiaddr;
		cdata->prev_cpu = cpu;
		cdata->prev_vector = vector;
		cdata->multi_msi = nr_irqs;
		cdata->move_in_progress = false;
		printk("TYPE_MSI cpu:%#x vector:%#x msiaddr:%#lx virq:%d\n",
				cpu, vector, msiaddr, virq);
	} else {
	for (i = 0; i < nr_irqs; i++) {
		if (!find_free_cpu_vector(&searchmask, &cpu, &vector))
			return -ENOSPC;
@@ -335,37 +227,30 @@ 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, cpu, msiconf_index, vector);

		cdata->dst_cpu = cpu;
		cdata->vector = vector;
		cdata->rc_index = hose->index;
		cdata->rc_node = hose->node;
#if defined(CONFIG_UNCORE_XUELANG)
			msiconf_index = start_index + i;
			msi_config = set_piu_msi_config(hose, cpu, msiconf_index, vector);
		cdata->msi_config = msi_config;
		cdata->msi_config_index = msiconf_index;
#elif defined(CONFIG_UNCORE_JUNZHANG)
			cdata->msiaddr = msiaddr;
#endif
		cdata->prev_cpu = cpu;
		cdata->prev_vector = vector;
			cdata->multi_msi = 1;
		cdata->move_in_progress = false;
	}
	}
	return 0;
}

static int assign_irq_vector(int irq, unsigned int nr_irqs,
		struct irq_domain *domain, struct pci_controller *hose,
		enum irq_alloc_type type)
		struct irq_domain *domain, struct pci_controller *hose)
{
	int err;
	unsigned long flags;

	raw_spin_lock_irqsave(&vector_lock, flags);
	err = __assign_irq_vector(irq, nr_irqs, domain, hose, type);
	err = __assign_irq_vector(irq, nr_irqs, domain, hose);
	raw_spin_unlock_irqrestore(&vector_lock, flags);
	return err;
}
@@ -373,33 +258,28 @@ static int assign_irq_vector(int irq, unsigned int nr_irqs,
static void sw64_vector_free_irqs(struct irq_domain *domain,
		unsigned int virq, unsigned int nr_irqs)
{
	int i, j;
	int i;
	struct irq_data *irq_data;
	unsigned long flags;
	struct msi_desc *entry __maybe_unused;
	struct pci_controller *hose __maybe_unused;

	for (i = 0; i < nr_irqs; i++) {
		irq_data = irq_domain_get_irq_data(domain, virq + i);
		if (irq_data && irq_data->chip_data) {
			struct sw64_msi_chip_data *cdata;
			struct msi_desc *entry;
			struct pci_controller *hose;

			raw_spin_lock_irqsave(&vector_lock, flags);
			cdata = irq_data->chip_data;
#ifdef CONFIG_UNCORE_XUELANG
			entry = irq_get_msi_desc(virq + i);
			if (entry) {
				hose = (struct pci_controller *)msi_desc_to_pci_sysdata(entry);
				clear_bit(cdata->msi_config_index, hose->piu_msiconfig);
			}
#endif
			irq_domain_reset_irq_data(irq_data);
			for (j = 0; j < cdata->multi_msi; j++)
				per_cpu(vector_irq, cdata->dst_cpu)[cdata->vector + j] = 0;
			per_cpu(vector_irq, cdata->dst_cpu)[cdata->vector] = 0;
			kfree(cdata);
			raw_spin_unlock_irqrestore(&vector_lock, flags);
			if (cdata->multi_msi > 1)
				break;
		}
	}
}
@@ -434,13 +314,11 @@ static int sw64_vector_alloc_irqs(struct irq_domain *domain, unsigned int virq,
	int err;
	struct irq_alloc_info *info = arg;
	struct pci_controller *hose;
	enum irq_alloc_type msi_type;

	if (arg == NULL)
		return -ENODEV;
	hose = info->msi_dev->sysdata;
	msi_type = info->type;
	err = assign_irq_vector(virq, nr_irqs, domain, hose, msi_type);
	err = assign_irq_vector(virq, nr_irqs, domain, hose);
	if (err)
		goto error;
	return 0;
@@ -525,39 +403,23 @@ static void irq_move_complete(struct sw64_msi_chip_data *cdata, int cpu, int vec
{
	if (likely(!cdata->move_in_progress))
		return;
#if defined(CONFIG_UNCORE_XUELANG)
	if (vector == cdata->vector && cdata->dst_cpu == cpu) {
		raw_spin_lock(&vector_lock);
		cdata->move_in_progress = 0;
		per_cpu(vector_irq, cdata->prev_cpu)[cdata->prev_vector] = 0;
		raw_spin_unlock(&vector_lock);
	}
#elif defined(UNCORE_JUNZHANG)
	if (cdata->dst_cpu == cpu) {
		if (vector >= cdata->vector &&
				vector < cdata->vector + cdata->multi_msi) {
			int i;

			raw_spin_lock(&vector_lock);
			cdata->move_in_progress = false;
			for (i = 0; i < cdata->multi_msi; i++)
				per_cpu(vector_irq, cdata->prev_cpu)[cdata->prev_vector + i] = 0;
			raw_spin_unlock(&vector_lock);
		}
	}
#endif
}

void handle_pci_msi_interrupt(unsigned long type, unsigned long vector, unsigned long pci_msi1_addr)
{
	int i, irq, msi_index = 0;
	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;
	struct irq_data *irq_data;
	struct sw64_msi_chip_data *cdata;
	int piu_index __maybe_unused;
	unsigned long value __maybe_unused = 0;

	if (is_guest_or_emul()) {
		cpu = smp_processor_id();
@@ -576,8 +438,6 @@ void handle_pci_msi_interrupt(unsigned long type, unsigned long vector, unsigned
	for (i = 0; i < 4; i++) {
		vector_index = i * 64;
		while (vector != 0) {
			int irq = 0;

			msi_index = find_next_bit(&vector, 64, msi_index);
			if (msi_index == 64) {
				msi_index = 0;
@@ -589,11 +449,9 @@ void handle_pci_msi_interrupt(unsigned long type, unsigned long vector, unsigned
			cdata = irq_data_get_irq_chip_data(irq_data);
			spin_lock(&cdata->cdata_lock);
			irq_move_complete(cdata, cpu, vector_index + msi_index);
#ifdef CONFIG_UNCORE_XUELANG
			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);
#endif
			spin_unlock(&cdata->cdata_lock);
			handle_irq(irq);