diff options
Diffstat (limited to 'drivers/irqchip/irq-gic-v3-its-msi-parent.c')
| -rw-r--r-- | drivers/irqchip/irq-gic-v3-its-msi-parent.c | 210 |
1 files changed, 0 insertions, 210 deletions
diff --git a/drivers/irqchip/irq-gic-v3-its-msi-parent.c b/drivers/irqchip/irq-gic-v3-its-msi-parent.c deleted file mode 100644 index e150365fbe89..000000000000 --- a/drivers/irqchip/irq-gic-v3-its-msi-parent.c +++ /dev/null @@ -1,210 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// Copyright (C) 2013-2015 ARM Limited, All Rights Reserved. -// Author: Marc Zyngier <marc.zyngier@arm.com> -// Copyright (C) 2022 Linutronix GmbH -// Copyright (C) 2022 Intel - -#include <linux/acpi_iort.h> -#include <linux/pci.h> - -#include "irq-gic-common.h" -#include "irq-msi-lib.h" - -#define ITS_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ - MSI_FLAG_USE_DEF_CHIP_OPS | \ - MSI_FLAG_PCI_MSI_MASK_PARENT) - -#define ITS_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ - MSI_FLAG_PCI_MSIX | \ - MSI_FLAG_MULTI_PCI_MSI) - -#ifdef CONFIG_PCI_MSI -static int its_pci_msi_vec_count(struct pci_dev *pdev, void *data) -{ - int msi, msix, *count = data; - - msi = max(pci_msi_vec_count(pdev), 0); - msix = max(pci_msix_vec_count(pdev), 0); - *count += max(msi, msix); - - return 0; -} - -static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data) -{ - struct pci_dev **alias_dev = data; - - *alias_dev = pdev; - - return 0; -} - -static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev, - int nvec, msi_alloc_info_t *info) -{ - struct pci_dev *pdev, *alias_dev; - struct msi_domain_info *msi_info; - int alias_count = 0, minnvec = 1; - - if (!dev_is_pci(dev)) - return -EINVAL; - - pdev = to_pci_dev(dev); - /* - * If pdev is downstream of any aliasing bridges, take an upper - * bound of how many other vectors could map to the same DevID. - * Also tell the ITS that the signalling will come from a proxy - * device, and that special allocation rules apply. - */ - pci_for_each_dma_alias(pdev, its_get_pci_alias, &alias_dev); - if (alias_dev != pdev) { - if (alias_dev->subordinate) - pci_walk_bus(alias_dev->subordinate, - its_pci_msi_vec_count, &alias_count); - info->flags |= MSI_ALLOC_FLAGS_PROXY_DEVICE; - } - - /* ITS specific DeviceID, as the core ITS ignores dev. */ - info->scratchpad[0].ul = pci_msi_domain_get_msi_rid(domain->parent, pdev); - - /* - * @domain->msi_domain_info->hwsize contains the size of the - * MSI[-X] domain, but vector allocation happens one by one. This - * needs some thought when MSI comes into play as the size of MSI - * might be unknown at domain creation time and therefore set to - * MSI_MAX_INDEX. - */ - msi_info = msi_get_domain_info(domain); - if (msi_info->hwsize > nvec) - nvec = msi_info->hwsize; - - /* - * Always allocate a power of 2, and special case device 0 for - * broken systems where the DevID is not wired (and all devices - * appear as DevID 0). For that reason, we generously allocate a - * minimum of 32 MSIs for DevID 0. If you want more because all - * your devices are aliasing to DevID 0, consider fixing your HW. - */ - nvec = max(nvec, alias_count); - if (!info->scratchpad[0].ul) - minnvec = 32; - nvec = max_t(int, minnvec, roundup_pow_of_two(nvec)); - - msi_info = msi_get_domain_info(domain->parent); - return msi_info->ops->msi_prepare(domain->parent, dev, nvec, info); -} -#else /* CONFIG_PCI_MSI */ -#define its_pci_msi_prepare NULL -#endif /* !CONFIG_PCI_MSI */ - -static int of_pmsi_get_dev_id(struct irq_domain *domain, struct device *dev, - u32 *dev_id) -{ - int ret, index = 0; - - /* Suck the DeviceID out of the msi-parent property */ - do { - struct of_phandle_args args; - - ret = of_parse_phandle_with_args(dev->of_node, - "msi-parent", "#msi-cells", - index, &args); - if (args.np == irq_domain_get_of_node(domain)) { - if (WARN_ON(args.args_count != 1)) - return -EINVAL; - *dev_id = args.args[0]; - break; - } - index++; - } while (!ret); - - return ret; -} - -int __weak iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id) -{ - return -1; -} - -static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev, - int nvec, msi_alloc_info_t *info) -{ - struct msi_domain_info *msi_info; - u32 dev_id; - int ret; - - if (dev->of_node) - ret = of_pmsi_get_dev_id(domain->parent, dev, &dev_id); - else - ret = iort_pmsi_get_dev_id(dev, &dev_id); - if (ret) - return ret; - - /* ITS specific DeviceID, as the core ITS ignores dev. */ - info->scratchpad[0].ul = dev_id; - - /* - * @domain->msi_domain_info->hwsize contains the size of the device - * domain, but vector allocation happens one by one. - */ - msi_info = msi_get_domain_info(domain); - if (msi_info->hwsize > nvec) - nvec = msi_info->hwsize; - - /* Allocate at least 32 MSIs, and always as a power of 2 */ - nvec = max_t(int, 32, roundup_pow_of_two(nvec)); - - msi_info = msi_get_domain_info(domain->parent); - return msi_info->ops->msi_prepare(domain->parent, - dev, nvec, info); -} - -static bool its_init_dev_msi_info(struct device *dev, struct irq_domain *domain, - struct irq_domain *real_parent, struct msi_domain_info *info) -{ - if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info)) - return false; - - switch(info->bus_token) { - case DOMAIN_BUS_PCI_DEVICE_MSI: - case DOMAIN_BUS_PCI_DEVICE_MSIX: - /* - * FIXME: This probably should be done after a (not yet - * existing) post domain creation callback once to make - * support for dynamic post-enable MSI-X allocations - * work without having to reevaluate the domain size - * over and over. It is known already at allocation - * time via info->hwsize. - * - * That should work perfectly fine for MSI/MSI-X but needs - * some thoughts for purely software managed MSI domains - * where the index space is only limited artificially via - * %MSI_MAX_INDEX. - */ - info->ops->msi_prepare = its_pci_msi_prepare; - break; - case DOMAIN_BUS_DEVICE_MSI: - case DOMAIN_BUS_WIRED_TO_MSI: - /* - * FIXME: See the above PCI prepare comment. The domain - * size is also known at domain creation time. - */ - info->ops->msi_prepare = its_pmsi_prepare; - break; - default: - /* Confused. How did the lib return true? */ - WARN_ON_ONCE(1); - return false; - } - - return true; -} - -const struct msi_parent_ops gic_v3_its_msi_parent_ops = { - .supported_flags = ITS_MSI_FLAGS_SUPPORTED, - .required_flags = ITS_MSI_FLAGS_REQUIRED, - .bus_select_token = DOMAIN_BUS_NEXUS, - .bus_select_mask = MATCH_PCI_MSI | MATCH_PLATFORM_MSI, - .prefix = "ITS-", - .init_dev_msi_info = its_init_dev_msi_info, -}; |
