Skip to content

Commit 5c99e02

Browse files
committed
genirq/msi: Use lock guards for MSI descriptor locking
Provide a lock guard for MSI descriptor locking and update the core code accordingly. No functional change intended. Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Jonathan Cameron <[email protected]> Link: https://lore.kernel.org/all/[email protected]
1 parent 08549ff commit 5c99e02

File tree

3 files changed

+45
-69
lines changed

3 files changed

+45
-69
lines changed

include/linux/irqdomain.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,8 @@ static inline struct fwnode_handle *irq_domain_alloc_fwnode(phys_addr_t *pa)
281281

282282
void irq_domain_free_fwnode(struct fwnode_handle *fwnode);
283283

284+
DEFINE_FREE(irq_domain_free_fwnode, struct fwnode_handle *, if (_T) irq_domain_free_fwnode(_T))
285+
284286
struct irq_domain_chip_generic_info;
285287

286288
/**

include/linux/msi.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,9 @@ int msi_setup_device_data(struct device *dev);
227227
void msi_lock_descs(struct device *dev);
228228
void msi_unlock_descs(struct device *dev);
229229

230+
DEFINE_LOCK_GUARD_1(msi_descs_lock, struct device, msi_lock_descs(_T->lock),
231+
msi_unlock_descs(_T->lock));
232+
230233
struct msi_desc *msi_domain_first_desc(struct device *dev, unsigned int domid,
231234
enum msi_desc_filter filter);
232235

kernel/irq/msi.c

Lines changed: 40 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,6 @@ EXPORT_SYMBOL_GPL(msi_next_desc);
443443
unsigned int msi_domain_get_virq(struct device *dev, unsigned int domid, unsigned int index)
444444
{
445445
struct msi_desc *desc;
446-
unsigned int ret = 0;
447446
bool pcimsi = false;
448447
struct xarray *xa;
449448

@@ -457,7 +456,7 @@ unsigned int msi_domain_get_virq(struct device *dev, unsigned int domid, unsigne
457456
if (dev_is_pci(dev) && domid == MSI_DEFAULT_DOMAIN)
458457
pcimsi = to_pci_dev(dev)->msi_enabled;
459458

460-
msi_lock_descs(dev);
459+
guard(msi_descs_lock)(dev);
461460
xa = &dev->msi.data->__domains[domid].store;
462461
desc = xa_load(xa, pcimsi ? 0 : index);
463462
if (desc && desc->irq) {
@@ -466,16 +465,12 @@ unsigned int msi_domain_get_virq(struct device *dev, unsigned int domid, unsigne
466465
* PCI-MSIX and platform MSI use a descriptor per
467466
* interrupt.
468467
*/
469-
if (pcimsi) {
470-
if (index < desc->nvec_used)
471-
ret = desc->irq + index;
472-
} else {
473-
ret = desc->irq;
474-
}
468+
if (!pcimsi)
469+
return desc->irq;
470+
if (index < desc->nvec_used)
471+
return desc->irq + index;
475472
}
476-
477-
msi_unlock_descs(dev);
478-
return ret;
473+
return 0;
479474
}
480475
EXPORT_SYMBOL_GPL(msi_domain_get_virq);
481476

