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 |
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) { >
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 --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) {