123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2022-10-24 GuEe-GUI first version
- */
- #include <drivers/pci_msi.h>
- #define DBG_TAG "pci.msi.irq"
- #define DBG_LVL DBG_INFO
- #include <rtdbg.h>
- static RT_DEFINE_SPINLOCK(msi_irq_map_lock);
- static RT_BITMAP_DECLARE(msi_irq_map, MAX_HANDLERS) = {};
- rt_err_t rt_pci_msi_setup_irqs(struct rt_pci_device *pdev, int nvec, int type)
- {
- int irq, index = 0, irq_nr = 0;
- rt_err_t err = RT_EOK;
- struct rt_pic_irq *pirq;
- struct rt_pic *msi_pic;
- struct rt_pci_msi_desc *desc;
- if (!pdev)
- {
- return -RT_EINVAL;
- }
- msi_pic = pdev->msi_pic;
- if (type == PCIY_MSI)
- {
- int last_irq = -1, irq_idx;
- rt_size_t irq_nr;
- desc = rt_pci_msi_first_desc(pdev);
- irq_nr = 1 << desc->msi.cap.multi_msg_use;
- rt_hw_spin_lock(&msi_irq_map_lock.lock);
- _retry:
- for (int i = 0; i < irq_nr; ++i)
- {
- if ((irq = msi_pic->ops->irq_alloc_msi(msi_pic, desc)) < 0)
- {
- err = irq;
- LOG_E("Setup %s[%d] IRQ error = %s", "MSI", i, rt_strerror(err));
- break;
- }
- if (last_irq >= 0 && last_irq + 1 != irq)
- {
- for (int idx = 0; idx < i; ++i, --last_irq)
- {
- rt_bitmap_set_bit(msi_irq_map, last_irq);
- }
- last_irq = irq;
- goto _retry;
- }
- last_irq = irq;
- }
- if (!err)
- {
- /* Get the first irq */
- desc->irq = irq - (irq_nr - 1);
- }
- rt_bitmap_for_each_set_bit(msi_irq_map, irq_idx, MAX_HANDLERS)
- {
- msi_pic->ops->irq_free_msi(msi_pic, irq_idx);
- /* Free bit so the next user doesn't need to bzero */
- rt_bitmap_clear_bit(msi_irq_map, irq_idx);
- }
- rt_hw_spin_unlock(&msi_irq_map_lock.lock);
- if (!err)
- {
- for (int idx = 0; idx < nvec; ++idx)
- {
- pirq = rt_pic_find_pirq(msi_pic, irq + idx);
- pirq->msi_desc = desc;
- msi_pic->ops->irq_compose_msi_msg(pirq, &desc->msg);
- rt_pci_msi_write_msg(desc, &desc->msg);
- }
- }
- }
- else if (type == PCIY_MSIX)
- {
- rt_pci_msi_for_each_desc(pdev, desc)
- {
- if ((irq = msi_pic->ops->irq_alloc_msi(msi_pic, desc)) < 0)
- {
- err = irq;
- LOG_E("Setup %s[%d] IRQ error = %s", "MSI-X",
- desc->msix.index, rt_strerror(err));
- break;
- }
- desc->irq = irq;
- pirq = rt_pic_find_pirq(msi_pic, irq);
- pirq->msi_desc = desc;
- msi_pic->ops->irq_compose_msi_msg(pirq, &desc->msg);
- rt_pci_msi_write_msg(desc, &desc->msg);
- ++irq_nr;
- }
- if (err)
- {
- rt_pci_msi_for_each_desc(pdev, desc)
- {
- if (index >= irq_nr)
- {
- break;
- }
- msi_pic->ops->irq_free_msi(msi_pic, desc->irq);
- ++index;
- }
- }
- }
- else
- {
- err = -RT_EINVAL;
- }
- return err;
- }
|