Skip to content

Commit 7135b35

Browse files
author
Marc Zyngier
committed
Merge branch irq/irqdomain-locking into irq/irqchip-next
* irq/irqdomain-locking: : . : irqdomain locking overhaul courtesy of Johan Hovold. : : From the cover letter: : : "Parallel probing (e.g. due to asynchronous probing) of devices that : share interrupts can currently result in two mappings for the same : hardware interrupt to be created. : : This series fixes this mapping race and reworks the irqdomain locking so : that in the end the global irq_domain_mutex is only used for managing : the likewise global irq_domain_list, while domain operations (e.g. IRQ : allocations) use per-domain (hierarchy) locking." : . irqdomain: Switch to per-domain locking irqchip/mvebu-odmi: Use irq_domain_create_hierarchy() irqchip/loongson-pch-msi: Use irq_domain_create_hierarchy() irqchip/gic-v3-mbi: Use irq_domain_create_hierarchy() irqchip/gic-v3-its: Use irq_domain_create_hierarchy() irqchip/gic-v2m: Use irq_domain_create_hierarchy() irqchip/alpine-msi: Use irq_domain_add_hierarchy() x86/uv: Use irq_domain_create_hierarchy() x86/ioapic: Use irq_domain_create_hierarchy() irqdomain: Clean up irq_domain_push/pop_irq() irqdomain: Drop leftover brackets irqdomain: Drop dead domain-name assignment irqdomain: Drop revmap mutex irqdomain: Fix domain registration race irqdomain: Fix mapping-creation race irqdomain: Refactor __irq_domain_alloc_irqs() irqdomain: Look for existing mapping only once irqdomain: Drop bogus fwspec-mapping error handling irqdomain: Fix disassociation race irqdomain: Fix association race Signed-off-by: Marc Zyngier <maz@kernel.org>
2 parents df2d85d + 9dbb8e3 commit 7135b35

10 files changed

Lines changed: 279 additions & 202 deletions

File tree

arch/x86/kernel/apic/io_apic.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2364,18 +2364,15 @@ static int mp_irqdomain_create(int ioapic)
23642364
return -ENODEV;
23652365
}
23662366

2367-
ip->irqdomain = irq_domain_create_linear(fn, hwirqs, cfg->ops,
2368-
(void *)(long)ioapic);
2369-
2367+
ip->irqdomain = irq_domain_create_hierarchy(parent, 0, hwirqs, fn, cfg->ops,
2368+
(void *)(long)ioapic);
23702369
if (!ip->irqdomain) {
23712370
/* Release fw handle if it was allocated above */
23722371
if (!cfg->dev)
23732372
irq_domain_free_fwnode(fn);
23742373
return -ENOMEM;
23752374
}
23762375

2377-
ip->irqdomain->parent = parent;
2378-
23792376
if (cfg->type == IOAPIC_DOMAIN_LEGACY ||
23802377
cfg->type == IOAPIC_DOMAIN_STRICT)
23812378
ioapic_dynirq_base = max(ioapic_dynirq_base,

arch/x86/platform/uv/uv_irq.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,9 @@ static struct irq_domain *uv_get_irq_domain(void)
166166
if (!fn)
167167
goto out;
168168

169-
uv_domain = irq_domain_create_tree(fn, &uv_domain_ops, NULL);
170-
if (uv_domain)
171-
uv_domain->parent = x86_vector_domain;
172-
else
169+
uv_domain = irq_domain_create_hierarchy(x86_vector_domain, 0, 0, fn,
170+
&uv_domain_ops, NULL);
171+
if (!uv_domain)
173172
irq_domain_free_fwnode(fn);
174173
out:
175174
mutex_unlock(&uv_lock);

drivers/irqchip/irq-alpine-msi.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,16 +205,14 @@ static int alpine_msix_init_domains(struct alpine_msix_data *priv,
205205
return -ENXIO;
206206
}
207207

208-
middle_domain = irq_domain_add_tree(NULL,
209-
&alpine_msix_middle_domain_ops,
210-
priv);
208+
middle_domain = irq_domain_add_hierarchy(gic_domain, 0, 0, NULL,
209+
&alpine_msix_middle_domain_ops,
210+
priv);
211211
if (!middle_domain) {
212212
pr_err("Failed to create the MSIX middle domain\n");
213213
return -ENOMEM;
214214
}
215215

216-
middle_domain->parent = gic_domain;
217-
218216
msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node),
219217
&alpine_msix_domain_info,
220218
middle_domain);

drivers/irqchip/irq-gic-v2m.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,15 +287,14 @@ static __init int gicv2m_allocate_domains(struct irq_domain *parent)
287287
if (!v2m)
288288
return 0;
289289

290-
inner_domain = irq_domain_create_tree(v2m->fwnode,
291-
&gicv2m_domain_ops, v2m);
290+
inner_domain = irq_domain_create_hierarchy(parent, 0, 0, v2m->fwnode,
291+
&gicv2m_domain_ops, v2m);
292292
if (!inner_domain) {
293293
pr_err("Failed to create GICv2m domain\n");
294294
return -ENOMEM;
295295
}
296296

297297
irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_NEXUS);
298-
inner_domain->parent = parent;
299298
pci_domain = pci_msi_create_irq_domain(v2m->fwnode,
300299
&gicv2m_msi_domain_info,
301300
inner_domain);

drivers/irqchip/irq-gic-v3-its.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4909,18 +4909,19 @@ static int its_init_domain(struct fwnode_handle *handle, struct its_node *its)
49094909
if (!info)
49104910
return -ENOMEM;
49114911

