irqchip/gic-v3-its: Add virt platform devices MSI support
ANBZ: #9398 commit 4cc685056a0056a0f8bdcfe901000dd4731efc6b openEuler. virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8UROS 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: wanghaibin <wanghaibin.wang@huawei.com> Signed-off-by: Zenghui Yu <yuzenghui@huawei.com> Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com> Signed-off-by: Dongxu Sun <sundongxu3@huawei.com> Signed-off-by: Guanghui Feng <guanghuifeng@linux.alibaba.com> Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com> Link: https://gitee.com/anolis/cloud-kernel/pulls/3463
This commit is contained in:
parent
2040f15d5b
commit
557e32b259
|
@ -10,6 +10,20 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
|
||||
#ifdef CONFIG_VIRT_PLAT_DEV
|
||||
static struct irq_domain *vp_irq_domain;
|
||||
extern bool rsv_devid_pool_cap;
|
||||
|
||||
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);
|
||||
#endif
|
||||
|
||||
static struct irq_chip its_pmsi_irq_chip = {
|
||||
.name = "ITS-pMSI",
|
||||
};
|
||||
|
@ -52,6 +66,19 @@ static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev,
|
|||
|
||||
msi_info = msi_get_domain_info(domain->parent);
|
||||
|
||||
#ifdef CONFIG_VIRT_PLAT_DEV
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dev->of_node)
|
||||
ret = of_pmsi_get_dev_id(domain, dev, &dev_id);
|
||||
else
|
||||
|
@ -62,6 +89,9 @@ 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;
|
||||
|
||||
#ifdef CONFIG_VIRT_PLAT_DEV
|
||||
vdev_pmsi_prepare:
|
||||
#endif
|
||||
/* 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,
|
||||
|
@ -86,7 +116,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 +124,22 @@ 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);
|
||||
|
||||
#ifdef CONFIG_VIRT_PLAT_DEV
|
||||
/* Should we take other irqdomains into account? */
|
||||
if (!vp_irq_domain)
|
||||
vp_irq_domain = pmsi_irqdomain;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,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)
|
||||
|
|
|
@ -550,6 +550,10 @@ 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);
|
||||
|
||||
#ifdef CONFIG_VIRT_PLAT_DEV
|
||||
struct irq_domain *vp_get_irq_domain(void);
|
||||
#endif
|
||||
#else
|
||||
static inline struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue