pdsc_stop() masks interrupts but does not disable bus mastering, leaving the device able to perform DMA after the function returns. This can lead to use-after-free if DMA buffers are freed while the device is still accessing them. Add pci_clear_master() to pdsc_stop() to disable bus mastering after masking interrupts, ensuring all DMA is quiesced before teardown proceeds. Add the corresponding pci_set_master() to pdsc_start() to re-enable bus mastering when the device is brought back up, such as during recovery. Fixes: 01ba61b55b20 ("pds_core: Add adminq processing and commands") Signed-off-by: Nikhil P. Rao --- drivers/net/ethernet/amd/pds_core/core.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c index 705cab7b0727..27369b3297b2 100644 --- a/drivers/net/ethernet/amd/pds_core/core.c +++ b/drivers/net/ethernet/amd/pds_core/core.c @@ -494,6 +494,7 @@ void pdsc_teardown(struct pdsc *pdsc, bool removing) int pdsc_start(struct pdsc *pdsc) { + pci_set_master(pdsc->pdev); pds_core_intr_mask(&pdsc->intr_ctrl[pdsc->adminqcq.intx], PDS_CORE_INTR_MASK_CLEAR); @@ -504,14 +505,15 @@ void pdsc_stop(struct pdsc *pdsc) { int i; - if (!pdsc->intr_info) - return; - /* Mask interrupts that are in use */ - for (i = 0; i < pdsc->nintrs; i++) - if (pdsc->intr_info[i].vector) - pds_core_intr_mask(&pdsc->intr_ctrl[i], - PDS_CORE_INTR_MASK_SET); + if (pdsc->intr_info) { + for (i = 0; i < pdsc->nintrs; i++) + if (pdsc->intr_info[i].vector) + pds_core_intr_mask(&pdsc->intr_ctrl[i], + PDS_CORE_INTR_MASK_SET); + } + + pci_clear_master(pdsc->pdev); } static void pdsc_adminq_wait_and_dec_once_unused(struct pdsc *pdsc) -- 2.43.0