summaryrefslogtreecommitdiff
path: root/arch/s390/pci
diff options
context:
space:
mode:
authorNiklas Schnelle <schnelle@linux.ibm.com>2021-03-24 11:21:21 +0100
committerHeiko Carstens <hca@linux.ibm.com>2021-03-28 20:23:54 +0200
commit652d40b2f8bec14957295f999e3d329c3b53390f (patch)
treeaa52eaa90ff9467f375b61934a7c16aa81d8d16f /arch/s390/pci
parent263df6e485445aff8f6189c1913b916b8c7f4f1d (diff)
s390/pci: fix DMA cleanup on hard deconfigure
In commit dee60c0dbc83 ("s390/pci: add zpci_event_hard_deconfigured()") we added a zdev_enabled() check to what was previously an uncoditional call to zpci_disable_device(). There are two problems with that. Firstly zpci_had_deconfigured() is only called on event 0x0304 for which the device is always already disabled by the platform so it is always false. Secondly zpci_disable_device() not only disables the device but also calls zpci_dma_exit_device() which is thus not called and we leak the DMA tables. Fix this by calling zpci_disable_device() unconditionally to perform Linux side cleanup including the freeing of DMA tables. Fixes: dee60c0dbc83 ("s390/pci: add zpci_event_hard_deconfigured()") Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com> Acked-by: Pierre Morel <pmorel@linux.ibm.com> Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Diffstat (limited to 'arch/s390/pci')
-rw-r--r--arch/s390/pci/pci_event.c11
1 files changed, 5 insertions, 6 deletions
diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
index 9455c5be8820..ae3054d85491 100644
--- a/arch/s390/pci/pci_event.c
+++ b/arch/s390/pci/pci_event.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <asm/pci_debug.h>
+#include <asm/pci_dma.h>
#include <asm/sclp.h>
#include "pci_bus.h"
@@ -76,18 +77,16 @@ void zpci_event_error(void *data)
static void zpci_event_hard_deconfigured(struct zpci_dev *zdev, u32 fh)
{
enum zpci_state state;
- int rc;
zdev->fh = fh;
/* Give the driver a hint that the function is
* already unusable.
*/
zpci_bus_remove_device(zdev, true);
- if (zdev_enabled(zdev)) {
- rc = zpci_disable_device(zdev);
- if (rc)
- return;
- }
+ /* Even though the device is already gone we still
+ * need to free zPCI resources as part of the disable.
+ */
+ zpci_disable_device(zdev);
zdev->state = ZPCI_FN_STATE_STANDBY;
if (!clp_get_state(zdev->fid, &state) &&
state == ZPCI_FN_STATE_RESERVED) {