@@ -993,17 +988,17 @@ bool msi_create_device_irq_domain(struct device *dev, unsigned int domid,
993988
void *chip_data)
994989
{
995990
struct irq_domain *domain, *parent = dev->msi.domain;
996-
struct fwnode_handle *fwnode, *fwnalloced = NULL;
997-
struct msi_domain_template *bundle;
998991
const struct msi_parent_ops *pops;
992+
struct fwnode_handle *fwnode;
999993

1000994
if (!irq_domain_is_msi_parent(parent))
1001995
return false;
1002996

1003997
if (domid >= MSI_MAX_DEVICE_IRQDOMAINS)
1004998
return false;
1005999

1006-
bundle = kmemdup(template, sizeof(*bundle), GFP_KERNEL);
1000+
struct msi_domain_template *bundle __free(kfree) =
1001+
bundle = kmemdup(template, sizeof(*bundle), GFP_KERNEL);
10071002
if (!bundle)
10081003
return false;
10091004

@@ -1026,41 +1021,36 @@ bool msi_create_device_irq_domain(struct device *dev, unsigned int domid,
10261021
* node as they are not guaranteed to have a fwnode. They are never
10271022
* looked up and always handled in the context of the device.
10281023
*/
1029-
if (bundle->info.flags & MSI_FLAG_USE_DEV_FWNODE)
1030-
fwnode = dev->fwnode;
1024+
struct fwnode_handle *fwnode_alloced __free(irq_domain_free_fwnode) = NULL;
1025+
1026+
if (!(bundle->info.flags & MSI_FLAG_USE_DEV_FWNODE))
1027+
fwnode = fwnode_alloced = irq_domain_alloc_named_fwnode(bundle->name);
10311028
else
1032-
fwnode = fwnalloced = irq_domain_alloc_named_fwnode(bundle->name);
1029+
fwnode = dev->fwnode;
10331030

10341031
if (!fwnode)
1035-
goto free_bundle;
1032+
return false;
10361033

10371034
if (msi_setup_device_data(dev))
1038-
goto free_fwnode;
1039-
1040-
msi_lock_descs(dev);
1035+
return false;
10411036

1037+
guard(msi_descs_lock)(dev);
10421038
if (WARN_ON_ONCE(msi_get_device_domain(dev, domid)))
1043-
goto fail;
1039+
return false;
10441040

10451041
if (!pops->init_dev_msi_info(dev, parent, parent, &bundle->info))
1046-
goto fail;
1042+
return false;
10471043

10481044
domain = __msi_create_irq_domain(fwnode, &bundle->info, IRQ_DOMAIN_FLAG_MSI_DEVICE, parent);
10491045
if (!domain)
1050-
goto fail;
1046+
return false;
10511047

1048+
/* @bundle and @fwnode_alloced are now in use. Prevent cleanup */
1049+
retain_ptr(bundle);
1050+
retain_ptr(fwnode_alloced);
10521051
domain->dev = dev;
10531052
dev->msi.data->__domains[domid].domain = domain;
1054-
msi_unlock_descs(dev);
10551053
return true;
1056-
1057-
fail:
1058-
msi_unlock_descs(dev);
1059-
free_fwnode:
1060-
irq_domain_free_fwnode(fwnalloced);
1061-
free_bundle:
1062-
kfree(bundle);
1063-
return false;
10641054
}
10651055

10661056
/**
@@ -1074,12 +1064,10 @@ void msi_remove_device_irq_domain(struct device *dev, unsigned int domid)
10741064
struct msi_domain_info *info;
10751065
struct irq_domain *domain;
10761066

1077-
msi_lock_descs(dev);
1078-
1067+
guard(msi_descs_lock)(dev);
10791068
domain = msi_get_device_domain(dev, domid);
1080-
10811069
if (!domain || !irq_domain_is_msi_device(domain))
1082-
goto unlock;
1070+
return;
10831071

10841072
dev->msi.data->__domains[domid].domain = NULL;
10851073
info = domain->host_data;
@@ -1088,9 +1076,6 @@ void msi_remove_device_irq_domain(struct device *dev, unsigned int domid)
10881076
irq_domain_remove(domain);
10891077
irq_domain_free_fwnode(fwnode);
10901078
kfree(container_of(info, struct msi_domain_template, info));
1091-
1092-
unlock:
1093-
msi_unlock_descs(dev);
10941079
}
10951080

10961081
/**
@@ -1106,16 +1091,14 @@ bool msi_match_device_irq_domain(struct device *dev, unsigned int domid,
11061091
{
11071092
struct msi_domain_info *info;
11081093
struct irq_domain *domain;
1109-
bool ret = false;
11101094

1111-
msi_lock_descs(dev);
1095+
guard(msi_descs_lock)(dev);
11121096
domain = msi_get_device_domain(dev, domid);
11131097
if (domain && irq_domain_is_msi_device(domain)) {
11141098
info = domain->host_data;
1115-
ret = info->bus_token == bus_token;
1099+
return info->bus_token == bus_token;
11161100
}
1117-
msi_unlock_descs(dev);
1118-
return ret;
1101+
return false;
11191102
}
11201103

11211104
static int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
@@ -1365,12 +1348,9 @@ int msi_domain_alloc_irqs_range(struct device *dev, unsigned int domid,
13651348
.last = last,
13661349
.nirqs = last + 1 - first,
13671350
};
1368-
int ret;
13691351

1370-
msi_lock_descs(dev);
1371-
ret = msi_domain_alloc_locked(dev, &ctrl);
1372-
msi_unlock_descs(dev);
1373-
return ret;
1352+
guard(msi_descs_lock)(dev);
1353+
return msi_domain_alloc_locked(dev, &ctrl);
13741354
}
13751355
EXPORT_SYMBOL_GPL(msi_domain_alloc_irqs_range);
13761356

@@ -1474,12 +1454,8 @@ struct msi_map msi_domain_alloc_irq_at(struct device *dev, unsigned int domid, u
14741454
const struct irq_affinity_desc *affdesc,
14751455
union msi_instance_cookie *icookie)
14761456
{
1477-
struct msi_map map;
1478-
1479-
msi_lock_descs(dev);
1480-
map = __msi_domain_alloc_irq_at(dev, domid, index, affdesc, icookie);
1481-
msi_unlock_descs(dev);
1482-
return map;
1457+
guard(msi_descs_lock)(dev);
1458+
return __msi_domain_alloc_irq_at(dev, domid, index, affdesc, icookie);
14831459
}
14841460

14851461
/**
@@ -1516,13 +1492,11 @@ int msi_device_domain_alloc_wired(struct irq_domain *domain, unsigned int hwirq,
15161492

15171493
icookie.value = ((u64)type << 32) | hwirq;
15181494

1519-
msi_lock_descs(dev);
1495+
guard(msi_descs_lock)(dev);
15201496
if (WARN_ON_ONCE(msi_get_device_domain(dev, domid) != domain))
15211497
map.index = -EINVAL;
15221498
else
15231499
map = __msi_domain_alloc_irq_at(dev, domid, MSI_ANY_INDEX, NULL, &icookie);
1524-
msi_unlock_descs(dev);
1525-
15261500
return map.index >= 0 ? map.virq : map.index;
15271501
}
15281502

@@ -1615,9 +1589,8 @@ static void msi_domain_free_irqs_range_locked(struct device *dev, unsigned int d
16151589
void msi_domain_free_irqs_range(struct device *dev, unsigned int domid,
16161590
unsigned int first, unsigned int last)
16171591
{
1618-
msi_lock_descs(dev);
1592+
guard(msi_descs_lock)(dev);
16191593
msi_domain_free_irqs_range_locked(dev, domid, first, last);
1620-
msi_unlock_descs(dev);
16211594
}
16221595
EXPORT_SYMBOL_GPL(msi_domain_free_irqs_all);
16231596

@@ -1647,9 +1620,8 @@ void msi_domain_free_irqs_all_locked(struct device *dev, unsigned int domid)
16471620
*/
16481621
void msi_domain_free_irqs_all(struct device *dev, unsigned int domid)
16491622
{
1650-
msi_lock_descs(dev);
1623+
guard(msi_descs_lock)(dev);
16511624
msi_domain_free_irqs_all_locked(dev, domid);
1652-
msi_unlock_descs(dev);
16531625
}
16541626

16551627
/**
@@ -1668,12 +1640,11 @@ void msi_device_domain_free_wired(struct irq_domain *domain, unsigned int virq)
16681640
if (WARN_ON_ONCE(!dev || !desc || domain->bus_token != DOMAIN_BUS_WIRED_TO_MSI))
16691641
return;
16701642

1671-
msi_lock_descs(dev);
1672-
if (!WARN_ON_ONCE(msi_get_device_domain(dev, MSI_DEFAULT_DOMAIN) != domain)) {
1673-
msi_domain_free_irqs_range_locked(dev, MSI_DEFAULT_DOMAIN, desc->msi_index,
1674-
desc->msi_index);
1675-
}
1676-
msi_unlock_descs(dev);
1643+
guard(msi_descs_lock)(dev);
1644+
if (WARN_ON_ONCE(msi_get_device_domain(dev, MSI_DEFAULT_DOMAIN) != domain))
1645+
return;
1646+
msi_domain_free_irqs_range_locked(dev, MSI_DEFAULT_DOMAIN, desc->msi_index,
1647+
desc->msi_index);
16771648
}
16781649

16791650
/**

0 commit comments

Comments
 (0)