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
7 #include <linux/acpi_iort.h>
10 #include "irq-gic-common.h"
11 #include "irq-msi-lib.h"
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)
17 #define ITS_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \
19 MSI_FLAG_MULTI_PCI_MSI)
22 static int its_pci_msi_vec_count(struct pci_dev
*pdev
, void *data
)
24 int msi
, msix
, *count
= data
;
26 msi
= max(pci_msi_vec_count(pdev
), 0);
27 msix
= max(pci_msix_vec_count(pdev
), 0);
28 *count
+= max(msi
, msix
);
33 static int its_get_pci_alias(struct pci_dev
*pdev
, u16 alias
, void *data
)
35 struct pci_dev
**alias_dev
= data
;
42 static int its_pci_msi_prepare(struct irq_domain
*domain
, struct device
*dev
,
43 int nvec
, msi_alloc_info_t
*info
)
45 struct pci_dev
*pdev
, *alias_dev
;
46 struct msi_domain_info
*msi_info
;
47 int alias_count
= 0, minnvec
= 1;
52 pdev
= to_pci_dev(dev
);
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.
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
;
67 /* ITS specific DeviceID, as the core ITS ignores dev. */
68 info
->scratchpad
[0].ul
= pci_msi_domain_get_msi_rid(domain
->parent
, pdev
);
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
77 msi_info
= msi_get_domain_info(domain
);
78 if (msi_info
->hwsize
> nvec
)
79 nvec
= msi_info
->hwsize
;
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.
88 nvec
= max(nvec
, alias_count
);
89 if (!info
->scratchpad
[0].ul
)
91 nvec
= max_t(int, minnvec
, roundup_pow_of_two(nvec
));
93 msi_info
= msi_get_domain_info(domain
->parent
);
94 return msi_info
->ops
->msi_prepare(domain
->parent
, dev
, nvec
, info
);
96 #else /* CONFIG_PCI_MSI */
97 #define its_pci_msi_prepare NULL
98 #endif /* !CONFIG_PCI_MSI */
100 static int of_pmsi_get_dev_id(struct irq_domain
*domain
, struct device
*dev
,
105 /* Suck the DeviceID out of the msi-parent property */
107 struct of_phandle_args args
;
109 ret
= of_parse_phandle_with_args(dev
->of_node
,
110 "msi-parent", "#msi-cells",
112 if (args
.np
== irq_domain_get_of_node(domain
)) {
113 if (WARN_ON(args
.args_count
!= 1))
115 *dev_id
= args
.args
[0];
124 int __weak
iort_pmsi_get_dev_id(struct device
*dev
, u32
*dev_id
)
129 static int its_pmsi_prepare(struct irq_domain
*domain
, struct device
*dev
,
130 int nvec
, msi_alloc_info_t
*info
)
132 struct msi_domain_info
*msi_info
;
137 ret
= of_pmsi_get_dev_id(domain
->parent
, dev
, &dev_id
);
139 ret
= iort_pmsi_get_dev_id(dev
, &dev_id
);
143 /* ITS specific DeviceID, as the core ITS ignores dev. */
144 info
->scratchpad
[0].ul
= dev_id
;
147 * @domain->msi_domain_info->hwsize contains the size of the device
148 * domain, but vector allocation happens one by one.
150 msi_info
= msi_get_domain_info(domain
);
151 if (msi_info
->hwsize
> nvec
)
152 nvec
= msi_info
->hwsize
;
154 /* Allocate at least 32 MSIs, and always as a power of 2 */
155 nvec
= max_t(int, 32, roundup_pow_of_two(nvec
));
157 msi_info
= msi_get_domain_info(domain
->parent
);
158 return msi_info
->ops
->msi_prepare(domain
->parent
,
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
)
165 if (!msi_lib_init_dev_msi_info(dev
, domain
, real_parent
, info
))
168 switch(info
->bus_token
) {
169 case DOMAIN_BUS_PCI_DEVICE_MSI
:
170 case DOMAIN_BUS_PCI_DEVICE_MSIX
:
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.
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
184 info
->ops
->msi_prepare
= its_pci_msi_prepare
;
186 case DOMAIN_BUS_DEVICE_MSI
:
187 case DOMAIN_BUS_WIRED_TO_MSI
:
189 * FIXME: See the above PCI prepare comment. The domain
190 * size is also known at domain creation time.
192 info
->ops
->msi_prepare
= its_pmsi_prepare
;
195 /* Confused. How did the lib return true? */
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
,
209 .init_dev_msi_info
= its_init_dev_msi_info
,