|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v5 09/10] vpci/msi: Free MSI resources when init_msi() fails
When init_msi() fails, current logic return fail and free MSI-related
resources in vpci_deassign_device(). But the previous new changes will
hide MSI capability and return success, it can't reach
vpci_deassign_device() to remove resources if hiding success, so those
resources must be removed in cleanup function of MSI.
To do that, implement cleanup function for MSI.
Signed-off-by: Jiqian Chen <Jiqian.Chen@xxxxxxx>
---
cc: "Roger Pau Monné" <roger.pau@xxxxxxxxxx>
---
v4->v5 changes:
* Change definition "static void cleanup_msi" to "static int cf_check
cleanup_msi" since cleanup hook is changed to be int.
* Add a read-only register for MSI Control Register in the end of cleanup_msi.
v3->v4 changes:
* Change function name from fini_msi() to cleanup_msi().
* Remove unnecessary comment.
* Change to use XFREE to free vpci->msi.
v2->v3 changes:
* Remove all fail path, and use fini_msi() hook instead.
* Change the method to calculating the size of msi registers.
v1->v2 changes:
* Added a new function fini_msi to free all MSI resources instead of using an
array to record registered registers.
Best regards,
Jiqian Chen.
---
xen/drivers/vpci/msi.c | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/xen/drivers/vpci/msi.c b/xen/drivers/vpci/msi.c
index 2d45c7867de7..4e106c39efae 100644
--- a/xen/drivers/vpci/msi.c
+++ b/xen/drivers/vpci/msi.c
@@ -193,6 +193,33 @@ static void cf_check mask_write(
msi->mask = val;
}
+static int cf_check cleanup_msi(struct pci_dev *pdev)
+{
+ int rc;
+ unsigned int end, size;
+ struct vpci *vpci = pdev->vpci;
+ const unsigned int msi_pos = pdev->msi_pos;
+ const unsigned int ctrl = msi_control_reg(msi_pos);
+
+ if ( !msi_pos || !vpci->msi )
+ return 0;
+
+ if ( vpci->msi->masking )
+ end = msi_pending_bits_reg(msi_pos, vpci->msi->address64);
+ else
+ end = msi_mask_bits_reg(msi_pos, vpci->msi->address64) - 2;
+
+ size = end - ctrl;
+
+ rc = vpci_remove_registers(vpci, ctrl, size);
+ if ( rc )
+ return rc;
+
+ XFREE(vpci->msi);
+
+ return vpci_add_register(pdev->vpci, vpci_hw_read16, NULL, ctrl, 2, NULL);
+}
+
static int cf_check init_msi(struct pci_dev *pdev)
{
unsigned int pos = pdev->msi_pos;
@@ -270,7 +297,7 @@ static int cf_check init_msi(struct pci_dev *pdev)
return 0;
}
-REGISTER_VPCI_CAP(PCI_CAP_ID_MSI, init_msi, NULL);
+REGISTER_VPCI_CAP(PCI_CAP_ID_MSI, init_msi, cleanup_msi);
void vpci_dump_msi(void)
{
--
2.34.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |