Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'irq-msi-2025-03-23' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull MSI irq updates from Thomas Gleixner:

- Switch the MSI descriptor locking to guards

- Replace the broken PCI/TPH implementation, which lacks any form of
serialization against concurrent modifications with a properly
serialized mechanism in the PCI/MSI core code

- Replace the MSI descriptor abuse in the SCSI/UFS Qualcom driver with
dedicated driver internal storage

* tag 'irq-msi-2025-03-23' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
genirq/msi: Rename msi_[un]lock_descs()
scsi: ufs: qcom: Remove the MSI descriptor abuse
PCI/TPH: Replace the broken MSI-X control word update
PCI/MSI: Provide a sane mechanism for TPH
PCI: hv: Switch MSI descriptor locking to guard()
PCI/MSI: Switch to MSI descriptor locking to guard()
NTB/msi: Switch MSI descriptor locking to lock guard()
soc: ti: ti_sci_inta_msi: Switch MSI descriptor locking to guard()
genirq/msi: Use lock guards for MSI descriptor locking
cleanup: Provide retain_ptr()
genirq/msi: Make a few functions static

+256 -291
+8 -14
drivers/ntb/msi.c
··· 106 106 if (!ntb->msi) 107 107 return -EINVAL; 108 108 109 - msi_lock_descs(&ntb->pdev->dev); 110 - desc = msi_first_desc(&ntb->pdev->dev, MSI_DESC_ASSOCIATED); 111 - addr = desc->msg.address_lo + ((uint64_t)desc->msg.address_hi << 32); 112 - msi_unlock_descs(&ntb->pdev->dev); 109 + scoped_guard (msi_descs_lock, &ntb->pdev->dev) { 110 + desc = msi_first_desc(&ntb->pdev->dev, MSI_DESC_ASSOCIATED); 111 + addr = desc->msg.address_lo + ((uint64_t)desc->msg.address_hi << 32); 112 + } 113 113 114 114 for (peer = 0; peer < ntb_peer_port_count(ntb); peer++) { 115 115 peer_widx = ntb_peer_highest_mw_idx(ntb, peer); ··· 289 289 if (!ntb->msi) 290 290 return -EINVAL; 291 291 292 - msi_lock_descs(dev); 292 + guard(msi_descs_lock)(dev); 293 293 msi_for_each_desc(entry, dev, MSI_DESC_ASSOCIATED) { 294 294 if (irq_has_action(entry->irq)) 295 295 continue; ··· 307 307 ret = ntbm_msi_setup_callback(ntb, entry, msi_desc); 308 308 if (ret) { 309 309 devm_free_irq(&ntb->dev, entry->irq, dev_id); 310 - goto unlock; 310 + return ret; 311 311 } 312 - 313 - ret = entry->irq; 314 - goto unlock; 312 + return entry->irq; 315 313 } 316 - ret = -ENODEV; 317 - 318 - unlock: 319 - msi_unlock_descs(dev); 320 - return ret; 314 + return -ENODEV; 321 315 } 322 316 EXPORT_SYMBOL(ntbm_msi_request_threaded_irq); 323 317
+4 -10
drivers/pci/controller/pci-hyperv.c
··· 3975 3975 { 3976 3976 struct irq_data *irq_data; 3977 3977 struct msi_desc *entry; 3978 - int ret = 0; 3979 3978 3980 3979 if (!pdev->msi_enabled && !pdev->msix_enabled) 3981 3980 return 0; 3982 3981 3983 - msi_lock_descs(&pdev->dev); 3982 + guard(msi_descs_lock)(&pdev->dev); 3984 3983 msi_for_each_desc(entry, &pdev->dev, MSI_DESC_ASSOCIATED) { 3985 3984 irq_data = irq_get_irq_data(entry->irq); 3986 - if (WARN_ON_ONCE(!irq_data)) { 3987 - ret = -EINVAL; 3988 - break; 3989 - } 3990 - 3985 + if (WARN_ON_ONCE(!irq_data)) 3986 + return -EINVAL; 3991 3987 hv_compose_msi_msg(irq_data, &entry->msg); 3992 3988 } 3993 - msi_unlock_descs(&pdev->dev); 3994 - 3995 - return ret; 3989 + return 0; 3996 3990 } 3997 3991 3998 3992 /*
+2 -4
drivers/pci/msi/api.c
··· 53 53 if (!pci_msi_enabled() || !dev || !dev->msi_enabled) 54 54 return; 55 55 56 - msi_lock_descs(&dev->dev); 56 + guard(msi_descs_lock)(&dev->dev); 57 57 pci_msi_shutdown(dev); 58 58 pci_free_msi_irqs(dev); 59 - msi_unlock_descs(&dev->dev); 60 59 } 61 60 EXPORT_SYMBOL(pci_disable_msi); 62 61 ··· 195 196 if (!pci_msi_enabled() || !dev || !dev->msix_enabled) 196 197 return; 197 198 198 - msi_lock_descs(&dev->dev); 199 + guard(msi_descs_lock)(&dev->dev); 199 200 pci_msix_shutdown(dev); 200 201 pci_free_msi_irqs(dev); 201 - msi_unlock_descs(&dev->dev); 202 202 } 203 203 EXPORT_SYMBOL(pci_disable_msix); 204 204
+107 -60
drivers/pci/msi/msi.c
··· 336 336 return !entry ? 0 : -EIO; 337 337 } 338 338 339 - /** 340 - * msi_capability_init - configure device's MSI capability structure 341 - * @dev: pointer to the pci_dev data structure of MSI device function 342 - * @nvec: number of interrupts to allocate 343 - * @affd: description of automatic IRQ affinity assignments (may be %NULL) 344 - * 345 - * Setup the MSI capability structure of the device with the requested 346 - * number of interrupts. A return value of zero indicates the successful 347 - * setup of an entry with the new MSI IRQ. A negative return value indicates 348 - * an error, and a positive return value indicates the number of interrupts 349 - * which could have been allocated. 350 - */ 351 - static int msi_capability_init(struct pci_dev *dev, int nvec, 352 - struct irq_affinity *affd) 339 + static int __msi_capability_init(struct pci_dev *dev, int nvec, struct irq_affinity_desc *masks) 353 340 { 354 - struct irq_affinity_desc *masks = NULL; 341 + int ret = msi_setup_msi_desc(dev, nvec, masks); 355 342 struct msi_desc *entry, desc; 356 - int ret; 357 343 358 - /* Reject multi-MSI early on irq domain enabled architectures */ 359 - if (nvec > 1 && !pci_msi_domain_supports(dev, MSI_FLAG_MULTI_PCI_MSI, ALLOW_LEGACY)) 360 - return 1; 361 - 362 - /* 363 - * Disable MSI during setup in the hardware, but mark it enabled 364 - * so that setup code can evaluate it. 365 - */ 366 - pci_msi_set_enable(dev, 0); 367 - dev->msi_enabled = 1; 368 - 369 - if (affd) 370 - masks = irq_create_affinity_masks(nvec, affd); 371 - 372 - msi_lock_descs(&dev->dev); 373 - ret = msi_setup_msi_desc(dev, nvec, masks); 374 344 if (ret) 375 345 goto fail; 376 346 ··· 369 399 370 400 pcibios_free_irq(dev); 371 401 dev->irq = entry->irq; 372 - goto unlock; 373 - 402 + return 0; 374 403 err: 375 404 pci_msi_unmask(&desc, msi_multi_mask(&desc)); 376 405 pci_free_msi_irqs(dev); 377 406 fail: 378 407 dev->msi_enabled = 0; 379 - unlock: 380 - msi_unlock_descs(&dev->dev); 381 - kfree(masks); 382 408 return ret; 409 + } 410 + 411 + /** 412 + * msi_capability_init - configure device's MSI capability structure 413 + * @dev: pointer to the pci_dev data structure of MSI device function 414 + * @nvec: number of interrupts to allocate 415 + * @affd: description of automatic IRQ affinity assignments (may be %NULL) 416 + * 417 + * Setup the MSI capability structure of the device with the requested 418 + * number of interrupts. A return value of zero indicates the successful 419 + * setup of an entry with the new MSI IRQ. A negative return value indicates 420 + * an error, and a positive return value indicates the number of interrupts 421 + * which could have been allocated. 422 + */ 423 + static int msi_capability_init(struct pci_dev *dev, int nvec, 424 + struct irq_affinity *affd) 425 + { 426 + /* Reject multi-MSI early on irq domain enabled architectures */ 427 + if (nvec > 1 && !pci_msi_domain_supports(dev, MSI_FLAG_MULTI_PCI_MSI, ALLOW_LEGACY)) 428 + return 1; 429 + 430 + /* 431 + * Disable MSI during setup in the hardware, but mark it enabled 432 + * so that setup code can evaluate it. 433 + */ 434 + pci_msi_set_enable(dev, 0); 435 + dev->msi_enabled = 1; 436 + 437 + struct irq_affinity_desc *masks __free(kfree) = 438 + affd ? irq_create_affinity_masks(nvec, affd) : NULL; 439 + 440 + guard(msi_descs_lock)(&dev->dev); 441 + return __msi_capability_init(dev, nvec, masks); 383 442 } 384 443 385 444 int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, ··· 665 666 writel(ctrl, base + PCI_MSIX_ENTRY_VECTOR_CTRL); 666 667 } 667 668 668 - static int msix_setup_interrupts(struct pci_dev *dev, struct msix_entry *entries, 669 - int nvec, struct irq_affinity *affd) 669 + static int __msix_setup_interrupts(struct pci_dev *dev, struct msix_entry *entries, 670 + int nvec, struct irq_affinity_desc *masks) 670 671 { 671 - struct irq_affinity_desc *masks = NULL; 672 - int ret; 672 + int ret = msix_setup_msi_descs(dev, entries, nvec, masks); 673 673 674 - if (affd) 675 - masks = irq_create_affinity_masks(nvec, affd); 676 - 677 - msi_lock_descs(&dev->dev); 678 - ret = msix_setup_msi_descs(dev, entries, nvec, masks); 679 674 if (ret) 680 - goto out_free; 675 + goto fail; 681 676 682 677 ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); 683 678 if (ret) 684 - goto out_free; 679 + goto fail; 685 680 686 681 /* Check if all MSI entries honor device restrictions */ 687 682 ret = msi_verify_entries(dev); 688 683 if (ret) 689 - goto out_free; 684 + goto fail; 690 685 691 686 msix_update_entries(dev, entries); 692 - goto out_unlock; 687 + return 0; 693 688 694 - out_free: 689 + fail: 695 690 pci_free_msi_irqs(dev); 696 - out_unlock: 697 - msi_unlock_descs(&dev->dev); 698 - kfree(masks); 699 691 return ret; 692 + } 693 + 694 + static int msix_setup_interrupts(struct pci_dev *dev, struct msix_entry *entries, 695 + int nvec, struct irq_affinity *affd) 696 + { 697 + struct irq_affinity_desc *masks __free(kfree) = 698 + affd ? irq_create_affinity_masks(nvec, affd) : NULL; 699 + 700 + guard(msi_descs_lock)(&dev->dev); 701 + return __msix_setup_interrupts(dev, entries, nvec, masks); 700 702 } 701 703 702 704 /** ··· 871 871 872 872 write_msg = arch_restore_msi_irqs(dev); 873 873 874 - msi_lock_descs(&dev->dev); 875 - msi_for_each_desc(entry, &dev->dev, MSI_DESC_ALL) { 876 - if (write_msg) 877 - __pci_write_msi_msg(entry, &entry->msg); 878 - pci_msix_write_vector_ctrl(entry, entry->pci.msix_ctrl); 874 + scoped_guard (msi_descs_lock, &dev->dev) { 875 + msi_for_each_desc(entry, &dev->dev, MSI_DESC_ALL) { 876 + if (write_msg) 877 + __pci_write_msi_msg(entry, &entry->msg); 878 + pci_msix_write_vector_ctrl(entry, entry->pci.msix_ctrl); 879 + } 879 880 } 880 - msi_unlock_descs(&dev->dev); 881 881 882 882 pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0); 883 883 } ··· 915 915 dev->msix_base = NULL; 916 916 } 917 917 } 918 + 919 + #ifdef CONFIG_PCIE_TPH 920 + /** 921 + * pci_msix_write_tph_tag - Update the TPH tag for a given MSI-X vector 922 + * @pdev: The PCIe device to update 923 + * @index: The MSI-X index to update 924 + * @tag: The tag to write 925 + * 926 + * Returns: 0 on success, error code on failure 927 + */ 928 + int pci_msix_write_tph_tag(struct pci_dev *pdev, unsigned int index, u16 tag) 929 + { 930 + struct msi_desc *msi_desc; 931 + struct irq_desc *irq_desc; 932 + unsigned int virq; 933 + 934 + if (!pdev->msix_enabled) 935 + return -ENXIO; 936 + 937 + guard(msi_descs_lock)(&pdev->dev); 938 + virq = msi_get_virq(&pdev->dev, index); 939 + if (!virq) 940 + return -ENXIO; 941 + /* 942 + * This is a horrible hack, but short of implementing a PCI 943 + * specific interrupt chip callback and a huge pile of 944 + * infrastructure, this is the minor nuissance. It provides the 945 + * protection against concurrent operations on this entry and keeps 946 + * the control word cache in sync. 947 + */ 948 + irq_desc = irq_to_desc(virq); 949 + if (!irq_desc) 950 + return -ENXIO; 951 + 952 + guard(raw_spinlock_irq)(&irq_desc->lock); 953 + msi_desc = irq_data_get_msi_desc(&irq_desc->irq_data); 954 + if (!msi_desc || msi_desc->pci.msi_attrib.is_virtual) 955 + return -ENXIO; 956 + 957 + msi_desc->pci.msix_ctrl &= ~PCI_MSIX_ENTRY_CTRL_ST; 958 + msi_desc->pci.msix_ctrl |= FIELD_PREP(PCI_MSIX_ENTRY_CTRL_ST, tag); 959 + pci_msix_write_vector_ctrl(msi_desc, msi_desc->pci.msix_ctrl); 960 + /* Flush the write */ 961 + readl(pci_msix_desc_addr(msi_desc)); 962 + return 0; 963 + } 964 + #endif 918 965 919 966 /* Misc. infrastructure */ 920 967
+9
drivers/pci/pci.h
··· 989 989 const char *name); 990 990 void pcim_release_region(struct pci_dev *pdev, int bar); 991 991 992 + #ifdef CONFIG_PCI_MSI 993 + int pci_msix_write_tph_tag(struct pci_dev *pdev, unsigned int index, u16 tag); 994 + #else 995 + static inline int pci_msix_write_tph_tag(struct pci_dev *pdev, unsigned int index, u16 tag) 996 + { 997 + return -ENODEV; 998 + } 999 + #endif 1000 + 992 1001 /* 993 1002 * Config Address for PCI Configuration Mechanism #1 994 1003 *
+1 -43
drivers/pci/tph.c
··· 204 204 return FIELD_GET(PCI_EXP_DEVCAP2_TPH_COMP_MASK, reg); 205 205 } 206 206 207 - /* Write ST to MSI-X vector control reg - Return 0 if OK, otherwise -errno */ 208 - static int write_tag_to_msix(struct pci_dev *pdev, int msix_idx, u16 tag) 209 - { 210 - #ifdef CONFIG_PCI_MSI 211 - struct msi_desc *msi_desc = NULL; 212 - void __iomem *vec_ctrl; 213 - u32 val; 214 - int err = 0; 215 - 216 - msi_lock_descs(&pdev->dev); 217 - 218 - /* Find the msi_desc entry with matching msix_idx */ 219 - msi_for_each_desc(msi_desc, &pdev->dev, MSI_DESC_ASSOCIATED) { 220 - if (msi_desc->msi_index == msix_idx) 221 - break; 222 - } 223 - 224 - if (!msi_desc) { 225 - err = -ENXIO; 226 - goto err_out; 227 - } 228 - 229 - /* Get the vector control register (offset 0xc) pointed by msix_idx */ 230 - vec_ctrl = pdev->msix_base + msix_idx * PCI_MSIX_ENTRY_SIZE; 231 - vec_ctrl += PCI_MSIX_ENTRY_VECTOR_CTRL; 232 - 233 - val = readl(vec_ctrl); 234 - val &= ~PCI_MSIX_ENTRY_CTRL_ST; 235 - val |= FIELD_PREP(PCI_MSIX_ENTRY_CTRL_ST, tag); 236 - writel(val, vec_ctrl); 237 - 238 - /* Read back to flush the update */ 239 - val = readl(vec_ctrl); 240 - 241 - err_out: 242 - msi_unlock_descs(&pdev->dev); 243 - return err; 244 - #else 245 - return -ENODEV; 246 - #endif 247 - } 248 - 249 207 /* Write tag to ST table - Return 0 if OK, otherwise -errno */ 250 208 static int write_tag_to_st_table(struct pci_dev *pdev, int index, u16 tag) 251 209 { ··· 304 346 305 347 switch (loc) { 306 348 case PCI_TPH_LOC_MSIX: 307 - err = write_tag_to_msix(pdev, index, tag); 349 + err = pci_msix_write_tph_tag(pdev, index, tag); 308 350 break; 309 351 case PCI_TPH_LOC_CAP: 310 352 err = write_tag_to_st_table(pdev, index, tag);
+3 -7
drivers/soc/ti/ti_sci_inta_msi.c
··· 103 103 if (ret) 104 104 return ret; 105 105 106 - msi_lock_descs(dev); 106 + guard(msi_descs_lock)(dev); 107 107 nvec = ti_sci_inta_msi_alloc_descs(dev, res); 108 - if (nvec <= 0) { 109 - ret = nvec; 110 - goto unlock; 111 - } 108 + if (nvec <= 0) 109 + return nvec; 112 110 113 111 /* Use alloc ALL as it's unclear whether there are gaps in the indices */ 114 112 ret = msi_domain_alloc_irqs_all_locked(dev, MSI_DEFAULT_DOMAIN, nvec); 115 113 if (ret) 116 114 dev_err(dev, "Failed to allocate IRQs %d\n", ret); 117 - unlock: 118 - msi_unlock_descs(dev); 119 115 return ret; 120 116 } 121 117 EXPORT_SYMBOL_GPL(ti_sci_inta_msi_domain_alloc_irqs);
+39 -36
drivers/ufs/host/ufs-qcom.c
··· 1782 1782 ufshcd_mcq_config_esi(hba, msg); 1783 1783 } 1784 1784 1785 + struct ufs_qcom_irq { 1786 + unsigned int irq; 1787 + unsigned int idx; 1788 + struct ufs_hba *hba; 1789 + }; 1790 + 1785 1791 static irqreturn_t ufs_qcom_mcq_esi_handler(int irq, void *data) 1786 1792 { 1787 - struct msi_desc *desc = data; 1788 - struct device *dev = msi_desc_to_dev(desc); 1789 - struct ufs_hba *hba = dev_get_drvdata(dev); 1790 - u32 id = desc->msi_index; 1791 - struct ufs_hw_queue *hwq = &hba->uhq[id]; 1793 + struct ufs_qcom_irq *qi = data; 1794 + struct ufs_hba *hba = qi->hba; 1795 + struct ufs_hw_queue *hwq = &hba->uhq[qi->idx]; 1792 1796 1793 - ufshcd_mcq_write_cqis(hba, 0x1, id); 1797 + ufshcd_mcq_write_cqis(hba, 0x1, qi->idx); 1794 1798 ufshcd_mcq_poll_cqe_lock(hba, hwq); 1795 1799 1796 1800 return IRQ_HANDLED; ··· 1803 1799 static int ufs_qcom_config_esi(struct ufs_hba *hba) 1804 1800 { 1805 1801 struct ufs_qcom_host *host = ufshcd_get_variant(hba); 1806 - struct msi_desc *desc; 1807 - struct msi_desc *failed_desc = NULL; 1802 + struct ufs_qcom_irq *qi; 1808 1803 int nr_irqs, ret; 1809 1804 1810 1805 if (host->esi_enabled) ··· 1814 1811 * 2. Poll queues do not need ESI. 1815 1812 */ 1816 1813 nr_irqs = hba->nr_hw_queues - hba->nr_queues[HCTX_TYPE_POLL]; 1814 + qi = devm_kcalloc(hba->dev, nr_irqs, sizeof(*qi), GFP_KERNEL); 1815 + if (qi) 1816 + return -ENOMEM; 1817 + 1817 1818 ret = platform_device_msi_init_and_alloc_irqs(hba->dev, nr_irqs, 1818 1819 ufs_qcom_write_msi_msg); 1819 1820 if (ret) { 1820 1821 dev_err(hba->dev, "Failed to request Platform MSI %d\n", ret); 1821 - return ret; 1822 + goto cleanup; 1822 1823 } 1823 1824 1824 - msi_lock_descs(hba->dev); 1825 - msi_for_each_desc(desc, hba->dev, MSI_DESC_ALL) { 1826 - ret = devm_request_irq(hba->dev, desc->irq, 1827 - ufs_qcom_mcq_esi_handler, 1828 - IRQF_SHARED, "qcom-mcq-esi", desc); 1825 + for (int idx = 0; idx < nr_irqs; idx++) { 1826 + qi[idx].irq = msi_get_virq(hba->dev, idx); 1827 + qi[idx].idx = idx; 1828 + qi[idx].hba = hba; 1829 + 1830 + ret = devm_request_irq(hba->dev, qi[idx].irq, ufs_qcom_mcq_esi_handler, 1831 + IRQF_SHARED, "qcom-mcq-esi", qi + idx); 1829 1832 if (ret) { 1830 1833 dev_err(hba->dev, "%s: Fail to request IRQ for %d, err = %d\n", 1831 - __func__, desc->irq, ret); 1832 - failed_desc = desc; 1833 - break; 1834 + __func__, qi[idx].irq, ret); 1835 + qi[idx].irq = 0; 1836 + goto cleanup; 1834 1837 } 1835 1838 } 1836 - msi_unlock_descs(hba->dev); 1837 1839 1838 - if (ret) { 1839 - /* Rewind */ 1840 - msi_lock_descs(hba->dev); 1841 - msi_for_each_desc(desc, hba->dev, MSI_DESC_ALL) { 1842 - if (desc == failed_desc) 1843 - break; 1844 - devm_free_irq(hba->dev, desc->irq, hba); 1845 - } 1846 - msi_unlock_descs(hba->dev); 1847 - platform_device_msi_free_irqs_all(hba->dev); 1848 - } else { 1849 - if (host->hw_ver.major == 6 && host->hw_ver.minor == 0 && 1850 - host->hw_ver.step == 0) 1851 - ufshcd_rmwl(hba, ESI_VEC_MASK, 1852 - FIELD_PREP(ESI_VEC_MASK, MAX_ESI_VEC - 1), 1853 - REG_UFS_CFG3); 1854 - ufshcd_mcq_enable_esi(hba); 1855 - host->esi_enabled = true; 1840 + if (host->hw_ver.major == 6 && host->hw_ver.minor == 0 && 1841 + host->hw_ver.step == 0) { 1842 + ufshcd_rmwl(hba, ESI_VEC_MASK, 1843 + FIELD_PREP(ESI_VEC_MASK, MAX_ESI_VEC - 1), 1844 + REG_UFS_CFG3); 1856 1845 } 1846 + ufshcd_mcq_enable_esi(hba); 1847 + host->esi_enabled = true; 1848 + return 0; 1857 1849 1850 + cleanup: 1851 + for (int idx = 0; qi[idx].irq; idx++) 1852 + devm_free_irq(hba->dev, qi[idx].irq, hba); 1853 + platform_device_msi_free_irqs_all(hba->dev); 1854 + devm_kfree(hba->dev, qi); 1858 1855 return ret; 1859 1856 } 1860 1857
+17
include/linux/cleanup.h
··· 216 216 217 217 #define return_ptr(p) return no_free_ptr(p) 218 218 219 + /* 220 + * Only for situations where an allocation is handed in to another function 221 + * and consumed by that function on success. 222 + * 223 + * struct foo *f __free(kfree) = kzalloc(sizeof(*f), GFP_KERNEL); 224 + * 225 + * setup(f); 226 + * if (some_condition) 227 + * return -EINVAL; 228 + * .... 229 + * ret = bar(f); 230 + * if (!ret) 231 + * retain_ptr(f); 232 + * return ret; 233 + */ 234 + #define retain_ptr(p) \ 235 + __get_and_null(p, NULL) 219 236 220 237 /* 221 238 * DEFINE_CLASS(name, type, exit, init, init_args...):
+2
include/linux/irqdomain.h
··· 281 281 282 282 void irq_domain_free_fwnode(struct fwnode_handle *fwnode); 283 283 284 + DEFINE_FREE(irq_domain_free_fwnode, struct fwnode_handle *, if (_T) irq_domain_free_fwnode(_T)) 285 + 284 286 struct irq_domain_chip_generic_info; 285 287 286 288 /**
+5 -7
include/linux/msi.h
··· 81 81 struct irq_domain; 82 82 struct irq_affinity_desc; 83 83 84 - void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg); 85 84 #ifdef CONFIG_GENERIC_MSI_IRQ 86 85 void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg); 87 86 #else ··· 224 225 225 226 int msi_setup_device_data(struct device *dev); 226 227 227 - void msi_lock_descs(struct device *dev); 228 - void msi_unlock_descs(struct device *dev); 228 + void __msi_lock_descs(struct device *dev); 229 + void __msi_unlock_descs(struct device *dev); 230 + 231 + DEFINE_LOCK_GUARD_1(msi_descs_lock, struct device, __msi_lock_descs(_T->lock), 232 + __msi_unlock_descs(_T->lock)); 229 233 230 234 struct msi_desc *msi_domain_first_desc(struct device *dev, unsigned int domid, 231 235 enum msi_desc_filter filter); ··· 605 603 bool msi_match_device_irq_domain(struct device *dev, unsigned int domid, 606 604 enum irq_domain_bus_token bus_token); 607 605 608 - int msi_domain_alloc_irqs_range_locked(struct device *dev, unsigned int domid, 609 - unsigned int first, unsigned int last); 610 606 int msi_domain_alloc_irqs_range(struct device *dev, unsigned int domid, 611 607 unsigned int first, unsigned int last); 612 608 int msi_domain_alloc_irqs_all_locked(struct device *dev, unsigned int domid, int nirqs); ··· 613 613 const struct irq_affinity_desc *affdesc, 614 614 union msi_instance_cookie *cookie); 615 615 616 - void msi_domain_free_irqs_range_locked(struct device *dev, unsigned int domid, 617 - unsigned int first, unsigned int last); 618 616 void msi_domain_free_irqs_range(struct device *dev, unsigned int domid, 619 617 unsigned int first, unsigned int last); 620 618 void msi_domain_free_irqs_all_locked(struct device *dev, unsigned int domid);
+59 -110
kernel/irq/msi.c
··· 270 270 return ret; 271 271 } 272 272 273 - void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg) 274 - { 275 - *msg = entry->msg; 276 - } 277 - 278 273 void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg) 279 274 { 280 275 struct msi_desc *entry = irq_get_msi_desc(irq); 281 276 282 - __get_cached_msi_msg(entry, msg); 277 + *msg = entry->msg; 283 278 } 284 279 EXPORT_SYMBOL_GPL(get_cached_msi_msg); 285 280 ··· 338 343 } 339 344 340 345 /** 341 - * msi_lock_descs - Lock the MSI descriptor storage of a device 346 + * __msi_lock_descs - Lock the MSI descriptor storage of a device 342 347 * @dev: Device to operate on 348 + * 349 + * Internal function for guard(msi_descs_lock). Don't use in code. 343 350 */ 344 - void msi_lock_descs(struct device *dev) 351 + void __msi_lock_descs(struct device *dev) 345 352 { 346 353 mutex_lock(&dev->msi.data->mutex); 347 354 } 348 - EXPORT_SYMBOL_GPL(msi_lock_descs); 355 + EXPORT_SYMBOL_GPL(__msi_lock_descs); 349 356 350 357 /** 351 - * msi_unlock_descs - Unlock the MSI descriptor storage of a device 358 + * __msi_unlock_descs - Unlock the MSI descriptor storage of a device 352 359 * @dev: Device to operate on 360 + * 361 + * Internal function for guard(msi_descs_lock). Don't use in code. 353 362 */ 354 - void msi_unlock_descs(struct device *dev) 363 + void __msi_unlock_descs(struct device *dev) 355 364 { 356 365 /* Invalidate the index which was cached by the iterator */ 357 366 dev->msi.data->__iter_idx = MSI_XA_MAX_INDEX; 358 367 mutex_unlock(&dev->msi.data->mutex); 359 368 } 360 - EXPORT_SYMBOL_GPL(msi_unlock_descs); 369 + EXPORT_SYMBOL_GPL(__msi_unlock_descs); 361 370 362 371 static struct msi_desc *msi_find_desc(struct msi_device_data *md, unsigned int domid, 363 372 enum msi_desc_filter filter) ··· 447 448 unsigned int msi_domain_get_virq(struct device *dev, unsigned int domid, unsigned int index) 448 449 { 449 450 struct msi_desc *desc; 450 - unsigned int ret = 0; 451 451 bool pcimsi = false; 452 452 struct xarray *xa; 453 453 ··· 460 462 if (dev_is_pci(dev) && domid == MSI_DEFAULT_DOMAIN) 461 463 pcimsi = to_pci_dev(dev)->msi_enabled; 462 464 463 - msi_lock_descs(dev); 465 + guard(msi_descs_lock)(dev); 464 466 xa = &dev->msi.data->__domains[domid].store; 465 467 desc = xa_load(xa, pcimsi ? 0 : index); 466 468 if (desc && desc->irq) { ··· 469 471 * PCI-MSIX and platform MSI use a descriptor per 470 472 * interrupt. 471 473 */ 472 - if (pcimsi) { 473 - if (index < desc->nvec_used) 474 - ret = desc->irq + index; 475 - } else { 476 - ret = desc->irq; 477 - } 474 + if (!pcimsi) 475 + return desc->irq; 476 + if (index < desc->nvec_used) 477 + return desc->irq + index; 478 478 } 479 - 480 - msi_unlock_descs(dev); 481 - return ret; 479 + return 0; 482 480 } 483 481 EXPORT_SYMBOL_GPL(msi_domain_get_virq); 484 482 ··· 992 998 void *chip_data) 993 999 { 994 1000 struct irq_domain *domain, *parent = dev->msi.domain; 995 - struct fwnode_handle *fwnode, *fwnalloced = NULL; 996 - struct msi_domain_template *bundle; 997 1001 const struct msi_parent_ops *pops; 1002 + struct fwnode_handle *fwnode; 998 1003 999 1004 if (!irq_domain_is_msi_parent(parent)) 1000 1005 return false; ··· 1001 1008 if (domid >= MSI_MAX_DEVICE_IRQDOMAINS) 1002 1009 return false; 1003 1010 1004 - bundle = kmemdup(template, sizeof(*bundle), GFP_KERNEL); 1011 + struct msi_domain_template *bundle __free(kfree) = 1012 + bundle = kmemdup(template, sizeof(*bundle), GFP_KERNEL); 1005 1013 if (!bundle) 1006 1014 return false; 1007 1015 ··· 1025 1031 * node as they are not guaranteed to have a fwnode. They are never 1026 1032 * looked up and always handled in the context of the device. 1027 1033 */ 1028 - if (bundle->info.flags & MSI_FLAG_USE_DEV_FWNODE) 1029 - fwnode = dev->fwnode; 1034 + struct fwnode_handle *fwnode_alloced __free(irq_domain_free_fwnode) = NULL; 1035 + 1036 + if (!(bundle->info.flags & MSI_FLAG_USE_DEV_FWNODE)) 1037 + fwnode = fwnode_alloced = irq_domain_alloc_named_fwnode(bundle->name); 1030 1038 else 1031 - fwnode = fwnalloced = irq_domain_alloc_named_fwnode(bundle->name); 1039 + fwnode = dev->fwnode; 1032 1040 1033 1041 if (!fwnode) 1034 - goto free_bundle; 1042 + return false; 1035 1043 1036 1044 if (msi_setup_device_data(dev)) 1037 - goto free_fwnode; 1045 + return false; 1038 1046 1039 - msi_lock_descs(dev); 1040 - 1047 + guard(msi_descs_lock)(dev); 1041 1048 if (WARN_ON_ONCE(msi_get_device_domain(dev, domid))) 1042 - goto fail; 1049 + return false; 1043 1050 1044 1051 if (!pops->init_dev_msi_info(dev, parent, parent, &bundle->info)) 1045 - goto fail; 1052 + return false; 1046 1053 1047 1054 domain = __msi_create_irq_domain(fwnode, &bundle->info, IRQ_DOMAIN_FLAG_MSI_DEVICE, parent); 1048 1055 if (!domain) 1049 - goto fail; 1056 + return false; 1050 1057 1058 + /* @bundle and @fwnode_alloced are now in use. Prevent cleanup */ 1059 + retain_ptr(bundle); 1060 + retain_ptr(fwnode_alloced); 1051 1061 domain->dev = dev; 1052 1062 dev->msi.data->__domains[domid].domain = domain; 1053 - msi_unlock_descs(dev); 1054 1063 return true; 1055 - 1056 - fail: 1057 - msi_unlock_descs(dev); 1058 - free_fwnode: 1059 - irq_domain_free_fwnode(fwnalloced); 1060 - free_bundle: 1061 - kfree(bundle); 1062 - return false; 1063 1064 } 1064 1065 1065 1066 /** ··· 1068 1079 struct msi_domain_info *info; 1069 1080 struct irq_domain *domain; 1070 1081 1071 - msi_lock_descs(dev); 1072 - 1082 + guard(msi_descs_lock)(dev); 1073 1083 domain = msi_get_device_domain(dev, domid); 1074 - 1075 1084 if (!domain || !irq_domain_is_msi_device(domain)) 1076 - goto unlock; 1085 + return; 1077 1086 1078 1087 dev->msi.data->__domains[domid].domain = NULL; 1079 1088 info = domain->host_data; ··· 1080 1093 irq_domain_remove(domain); 1081 1094 irq_domain_free_fwnode(fwnode); 1082 1095 kfree(container_of(info, struct msi_domain_template, info)); 1083 - 1084 - unlock: 1085 - msi_unlock_descs(dev); 1086 1096 } 1087 1097 1088 1098 /** ··· 1095 1111 { 1096 1112 struct msi_domain_info *info; 1097 1113 struct irq_domain *domain; 1098 - bool ret = false; 1099 1114 1100 - msi_lock_descs(dev); 1115 + guard(msi_descs_lock)(dev); 1101 1116 domain = msi_get_device_domain(dev, domid); 1102 1117 if (domain && irq_domain_is_msi_device(domain)) { 1103 1118 info = domain->host_data; 1104 - ret = info->bus_token == bus_token; 1119 + return info->bus_token == bus_token; 1105 1120 } 1106 - msi_unlock_descs(dev); 1107 - return ret; 1121 + return false; 1108 1122 } 1109 1123 1110 1124 static int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev, ··· 1334 1352 } 1335 1353 1336 1354 /** 1337 - * msi_domain_alloc_irqs_range_locked - Allocate interrupts from a MSI interrupt domain 1338 - * @dev: Pointer to device struct of the device for which the interrupts 1339 - * are allocated 1340 - * @domid: Id of the interrupt domain to operate on 1341 - * @first: First index to allocate (inclusive) 1342 - * @last: Last index to allocate (inclusive) 1343 - * 1344 - * Must be invoked from within a msi_lock_descs() / msi_unlock_descs() 1345 - * pair. Use this for MSI irqdomains which implement their own descriptor 1346 - * allocation/free. 1347 - * 1348 - * Return: %0 on success or an error code. 1349 - */ 1350 - int msi_domain_alloc_irqs_range_locked(struct device *dev, unsigned int domid, 1351 - unsigned int first, unsigned int last) 1352 - { 1353 - struct msi_ctrl ctrl = { 1354 - .domid = domid, 1355 - .first = first, 1356 - .last = last, 1357 - .nirqs = last + 1 - first, 1358 - }; 1359 - 1360 - return msi_domain_alloc_locked(dev, &ctrl); 1361 - } 1362 - 1363 - /** 1364 1355 * msi_domain_alloc_irqs_range - Allocate interrupts from a MSI interrupt domain 1365 1356 * @dev: Pointer to device struct of the device for which the interrupts 1366 1357 * are allocated ··· 1346 1391 int msi_domain_alloc_irqs_range(struct device *dev, unsigned int domid, 1347 1392 unsigned int first, unsigned int last) 1348 1393 { 1349 - int ret; 1394 + struct msi_ctrl ctrl = { 1395 + .domid = domid, 1396 + .first = first, 1397 + .last = last, 1398 + .nirqs = last + 1 - first, 1399 + }; 1350 1400 1351 - msi_lock_descs(dev); 1352 - ret = msi_domain_alloc_irqs_range_locked(dev, domid, first, last); 1353 - msi_unlock_descs(dev); 1354 - return ret; 1401 + guard(msi_descs_lock)(dev); 1402 + return msi_domain_alloc_locked(dev, &ctrl); 1355 1403 } 1356 1404 EXPORT_SYMBOL_GPL(msi_domain_alloc_irqs_range); 1357 1405 ··· 1458 1500 const struct irq_affinity_desc *affdesc, 1459 1501 union msi_instance_cookie *icookie) 1460 1502 { 1461 - struct msi_map map; 1462 - 1463 - msi_lock_descs(dev); 1464 - map = __msi_domain_alloc_irq_at(dev, domid, index, affdesc, icookie); 1465 - msi_unlock_descs(dev); 1466 - return map; 1503 + guard(msi_descs_lock)(dev); 1504 + return __msi_domain_alloc_irq_at(dev, domid, index, affdesc, icookie); 1467 1505 } 1468 1506 1469 1507 /** ··· 1496 1542 1497 1543 icookie.value = ((u64)type << 32) | hwirq; 1498 1544 1499 - msi_lock_descs(dev); 1545 + guard(msi_descs_lock)(dev); 1500 1546 if (WARN_ON_ONCE(msi_get_device_domain(dev, domid) != domain)) 1501 1547 map.index = -EINVAL; 1502 1548 else 1503 1549 map = __msi_domain_alloc_irq_at(dev, domid, MSI_ANY_INDEX, NULL, &icookie); 1504 - msi_unlock_descs(dev); 1505 - 1506 1550 return map.index >= 0 ? map.virq : map.index; 1507 1551 } 1508 1552 ··· 1570 1618 * @first: First index to free (inclusive) 1571 1619 * @last: Last index to free (inclusive) 1572 1620 */ 1573 - void msi_domain_free_irqs_range_locked(struct device *dev, unsigned int domid, 1574 - unsigned int first, unsigned int last) 1621 + static void msi_domain_free_irqs_range_locked(struct device *dev, unsigned int domid, 1622 + unsigned int first, unsigned int last) 1575 1623 { 1576 1624 struct msi_ctrl ctrl = { 1577 1625 .domid = domid, ··· 1593 1641 void msi_domain_free_irqs_range(struct device *dev, unsigned int domid, 1594 1642 unsigned int first, unsigned int last) 1595 1643 { 1596 - msi_lock_descs(dev); 1644 + guard(msi_descs_lock)(dev); 1597 1645 msi_domain_free_irqs_range_locked(dev, domid, first, last); 1598 - msi_unlock_descs(dev); 1599 1646 } 1600 1647 EXPORT_SYMBOL_GPL(msi_domain_free_irqs_all); 1601 1648 ··· 1624 1673 */ 1625 1674 void msi_domain_free_irqs_all(struct device *dev, unsigned int domid) 1626 1675 { 1627 - msi_lock_descs(dev); 1676 + guard(msi_descs_lock)(dev); 1628 1677 msi_domain_free_irqs_all_locked(dev, domid); 1629 - msi_unlock_descs(dev); 1630 1678 } 1631 1679 1632 1680 /** ··· 1644 1694 if (WARN_ON_ONCE(!dev || !desc || domain->bus_token != DOMAIN_BUS_WIRED_TO_MSI)) 1645 1695 return; 1646 1696 1647 - msi_lock_descs(dev); 1648 - if (!WARN_ON_ONCE(msi_get_device_domain(dev, MSI_DEFAULT_DOMAIN) != domain)) { 1649 - msi_domain_free_irqs_range_locked(dev, MSI_DEFAULT_DOMAIN, desc->msi_index, 1650 - desc->msi_index); 1651 - } 1652 - msi_unlock_descs(dev); 1697 + guard(msi_descs_lock)(dev); 1698 + if (WARN_ON_ONCE(msi_get_device_domain(dev, MSI_DEFAULT_DOMAIN) != domain)) 1699 + return; 1700 + msi_domain_free_irqs_range_locked(dev, MSI_DEFAULT_DOMAIN, desc->msi_index, 1701 + desc->msi_index); 1653 1702 } 1654 1703 1655 1704 /**