diff mbox series

[SRU,F,1/1] s390/pci: fix leak of DMA tables on hard unplug

Message ID 20200921144343.724633-2-frank.heimes@canonical.com
State New
Headers show
Series zPCI DMA tables and bitmap leak on hard unplug (PCI Event 0x0304) (LP: 1896216) | expand

Commit Message

Frank Heimes Sept. 21, 2020, 2:43 p.m. UTC
From: Niklas Schnelle <schnelle@linux.ibm.com>

BugLink: https://bugs.launchpad.net/bugs/1896216

commit f606b3ef47c9 ("s390/pci: adapt events for zbus") removed the
zpci_disable_device() call for a zPCI event with PEC 0x0304 because
the device is already deconfigured by the platform.
This however skips the Linux side of the disable in particular it leads
to leaking the DMA tables and bitmaps because zpci_dma_exit_device() is
never called on the device.

If the device transitions to the Reserved state we call zpci_zdev_put()
but zpci_release_device() will not call zpci_disable_device() because
the state of the zPCI function is already ZPCI_FN_STATE_STANDBY.

If the device is put into the Standby state, zpci_disable_device() is
not called and the device is assumed to have been put in Standby through
platform action.
At this point the device may be removed by a subsequent event with PEC
0x0308 or 0x0306 which calls zpci_zdev_put() with the same problem
as above or the device may be configured again in which case
zpci_disable_device() is also not called.

Fix this by calling zpci_disable_device() explicitly for PEC 0x0304 as
before. To make it more clear that zpci_disable_device() may be called,
even if the lower level device has already been disabled by the
platform, add a comment to zpci_disable_device().

Cc: <stable@vger.kernel.org> # 5.8
Fixes: f606b3ef47c9 ("s390/pci: adapt events for zbus")
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
(cherry picked from commit afdf9550e54627fcf4dd609bdc1153059378cdf5 linux-next)
Signed-off-by: Frank Heimes <frank.heimes@canonical.com>
---
 arch/s390/pci/pci.c       | 4 ++++
 arch/s390/pci/pci_event.c | 2 ++
 2 files changed, 6 insertions(+)

Comments

