Commit db0a347c authored by wanghaibin's avatar wanghaibin Committed by Dongxu Sun
Browse files

irqchip/gic-v3-its: Add virt platform devices MSI support

virt inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8K8HP


CVE: NA

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

Implement the virtual platform device MSI with the GICv3 ITS.
Compared with phycial platform device msi, msi_prepare implementation
need consider the devid alloc.

Signed-off-by: default avatarwanghaibin <wanghaibin.wang@huawei.com>
Signed-off-by: default avatarZenghui Yu <yuzenghui@huawei.com>
Signed-off-by: default avatarKunkun Jiang <jiangkunkun@huawei.com>
Signed-off-by: default avatarDongxu Sun <sundongxu3@huawei.com>
parent cba99807
Loading
Loading
Loading
Loading
+36 −3
Original line number Diff line number Diff line
@@ -10,6 +10,17 @@
#include <linux/of.h>
#include <linux/of_irq.h>

static struct irq_domain *vp_irq_domain;

struct irq_domain *vp_get_irq_domain(void)
{
	if (!vp_irq_domain)
		pr_err("virtual platform irqdomain hasn't be initialized!\n");

	return vp_irq_domain;
}
EXPORT_SYMBOL_GPL(vp_get_irq_domain);

static struct irq_chip its_pmsi_irq_chip = {
	.name			= "ITS-pMSI",
};
@@ -43,6 +54,8 @@ int __weak iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id)
	return -1;
}

extern bool rsv_devid_pool_cap;

static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev,
			    int nvec, msi_alloc_info_t *info)
{
@@ -52,6 +65,17 @@ static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev,

	msi_info = msi_get_domain_info(domain->parent);

	if (rsv_devid_pool_cap && !dev->of_node && !dev->fwnode) {
		WARN_ON_ONCE(domain != vp_irq_domain);
		/*
		 * virtual platform device doesn't have a DeviceID which
		 * will be allocated with core ITS's help.
		 */
		info->scratchpad[0].ul = -1;

		goto vdev_pmsi_prepare;
	}

	if (dev->of_node)
		ret = of_pmsi_get_dev_id(domain, dev, &dev_id);
	else
@@ -62,8 +86,10 @@ static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev,
	/* ITS specific DeviceID, as the core ITS ignores dev. */
	info->scratchpad[0].ul = dev_id;

vdev_pmsi_prepare:
	/* Allocate at least 32 MSIs, and always as a power of 2 */
	nvec = max_t(int, 32, roundup_pow_of_two(nvec));

	return msi_info->ops->msi_prepare(domain->parent,
					  dev, nvec, info);
}
@@ -86,7 +112,7 @@ static const struct of_device_id its_device_id[] = {
static int __init its_pmsi_init_one(struct fwnode_handle *fwnode,
				const char *name)
{
	struct irq_domain *parent;
	struct irq_domain *pmsi_irqdomain, *parent;

	parent = irq_find_matching_fwnode(fwnode, DOMAIN_BUS_NEXUS);
	if (!parent || !msi_get_domain_info(parent)) {
@@ -94,13 +120,20 @@ static int __init its_pmsi_init_one(struct fwnode_handle *fwnode,
		return -ENXIO;
	}

	if (!platform_msi_create_irq_domain(fwnode, &its_pmsi_domain_info,
					    parent)) {
	pmsi_irqdomain = platform_msi_create_irq_domain(fwnode,
							&its_pmsi_domain_info,
							parent);
	if (!pmsi_irqdomain) {
		pr_err("%s: unable to create platform domain\n", name);
		return -ENXIO;
	}

	pr_info("Platform MSI: %s domain created\n", name);

	/* Should we take other irqdomains into account? */
	if (!vp_irq_domain)
		vp_irq_domain = pmsi_irqdomain;

	return 0;
}

+1 −1
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@ static LIST_HEAD(rsv_devid_pools);
static DEFINE_RAW_SPINLOCK(rsv_devid_pools_lock);

/* Do we have usable rsv_devid_pool? Initialized to be true. */
static bool rsv_devid_pool_cap = true;
bool rsv_devid_pool_cap = true;
static u8 rsv_buses_start, rsv_buses_count;

static int __init rsv_buses_start_cfg(char *buf)
+2 −0
Original line number Diff line number Diff line
@@ -431,6 +431,8 @@ int pci_msi_domain_check_cap(struct irq_domain *domain,
u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev);
struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev);
bool pci_dev_has_special_msi_domain(struct pci_dev *pdev);

struct irq_domain *vp_get_irq_domain(void);
#else
static inline struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev)
{