xref: /linux/drivers/irqchip/irq-gic-v3-its-msi-parent.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (C) 2013-2015 ARM Limited, All Rights Reserved.
3 // Author: Marc Zyngier <marc.zyngier@arm.com>
4 // Copyright (C) 2022 Linutronix GmbH
5 // Copyright (C) 2022 Intel
6 
7 #include <linux/acpi_iort.h>
8 #include <linux/pci.h>
9 
10 #include "irq-gic-common.h"
11 #include "irq-msi-lib.h"
12 
13 #define ITS_MSI_FLAGS_REQUIRED  (MSI_FLAG_USE_DEF_DOM_OPS |	\
14 				 MSI_FLAG_USE_DEF_CHIP_OPS |	\
15 				 MSI_FLAG_PCI_MSI_MASK_PARENT)
16 
17 #define ITS_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK |	\
18 				 MSI_FLAG_PCI_MSIX      |	\
19 				 MSI_FLAG_MULTI_PCI_MSI)
20 
21 #ifdef CONFIG_PCI_MSI
its_pci_msi_vec_count(struct pci_dev * pdev,void * data)22 static int its_pci_msi_vec_count(struct pci_dev *pdev, void *data)
23 {
24 	int msi, msix, *count = data;
25 
26 	msi = max(pci_msi_vec_count(pdev), 0);
27 	msix = max(pci_msix_vec_count(pdev), 0);
28 	*count += max(msi, msix);
29 
30 	return 0;
31 }
32 
its_get_pci_alias(struct pci_dev * pdev,u16 alias,void * data)33 static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data)
34 {
35 	struct pci_dev **alias_dev = data;
36 
37 	*alias_dev = pdev;
38 
39 	return 0;
40 }
41 
its_pci_msi_prepare(struct irq_domain * domain,struct device * dev,int nvec,msi_alloc_info_t * info)42 static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev,
43 			       int nvec, msi_alloc_info_t *info)
44 {
45 	struct pci_dev *pdev, *alias_dev;
46 	struct msi_domain_info *msi_info;
47 	int alias_count = 0, minnvec = 1;
48 
49 	if (!dev_is_pci(dev))
50 		return -EINVAL;
51 
52 	pdev = to_pci_dev(dev);
53 	/*
54 	 * If pdev is downstream of any aliasing bridges, take an upper
55 	 * bound of how many other vectors could map to the same DevID.
56 	 * Also tell the ITS that the signalling will come from a proxy
57 	 * device, and that special allocation rules apply.
58 	 */
59 	pci_for_each_dma_alias(pdev, its_get_pci_alias, &alias_dev);
60 	if (alias_dev != pdev) {
61 		if (alias_dev->subordinate)
62 			pci_walk_bus(alias_dev->subordinate,
63 				     its_pci_msi_vec_count, &alias_count);
64 		info->flags |= MSI_ALLOC_FLAGS_PROXY_DEVICE;
65 	}
66 
67 	/* ITS specific DeviceID, as the core ITS ignores dev. */
68 	info->scratchpad[0].ul = pci_msi_domain_get_msi_rid(domain->parent, pdev);
69 
70 	/*
71 	 * @domain->msi_domain_info->hwsize contains the size of the
72 	 * MSI[-X] domain, but vector allocation happens one by one. This
73 	 * needs some thought when MSI comes into play as the size of MSI
74 	 * might be unknown at domain creation time and therefore set to
75 	 * MSI_MAX_INDEX.
76 	 */
77 	msi_info = msi_get_domain_info(domain);
78 	if (msi_info->hwsize > nvec)
79 		nvec = msi_info->hwsize;
80 
81 	/*
82 	 * Always allocate a power of 2, and special case device 0 for
83 	 * broken systems where the DevID is not wired (and all devices
84 	 * appear as DevID 0). For that reason, we generously allocate a
85 	 * minimum of 32 MSIs for DevID 0. If you want more because all
86 	 * your devices are aliasing to DevID 0, consider fixing your HW.
87 	 */
88 	nvec = max(nvec, alias_count);
89 	if (!info->scratchpad[0].ul)
90 		minnvec = 32;
91 	nvec = max_t(int, minnvec, roundup_pow_of_two(nvec));
92 
93 	msi_info = msi_get_domain_info(domain->parent);
94 	return msi_info->ops->msi_prepare(domain->parent, dev, nvec, info);
95 }
96 #else /* CONFIG_PCI_MSI */
97 #define its_pci_msi_prepare	NULL
98 #endif /* !CONFIG_PCI_MSI */
99 
of_pmsi_get_dev_id(struct irq_domain * domain,struct device * dev,u32 * dev_id)100 static int of_pmsi_get_dev_id(struct irq_domain *domain, struct device *dev,
101 				  u32 *dev_id)
102 {
103 	int ret, index = 0;
104 
105 	/* Suck the DeviceID out of the msi-parent property */
106 	do {
107 		struct of_phandle_args args;
108 
109 		ret = of_parse_phandle_with_args(dev->of_node,
110 						 "msi-parent", "#msi-cells",
111 						 index, &args);
112 		if (args.np == irq_domain_get_of_node(domain)) {
113 			if (WARN_ON(args.args_count != 1))
114 				return -EINVAL;
115 			*dev_id = args.args[0];
116 			break;
117 		}
118 		index++;
119 	} while (!ret);
120 
121 	return ret;
122 }
123 
iort_pmsi_get_dev_id(struct device * dev,u32 * dev_id)124 int __weak iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id)
125 {
126 	return -1;
127 }
128 
its_pmsi_prepare(struct irq_domain * domain,struct device * dev,int nvec,msi_alloc_info_t * info)129 static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev,
130 			    int nvec, msi_alloc_info_t *info)
131 {
132 	struct msi_domain_info *msi_info;
133 	u32 dev_id;
134 	int ret;
135 
136 	if (dev->of_node)
137 		ret = of_pmsi_get_dev_id(domain->parent, dev, &dev_id);
138 	else
139 		ret = iort_pmsi_get_dev_id(dev, &dev_id);
140 	if (ret)
141 		return ret;
142 
143 	/* ITS specific DeviceID, as the core ITS ignores dev. */
144 	info->scratchpad[0].ul = dev_id;
145 
146 	/*
147 	 * @domain->msi_domain_info->hwsize contains the size of the device
148 	 * domain, but vector allocation happens one by one.
149 	 */
150 	msi_info = msi_get_domain_info(domain);
151 	if (msi_info->hwsize > nvec)
152 		nvec = msi_info->hwsize;
153 
154 	/* Allocate at least 32 MSIs, and always as a power of 2 */
155 	nvec = max_t(int, 32, roundup_pow_of_two(nvec));
156 
157 	msi_info = msi_get_domain_info(domain->parent);
158 	return msi_info->ops->msi_prepare(domain->parent,
159 					  dev, nvec, info);
160 }
161 
its_init_dev_msi_info(struct device * dev,struct irq_domain * domain,struct irq_domain * real_parent,struct msi_domain_info * info)162 static bool its_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
163 				  struct irq_domain *real_parent, struct msi_domain_info *info)
164 {
165 	if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info))
166 		return false;
167 
168 	switch(info->bus_token) {
169 	case DOMAIN_BUS_PCI_DEVICE_MSI:
170 	case DOMAIN_BUS_PCI_DEVICE_MSIX:
171 		/*
172 		 * FIXME: This probably should be done after a (not yet
173 		 * existing) post domain creation callback once to make
174 		 * support for dynamic post-enable MSI-X allocations
175 		 * work without having to reevaluate the domain size
176 		 * over and over. It is known already at allocation
177 		 * time via info->hwsize.
178 		 *
179 		 * That should work perfectly fine for MSI/MSI-X but needs
180 		 * some thoughts for purely software managed MSI domains
181 		 * where the index space is only limited artificially via
182 		 * %MSI_MAX_INDEX.
183 		 */
184 		info->ops->msi_prepare = its_pci_msi_prepare;
185 		break;
186 	case DOMAIN_BUS_DEVICE_MSI:
187 	case DOMAIN_BUS_WIRED_TO_MSI:
188 		/*
189 		 * FIXME: See the above PCI prepare comment. The domain
190 		 * size is also known at domain creation time.
191 		 */
192 		info->ops->msi_prepare = its_pmsi_prepare;
193 		break;
194 	default:
195 		/* Confused. How did the lib return true? */
196 		WARN_ON_ONCE(1);
197 		return false;
198 	}
199 
200 	return true;
201 }
202 
203 const struct msi_parent_ops gic_v3_its_msi_parent_ops = {
204 	.supported_flags	= ITS_MSI_FLAGS_SUPPORTED,
205 	.required_flags		= ITS_MSI_FLAGS_REQUIRED,
206 	.bus_select_token	= DOMAIN_BUS_NEXUS,
207 	.bus_select_mask	= MATCH_PCI_MSI | MATCH_PLATFORM_MSI,
208 	.prefix			= "ITS-",
209 	.init_dev_msi_info	= its_init_dev_msi_info,
210 };
211