FAILED: patch "[PATCH] s390/pci: fix zpci_zdev_put() on reserve" failed to apply to 5.14-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 5.14-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From a46044a92add6a400f4dada7b943b30221f7cc80 Mon Sep 17 00:00:00 2001
From: Niklas Schnelle <[email protected]>
Date: Wed, 22 Sep 2021 15:55:12 +0200
Subject: [PATCH] s390/pci: fix zpci_zdev_put() on reserve
Since commit 2a671f77ee49 ("s390/pci: fix use after free of zpci_dev") the reference count of a zpci_dev is incremented between pcibios_add_device() and pcibios_release_device() which was supposed to prevent the zpci_dev from being freed while the common PCI code has access to it. It was missed however that the handling of zPCI availability events assumed that once zpci_zdev_put() was called no later availability event would still see the device. With the previously mentioned commit however this assumption no longer holds and we must make sure that we only drop the initial long-lived reference the zPCI subsystem holds exactly once.
Do so by introducing a zpci_device_reserved() function that handles when a device is reserved. Here we make sure the zpci_dev will not be considered for further events by removing it from the zpci_list.
This also means that the device actually stays in the ZPCI_FN_STATE_RESERVED state between the time we know it has been reserved and the final reference going away. We thus need to consider it a real state instead of just a conceptual state after the removal. The final cleanup of PCI resources, removal from zbus, and destruction of the IOMMU stays in zpci_release_device() to make sure holders of the reference do see valid data until the release.
arch/s390/include/asm/pci.h +2 -0
@@ -207,6 +207,8 @@ int zpci_enable_device(struct zpci_dev *);int zpci_disable_device (struct zpci_dev *);int zpci_scan_configured_device (struct zpci_dev *zdev,u32 fh);int zpci_deconfigure_device (struct zpci_dev *zdev); +void zpci_device_reserved (struct zpci_dev *zdev); +bool zpci_is_device_configured (struct zpci_dev *zdev);int zpci_register_ioat (struct zpci_dev *,u8 ,u64 ,u64 ,u64 );int zpci_unregister_ioat (struct zpci_dev *,u8 );
arch/s390/pci/pci.c +40 -5
75 lines not on this page · raw message
arch/s390/pci/pci_event.c +2 -2
@@ -140,7 +140,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)/* The 0x0304 event may immediately reserve the device */ if (!clp_get_state (zdev->fid, &state) && state ==ZPCI_FN_STATE_RESERVED ) { -zpci_zdev_put (zdev); +zpci_device_reserved (zdev); } }break ;
@@ -151,7 +151,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)case 0x0308 :/* Standby -> Reserved */ if (!zdev)break ; -zpci_zdev_put (zdev); +zpci_device_reserved (zdev);break ;default :break ;
drivers/pci/hotplug/s390_pci_hpc.c +1 -8
@@ -62,14 +62,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) struct zpci_dev *zdev = container_of(hotplug_slot, struct zpci_dev, hotplug_slot); -switch (zdev->state) { -case ZPCI_FN_STATE_STANDBY : - *value =0 ; -break ; -default : - *value =1 ; -break ; - } + *value =zpci_is_device_configured (zdev) ?1 :0 ;return 0 ; }
Niklas Schnelle
maintainerPATCH 1/1 s390/pci: fix zpci_zdev_put() on reserve
commit a46044a92add6a400f4dada7b943b30221f7cc80 upstream.
Backport note: The original commit conflicted with the upstream commit 023cc3cb1e4b ("s390/pci: cleanup resources only if necessary") instead of separately backporting that its change is subsumed in this backport patch.
Since commit 2a671f77ee49 ("s390/pci: fix use after free of zpci_dev") the reference count of a zpci_dev is incremented between pcibios_add_device() and pcibios_release_device() which was supposed to prevent the zpci_dev from being freed while the common PCI code has access to it. It was missed however that the handling of zPCI availability events assumed that once zpci_zdev_put() was called no later availability event would still see the device. With the previously mentioned commit however this assumption no longer holds and we must make sure that we only drop the initial long-lived reference the zPCI subsystem holds exactly once.
Do so by introducing a zpci_device_reserved() function that handles when a device is reserved. Here we make sure the zpci_dev will not be considered for further events by removing it from the zpci_list.
This also means that the device actually stays in the ZPCI_FN_STATE_RESERVED state between the time we know it has been reserved and the final reference going away. We thus need to consider it a real state instead of just a conceptual state after the removal. The final cleanup of PCI resources, removal from zbus, and destruction of the IOMMU stays in zpci_release_device() to make sure holders of the reference do see valid data until the release.
--- arch/s390/include/asm/pci.h | 2 ++ arch/s390/pci/pci.c | 48 ++++++++++++++++++++++++++---- arch/s390/pci/pci_event.c | 4 +-- drivers/pci/hotplug/s390_pci_hpc.c | 9 +----- 4 files changed, 47 insertions(+), 16 deletions(-)
arch/s390/include/asm/pci.h +2 -0
@@ -207,6 +207,8 @@ int zpci_enable_device(struct zpci_dev *);int zpci_disable_device (struct zpci_dev *);int zpci_scan_configured_device (struct zpci_dev *zdev,u32 fh);int zpci_deconfigure_device (struct zpci_dev *zdev); +void zpci_device_reserved (struct zpci_dev *zdev); +bool zpci_is_device_configured (struct zpci_dev *zdev);int zpci_register_ioat (struct zpci_dev *,u8 ,u64 ,u64 ,u64 );int zpci_unregister_ioat (struct zpci_dev *,u8 );
arch/s390/pci/pci.c +42 -6
78 lines not on this page · raw message
arch/s390/pci/pci_event.c +2 -2
@@ -137,7 +137,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)/* The 0x0304 event may immediately reserve the device */ if (!clp_get_state (zdev->fid, &state) && state ==ZPCI_FN_STATE_RESERVED ) { -zpci_zdev_put (zdev); +zpci_device_reserved (zdev); } }break ;
@@ -148,7 +148,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)case 0x0308 :/* Standby -> Reserved */ if (!zdev)break ; -zpci_zdev_put (zdev); +zpci_device_reserved (zdev);break ;default :break ;
drivers/pci/hotplug/s390_pci_hpc.c +1 -8
@@ -62,14 +62,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) struct zpci_dev *zdev = container_of(hotplug_slot, struct zpci_dev, hotplug_slot); -switch (zdev->state) { -case ZPCI_FN_STATE_STANDBY : - *value =0 ; -break ; -default : - *value =1 ; -break ; - } + *value =zpci_is_device_configured (zdev) ?1 :0 ;return 0 ; }
Signature · 1 line
2.25.1
Greg KH
maintainerRe: [PATCH 5.14 STABLE] s390/pci: fix zpci_zdev_put() on reserve
Quoted 6 lines · Niklas Schnelle
commit
a46044a92add6a400f4dada7b943b30221f7cc80upstream.Backport note: The original commit conflicted with the upstream commit
023cc3cb1e4b("s390/pci: cleanup resources only if necessary") instead of separately backporting that its change is subsumed in this backport patch.
No, please submit the same patches that are upstream, we want to prevent this type of stuff as much as possible.
thanks,
greg k-h