Stefan Bader Sept. 23, 2020, 1:23 p.m. UTC | #1
On 21.09.20 16:43, frank.heimes@canonical.com wrote:
> From: Niklas Schnelle <schnelle@linux.ibm.com>
> 
> BugLink: https://bugs.launchpad.net/bugs/1896216
> 
> commit f606b3ef47c9 ("s390/pci: adapt events for zbus") removed the
> zpci_disable_device() call for a zPCI event with PEC 0x0304 because
> the device is already deconfigured by the platform.
> This however skips the Linux side of the disable in particular it leads
> to leaking the DMA tables and bitmaps because zpci_dma_exit_device() is
> never called on the device.
> 
> If the device transitions to the Reserved state we call zpci_zdev_put()
> but zpci_release_device() will not call zpci_disable_device() because
> the state of the zPCI function is already ZPCI_FN_STATE_STANDBY.
> 
> If the device is put into the Standby state, zpci_disable_device() is
> not called and the device is assumed to have been put in Standby through
> platform action.
> At this point the device may be removed by a subsequent event with PEC
> 0x0308 or 0x0306 which calls zpci_zdev_put() with the same problem
> as above or the device may be configured again in which case
> zpci_disable_device() is also not called.
> 
> Fix this by calling zpci_disable_device() explicitly for PEC 0x0304 as
> before. To make it more clear that zpci_disable_device() may be called,
> even if the lower level device has already been disabled by the
> platform, add a comment to zpci_disable_device().
> 
> Cc: <stable@vger.kernel.org> # 5.8
> Fixes: f606b3ef47c9 ("s390/pci: adapt events for zbus")
> Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
> (cherry picked from commit afdf9550e54627fcf4dd609bdc1153059378cdf5 linux-next)
> Signed-off-by: Frank Heimes <frank.heimes@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
> ---
>  arch/s390/pci/pci.c       | 4 ++++
>  arch/s390/pci/pci_event.c | 2 ++
>  2 files changed, 6 insertions(+)
> 
> diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
> index fb25665ec44b..f3a477f919d0 100644
> --- a/arch/s390/pci/pci.c
> +++ b/arch/s390/pci/pci.c
> @@ -709,6 +709,10 @@ EXPORT_SYMBOL_GPL(zpci_enable_device);
>  int zpci_disable_device(struct zpci_dev *zdev)
>  {
>  	zpci_dma_exit_device(zdev);
> +	/*
> +	 * The zPCI function may already be disabled by the platform, this is
> +	 * detected in clp_disable_fh() which becomes a no-op.
> +	 */
>  	return clp_disable_fh(zdev);
>  }
>  EXPORT_SYMBOL_GPL(zpci_disable_device);
> diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
> index 9a3a291cad43..d9ae7456dd4c 100644
> --- a/arch/s390/pci/pci_event.c
> +++ b/arch/s390/pci/pci_event.c
> @@ -143,6 +143,8 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
>  			zpci_remove_device(zdev);
>  		}
>  
> +		zdev->fh = ccdf->fh;
> +		zpci_disable_device(zdev);
>  		zdev->state = ZPCI_FN_STATE_STANDBY;
>  		if (!clp_get_state(ccdf->fid, &state) &&
>  		    state == ZPCI_FN_STATE_RESERVED) {
>
Ian May Oct. 2, 2020, 10:22 p.m. UTC | #2
Applied to Focal/master-next.  Thanks!

Ian

On 2020-09-21 16:43:43 , frank.heimes@canonical.com wrote:
> From: Niklas Schnelle <schnelle@linux.ibm.com>
> 
> BugLink: https://bugs.launchpad.net/bugs/1896216
> 
> commit f606b3ef47c9 ("s390/pci: adapt events for zbus") removed the
> zpci_disable_device() call for a zPCI event with PEC 0x0304 because
> the device is already deconfigured by the platform.
> This however skips the Linux side of the disable in particular it leads
> to leaking the DMA tables and bitmaps because zpci_dma_exit_device() is
> never called on the device.
> 
> If the device transitions to the Reserved state we call zpci_zdev_put()
> but zpci_release_device() will not call zpci_disable_device() because
> the state of the zPCI function is already ZPCI_FN_STATE_STANDBY.
> 
> If the device is put into the Standby state, zpci_disable_device() is
> not called and the device is assumed to have been put in Standby through
> platform action.
> At this point the device may be removed by a subsequent event with PEC
> 0x0308 or 0x0306 which calls zpci_zdev_put() with the same problem
> as above or the device may be configured again in which case
> zpci_disable_device() is also not called.
> 
> Fix this by calling zpci_disable_device() explicitly for PEC 0x0304 as
> before. To make it more clear that zpci_disable_device() may be called,
> even if the lower level device has already been disabled by the
> platform, add a comment to zpci_disable_device().
> 
> Cc: <stable@vger.kernel.org> # 5.8
> Fixes: f606b3ef47c9 ("s390/pci: adapt events for zbus")
> Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
> (cherry picked from commit afdf9550e54627fcf4dd609bdc1153059378cdf5 linux-next)
> Signed-off-by: Frank Heimes <frank.heimes@canonical.com>
> ---
>  arch/s390/pci/pci.c       | 4 ++++
>  arch/s390/pci/pci_event.c | 2 ++
>  2 files changed, 6 insertions(+)
> 
> diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
> index fb25665ec44b..f3a477f919d0 100644
> --- a/arch/s390/pci/pci.c
> +++ b/arch/s390/pci/pci.c
> @@ -709,6 +709,10 @@ EXPORT_SYMBOL_GPL(zpci_enable_device);
>  int zpci_disable_device(struct zpci_dev *zdev)
>  {
>  	zpci_dma_exit_device(zdev);
> +	/*
> +	 * The zPCI function may already be disabled by the platform, this is
> +	 * detected in clp_disable_fh() which becomes a no-op.
> +	 */
>  	return clp_disable_fh(zdev);
>  }
>  EXPORT_SYMBOL_GPL(zpci_disable_device);
> diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
> index 9a3a291cad43..d9ae7456dd4c 100644
> --- a/arch/s390/pci/pci_event.c
> +++ b/arch/s390/pci/pci_event.c
> @@ -143,6 +143,8 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
>  			zpci_remove_device(zdev);
>  		}
>  
> +		zdev->fh = ccdf->fh;
> +		zpci_disable_device(zdev);
>  		zdev->state = ZPCI_FN_STATE_STANDBY;
>  		if (!clp_get_state(ccdf->fid, &state) &&
>  		    state == ZPCI_FN_STATE_RESERVED) {
> -- 
> 2.25.1
> 
> 
> -- 
> kernel-team mailing list
> kernel-team@lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team
diff mbox series

Patch

diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index fb25665ec44b..f3a477f919d0 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -709,6 +709,10 @@  EXPORT_SYMBOL_GPL(zpci_enable_device);
 int zpci_disable_device(struct zpci_dev *zdev)
 {
 	zpci_dma_exit_device(zdev);
+	/*
+	 * The zPCI function may already be disabled by the platform, this is
+	 * detected in clp_disable_fh() which becomes a no-op.
+	 */
 	return clp_disable_fh(zdev);
 }
 EXPORT_SYMBOL_GPL(zpci_disable_device);
diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
index 9a3a291cad43..d9ae7456dd4c 100644
--- a/arch/s390/pci/pci_event.c
+++ b/arch/s390/pci/pci_event.c
@@ -143,6 +143,8 @@  static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
 			zpci_remove_device(zdev);
 		}
 
+		zdev->fh = ccdf->fh;
+		zpci_disable_device(zdev);
 		zdev->state = ZPCI_FN_STATE_STANDBY;
 		if (!clp_get_state(ccdf->fid, &state) &&
 		    state == ZPCI_FN_STATE_RESERVED) {