Skip to content

Commit 0dac2b0

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 092d00e commit 0dac2b0

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
@@ -232,6 +232,9 @@ int msi_setup_device_data(struct device *dev);
232232
void msi_lock_descs(struct device *dev);
233233
void msi_unlock_descs(struct device *dev);
234234

235+
DEFINE_LOCK_GUARD_1(msi_descs_lock, struct device, msi_lock_descs(_T->lock),
236+
msi_unlock_descs(_T->lock));
237+
235238
struct msi_desc *msi_domain_first_desc(struct device *dev, unsigned int domid,
236239
enum msi_desc_filter filter);
237240

kernel/irq/msi.c

Lines changed: 40 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,6 @@ EXPORT_SYMBOL_GPL(msi_next_desc);
448448
unsigned int msi_domain_get_virq(struct device *dev, unsigned int domid, unsigned int index)
449449
{
450450
struct msi_desc *desc;
451-
unsigned int ret = 0;
452451
bool pcimsi = false;
453452
struct xarray *xa;
454453

@@ -462,7 +461,7 @@ unsigned int msi_domain_get_virq(struct device *dev, unsigned int domid, unsigne
462461
if (dev_is_pci(dev) && domid == MSI_DEFAULT_DOMAIN)
463462
pcimsi = to_pci_dev(dev)->msi_enabled;
464463

465-
msi_lock_descs(dev);
464+
guard(msi_descs_lock)(dev);
466465
xa = &dev->msi.data->__domains[domid].store;
467466
desc = xa_load(xa, pcimsi ? 0 : index);
468467
if (desc && desc->irq) {
@@ -471,16 +470,12 @@ unsigned int msi_domain_get_virq(struct device *dev, unsigned int domid, unsigne
471470
* PCI-MSIX and platform MSI use a descriptor per
472471
* interrupt.
473472
*/
474-
if (pcimsi) {
475-
if (index < desc->nvec_used)
476-
ret = desc->irq + index;
477-
} else {
478-
ret = desc->irq;
479-
}
473+
if (!pcimsi)
474+
return desc->irq;
475+
if (index < desc->nvec_used)
476+
return desc->irq + index;
480477
}
481-
482-
msi_unlock_descs(dev);
483-
return ret;
478+
return 0;
484479
}
485480
EXPORT_SYMBOL_GPL(msi_domain_get_virq);
486481

@@ -998,17 +993,17 @@ bool msi_create_device_irq_domain(struct device *dev, unsigned int domid,
998993
void *chip_data)
999994
{
1000995
struct irq_domain *domain, *parent = dev->msi.domain;
1001-
struct fwnode_handle *fwnode, *fwnalloced = NULL;
1002-
struct msi_domain_template *bundle;
1003996
const struct msi_parent_ops *pops;
997+
struct fwnode_handle *fwnode;
1004998

1005999
if (!irq_domain_is_msi_parent(parent))
10061000
return false;
10071001

10081002
if (domid >= MSI_MAX_DEVICE_IRQDOMAINS)
10091003
return false;
10101004

1011-
bundle = kmemdup(template, sizeof(*bundle), GFP_KERNEL);
1005+
struct msi_domain_template *bundle __free(kfree) =
1006+
kmemdup(template, sizeof(*bundle), GFP_KERNEL);
10121007
if (!bundle)
10131008
return false;
10141009

@@ -1031,41 +1026,36 @@ bool msi_create_device_irq_domain(struct device *dev, unsigned int domid,
10311026
* node as they are not guaranteed to have a fwnode. They are never
10321027
* looked up and always handled in the context of the device.
10331028
*/
1034-
if (bundle->info.flags & MSI_FLAG_USE_DEV_FWNODE)
1035-
fwnode = dev->fwnode;
1029+
struct fwnode_handle *fwnode_alloced __free(irq_domain_free_fwnode) = NULL;
1030+
1031+
if (!(bundle->info.flags & MSI_FLAG_USE_DEV_FWNODE))
1032+
fwnode = fwnode_alloced = irq_domain_alloc_named_fwnode(bundle->name);
10361033
else
1037-
fwnode = fwnalloced = irq_domain_alloc_named_fwnode(bundle->name);
1034+
fwnode = dev->fwnode;
10381035

10391036
if (!fwnode)
1040-
goto free_bundle;
1037+
return false;
10411038

10421039
if (msi_setup_device_data(dev))
1043-
goto free_fwnode;
1044-
1045-
msi_lock_descs(dev);
1040+
return false;
10461041

1042+
guard(msi_descs_lock)(dev);
10471043
if (WARN_ON_ONCE(msi_get_device_domain(dev, domid)))
1048-
goto fail;
1044+
return false;
10491045

10501046
if (!pops->init_dev_msi_info(dev, parent, parent, &bundle->info))
1051-
goto fail;
1047+
return false;
10521048

10531049
domain = __msi_create_irq_domain(fwnode, &bundle->info, IRQ_DOMAIN_FLAG_MSI_DEVICE, parent);
10541050
if (!domain)
1055-
goto fail;
1051+
return false;
10561052

1053+
/* @bundle and @fwnode_alloced are now in use. Prevent cleanup */
1054+
retain_and_null_ptr(bundle);
1055+
retain_and_null_ptr(fwnode_alloced);
10571056
domain->dev = dev;
10581057
dev->msi.data->__domains[domid].domain = domain;
1059-
msi_unlock_descs(dev);
10601058
return true;
1061-
1062-
fail:
1063-
msi_unlock_descs(dev);
1064-
free_fwnode:
1065-
irq_domain_free_fwnode(fwnalloced);
1066-
free_bundle:
1067-
kfree(bundle);
1068-
return false;
10691059
}
10701060

10711061
/**
@@ -1079,12 +1069,10 @@ void msi_remove_device_irq_domain(struct device *dev, unsigned int domid)
10791069
struct msi_domain_info *info;
10801070
struct irq_domain *domain;
10811071

1082-
msi_lock_descs(dev);
1083-
1072+
guard(msi_descs_lock)(dev);
10841073
domain = msi_get_device_domain(dev, domid);
1085-
10861074
if (!domain || !irq_domain_is_msi_device(domain))
1087-
goto unlock;
1075+
return;
10881076

10891077
dev->msi.data->__domains[domid].domain = NULL;
10901078
info = domain->host_data;
@@ -1093,9 +1081,6 @@ void msi_remove_device_irq_domain(struct device *dev, unsigned int domid)
10931081
irq_domain_remove(domain);
10941082
irq_domain_free_fwnode(fwnode);
10951083
kfree(container_of(info, struct msi_domain_template, info));
1096-
1097-
unlock:
1098-
msi_unlock_descs(dev);
10991084
}
11001085

11011086
/**
@@ -1111,16 +1096,14 @@ bool msi_match_device_irq_domain(struct device *dev, unsigned int domid,
11111096
{
11121097
struct msi_domain_info *info;
11131098
struct irq_domain *domain;
1114-
bool ret = false;
11151099

1116-
msi_lock_descs(dev);
1100+
guard(msi_descs_lock)(dev);
11171101
domain = msi_get_device_domain(dev, domid);
11181102
if (domain && irq_domain_is_msi_device(domain)) {
11191103
info = domain->host_data;
1120-
ret = info->bus_token == bus_token;
1104+
return info->bus_token == bus_token;
11211105
}
1122-
msi_unlock_descs(dev);
1123-
return ret;
1106+
return false;
11241107
}
11251108

11261109
static int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
@@ -1391,12 +1374,9 @@ int msi_domain_alloc_irqs_range_locked(struct device *dev, unsigned int domid,
13911374
int msi_domain_alloc_irqs_range(struct device *dev, unsigned int domid,
13921375
unsigned int first, unsigned int last)
13931376
{
1394-
int ret;
13951377

1396-
msi_lock_descs(dev);
1397-
ret = msi_domain_alloc_irqs_range_locked(dev, domid, first, last);
1398-
msi_unlock_descs(dev);
1399-
return ret;
1378+
guard(msi_descs_lock)(dev);
1379+
return msi_domain_alloc_irqs_range_locked(dev, domid, first, last);
14001380
}
14011381
EXPORT_SYMBOL_GPL(msi_domain_alloc_irqs_range);
14021382

@@ -1500,12 +1480,8 @@ struct msi_map msi_domain_alloc_irq_at(struct device *dev, unsigned int domid, u
15001480
const struct irq_affinity_desc *affdesc,
15011481
union msi_instance_cookie *icookie)
15021482
{
1503-
struct msi_map map;
1504-
1505-
msi_lock_descs(dev);
1506-
map = __msi_domain_alloc_irq_at(dev, domid, index, affdesc, icookie);
1507-
msi_unlock_descs(dev);
1508-
return map;
1483+
guard(msi_descs_lock)(dev);
1484+
return __msi_domain_alloc_irq_at(dev, domid, index, affdesc, icookie);
15091485
}
15101486

15111487
/**
@@ -1542,13 +1518,11 @@ int msi_device_domain_alloc_wired(struct irq_domain *domain, unsigned int hwirq,
15421518

15431519
icookie.value = ((u64)type << 32) | hwirq;
15441520

1545-
msi_lock_descs(dev);
1521+
guard(msi_descs_lock)(dev);
15461522
if (WARN_ON_ONCE(msi_get_device_domain(dev, domid) != domain))
15471523
map.index = -EINVAL;
15481524
else
15491525
map = __msi_domain_alloc_irq_at(dev, domid, MSI_ANY_INDEX, NULL, &icookie);
1550-
msi_unlock_descs(dev);
1551-
15521526
return map.index >= 0 ? map.virq : map.index;
15531527
}
15541528

@@ -1641,9 +1615,8 @@ void msi_domain_free_irqs_range_locked(struct device *dev, unsigned int domid,
16411615
void msi_domain_free_irqs_range(struct device *dev, unsigned int domid,
16421616
unsigned int first, unsigned int last)
16431617
{
1644-
msi_lock_descs(dev);
1618+
guard(msi_descs_lock)(dev);
16451619
msi_domain_free_irqs_range_locked(dev, domid, first, last);
1646-
msi_unlock_descs(dev);
16471620
}
16481621
EXPORT_SYMBOL_GPL(msi_domain_free_irqs_all);
16491622

@@ -1673,9 +1646,8 @@ void msi_domain_free_irqs_all_locked(struct device *dev, unsigned int domid)
16731646
*/
16741647
void msi_domain_free_irqs_all(struct device *dev, unsigned int domid)
16751648
{
1676-
msi_lock_descs(dev);
1649+
guard(msi_descs_lock)(dev);
16771650
msi_domain_free_irqs_all_locked(dev, domid);
1678-
msi_unlock_descs(dev);
16791651
}
16801652

16811653
/**
@@ -1694,12 +1666,11 @@ void msi_device_domain_free_wired(struct irq_domain *domain, unsigned int virq)
16941666
if (WARN_ON_ONCE(!dev || !desc || domain->bus_token != DOMAIN_BUS_WIRED_TO_MSI))
16951667
return;
16961668

1697-
msi_lock_descs(dev);
1698-
if (!WARN_ON_ONCE(msi_get_device_domain(dev, MSI_DEFAULT_DOMAIN) != domain)) {
1699-
msi_domain_free_irqs_range_locked(dev, MSI_DEFAULT_DOMAIN, desc->msi_index,
1700-
desc->msi_index);
1701-
}
1702-
msi_unlock_descs(dev);
1669+
guard(msi_descs_lock)(dev);
1670+
if (WARN_ON_ONCE(msi_get_device_domain(dev, MSI_DEFAULT_DOMAIN) != domain))
1671+
return;
1672+
msi_domain_free_irqs_range_locked(dev, MSI_DEFAULT_DOMAIN, desc->msi_index,
1673+
desc->msi_index);
17031674
}
17041675

17051676
/**

0 commit comments

Comments
 (0)