4912-
inner_domain = irq_domain_create_tree(handle, &its_domain_ops, its);
4912+
info->ops = &its_msi_domain_ops;
4913+
info->data = its;
4914+
4915+
inner_domain = irq_domain_create_hierarchy(its_parent,
4916+
its->msi_domain_flags, 0,
4917+
handle, &its_domain_ops,
4918+
info);
49134919
if (!inner_domain) {
49144920
kfree(info);
49154921
return -ENOMEM;
49164922
}
49174923

4918-
inner_domain->parent = its_parent;
49194924
irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_NEXUS);
4920-
inner_domain->flags |= its->msi_domain_flags;
4921-
info->ops = &its_msi_domain_ops;
4922-
info->data = its;
4923-
inner_domain->host_data = info;
49244925

49254926
return 0;
49264927
}

drivers/irqchip/irq-gic-v3-mbi.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,13 +233,12 @@ static int mbi_allocate_domains(struct irq_domain *parent)
233233
struct irq_domain *nexus_domain, *pci_domain, *plat_domain;
234234
int err;
235235

236-
nexus_domain = irq_domain_create_tree(parent->fwnode,
237-
&mbi_domain_ops, NULL);
236+
nexus_domain = irq_domain_create_hierarchy(parent, 0, 0, parent->fwnode,
237+
&mbi_domain_ops, NULL);
238238
if (!nexus_domain)
239239
return -ENOMEM;
240240

241241
irq_domain_update_bus_token(nexus_domain, DOMAIN_BUS_NEXUS);
242-
nexus_domain->parent = parent;
243242

244243
err = mbi_allocate_pci_domain(nexus_domain, &pci_domain);
245244

drivers/irqchip/irq-loongson-pch-msi.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,16 +163,15 @@ static int pch_msi_init_domains(struct pch_msi_data *priv,
163163
{
164164
struct irq_domain *middle_domain, *msi_domain;
165165

166-
middle_domain = irq_domain_create_linear(domain_handle,
167-
priv->num_irqs,
168-
&pch_msi_middle_domain_ops,
169-
priv);
166+
middle_domain = irq_domain_create_hierarchy(parent, 0, priv->num_irqs,
167+
domain_handle,
168+
&pch_msi_middle_domain_ops,
169+
priv);
170170
if (!middle_domain) {
171171
pr_err("Failed to create the MSI middle domain\n");
172172
return -ENOMEM;
173173
}
174174

175-
middle_domain->parent = parent;
176175
irq_domain_update_bus_token(middle_domain, DOMAIN_BUS_NEXUS);
177176

178177
msi_domain = pci_msi_create_irq_domain(domain_handle,

drivers/irqchip/irq-mvebu-odmi.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ static struct msi_domain_info odmi_msi_domain_info = {
161161
static int __init mvebu_odmi_init(struct device_node *node,
162162
struct device_node *parent)
163163
{
164-
struct irq_domain *inner_domain, *plat_domain;
164+
struct irq_domain *parent_domain, *inner_domain, *plat_domain;
165165
int ret, i;
166166

167167
if (of_property_read_u32(node, "marvell,odmi-frames", &odmis_count))
@@ -197,16 +197,17 @@ static int __init mvebu_odmi_init(struct device_node *node,
197197
}
198198
}
199199

200-
inner_domain = irq_domain_create_linear(of_node_to_fwnode(node),
201-
odmis_count * NODMIS_PER_FRAME,
202-
&odmi_domain_ops, NULL);
200+
parent_domain = irq_find_host(parent);
201+
202+
inner_domain = irq_domain_create_hierarchy(parent_domain, 0,
203+
odmis_count * NODMIS_PER_FRAME,
204+
of_node_to_fwnode(node),
205+
&odmi_domain_ops, NULL);
203206
if (!inner_domain) {
204207
ret = -ENOMEM;
205208
goto err_unmap;
206209
}
207210

208-
inner_domain->parent = irq_find_host(parent);
209-
210211
plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(node),
211212
&odmi_msi_domain_info,
212213
inner_domain);

include/linux/irqdomain.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ struct irq_domain_chip_generic;
125125
* core code.
126126
* @flags: Per irq_domain flags
127127
* @mapcount: The number of mapped interrupts
128+
* @mutex: Domain lock, hierarchical domains use root domain's lock
129+
* @root: Pointer to root domain, or containing structure if non-hierarchical
128130
*
129131
* Optional elements:
130132
* @fwnode: Pointer to firmware node associated with the irq_domain. Pretty easy
@@ -143,7 +145,6 @@ struct irq_domain_chip_generic;
143145
* Revmap data, used internally by the irq domain code:
144146
* @revmap_size: Size of the linear map table @revmap[]
145147
* @revmap_tree: Radix map tree for hwirqs that don't fit in the linear map
146-
* @revmap_mutex: Lock for the revmap
147148
* @revmap: Linear table of irq_data pointers
148149
*/
149150
struct irq_domain {
@@ -153,6 +154,8 @@ struct irq_domain {
153154
void *host_data;
154155
unsigned int flags;
155156
unsigned int mapcount;
157+
struct mutex mutex;
158+
struct irq_domain *root;
156159

157160
/* Optional data */
158161
struct fwnode_handle *fwnode;
@@ -171,7 +174,6 @@ struct irq_domain {
171174
irq_hw_number_t hwirq_max;
172175
unsigned int revmap_size;
173176
struct radix_tree_root revmap_tree;
174-
struct mutex revmap_mutex;
175177
struct irq_data __rcu *revmap[];
176178
};
177179

0 commit comments

Comments
 (0)