diff --git a/components/drivers/include/drivers/pci_msi.h b/components/drivers/include/drivers/pci_msi.h index b8238e6470..4fe03ca07a 100644 --- a/components/drivers/include/drivers/pci_msi.h +++ b/components/drivers/include/drivers/pci_msi.h @@ -177,6 +177,7 @@ struct rt_pci_msi_desc #define rt_pci_msix_table_size(flags) ((flags & PCIM_MSIXCTRL_TABLE_SIZE) + 1) rt_err_t rt_pci_msi_setup_irqs(struct rt_pci_device *pdev, int nvec, int type); +rt_err_t rt_pci_msi_cleanup_irqs(struct rt_pci_device *pdev); void rt_pci_msi_shutdown(struct rt_pci_device *pdev); void rt_pci_msix_shutdown(struct rt_pci_device *pdev); diff --git a/components/drivers/pci/msi/irq.c b/components/drivers/pci/msi/irq.c index dab8ee257a..8e3b7333e0 100644 --- a/components/drivers/pci/msi/irq.c +++ b/components/drivers/pci/msi/irq.c @@ -144,3 +144,42 @@ rt_err_t rt_pci_msi_setup_irqs(struct rt_pci_device *pdev, int nvec, int type) return err; } + +rt_err_t rt_pci_msi_cleanup_irqs(struct rt_pci_device *pdev) +{ + int type; + struct rt_pic *msi_pic; + struct rt_pci_msi_desc *desc; + + if (!pdev) + { + return -RT_EINVAL; + } + + msi_pic = pdev->msi_pic; + + if (!msi_pic) + { + return -RT_EINVAL; + } + + desc = rt_pci_msi_first_desc(pdev); + type = desc->is_msix ? PCIY_MSIX : PCIY_MSI; + + if (type == PCIY_MSI) + { + for (int idx = 0; idx < desc->vector_used; ++idx) + { + msi_pic->ops->irq_free_msi(msi_pic, desc->irq + idx); + } + } + else if (type == PCIY_MSIX) + { + rt_pci_msi_for_each_desc(pdev, desc) + { + msi_pic->ops->irq_free_msi(msi_pic, desc->irq); + } + } + + return RT_EOK; +} diff --git a/components/drivers/pci/msi/msi.c b/components/drivers/pci/msi/msi.c index eb0d578ed3..11ccdcb10c 100644 --- a/components/drivers/pci/msi/msi.c +++ b/components/drivers/pci/msi/msi.c @@ -233,6 +233,8 @@ void rt_pci_msi_free_irqs(struct rt_pci_device *pdev) pdev->msix_base = RT_NULL; } + rt_pci_msi_cleanup_irqs(pdev); + rt_pci_msi_for_each_desc(pdev, desc) { /* To safety */