linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] powerpc/sriov: Remove VF eeh_dev state when disabling SR-IOV
@ 2019-08-21  6:26 Oliver O'Halloran
  2019-08-21  6:26 ` [PATCH 2/3] powerpc/pcidn: Make VF pci_dn management CONFIG_PCI_IOV specific Oliver O'Halloran
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Oliver O'Halloran @ 2019-08-21  6:26 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: sbobroff, Oliver O'Halloran

When disabling virtual functions on an SR-IOV adapter we currently do not
correctly remove the EEH state for the now-dead virtual functions. When
removing the pci_dn that was created for the VF when SR-IOV was enabled
we free the corresponding eeh_dev without removing it from the child device
list of the eeh_pe that contained it. This can result in crashes due to the
use-after-free.

Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
No Fixes: here since I'm not sure if the commit that added this actually
introduced the bug. EEH is amazing.

I suspect backporting this would cause more problems than it solves since
reliably replicating the crash required enabling memory poisoning and
hacking a device driver to remove the PCI error handling callbacks so
the EEH fallback path (which removes and re-probes PCI devices)
would be used.
---
 arch/powerpc/kernel/pci_dn.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
index 6556b57..795c4e3 100644
--- a/arch/powerpc/kernel/pci_dn.c
+++ b/arch/powerpc/kernel/pci_dn.c
@@ -244,9 +244,22 @@ void remove_dev_pci_data(struct pci_dev *pdev)
 				continue;
 
 #ifdef CONFIG_EEH
-			/* Release EEH device for the VF */
+			/*
+			 * Release EEH state for this VF. The PCI core
+			 * has already torn down the pci_dev for this VF, but
+			 * we're responsible to removing the eeh_dev since it
+			 * has the same lifetime as the pci_dn that spawned it.
+			 */
 			edev = pdn_to_eeh_dev(pdn);
 			if (edev) {
+				/*
+				 * We allocate pci_dn's for the totalvfs count,
+				 * but only only the vfs that were activated
+				 * have a configured PE.
+				 */
+				if (edev->pe)
+					eeh_rmv_from_parent_pe(edev);
+
 				pdn->edev = NULL;
 				kfree(edev);
 			}
-- 
2.9.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/3] powerpc/pcidn: Make VF pci_dn management CONFIG_PCI_IOV specific
  2019-08-21  6:26 [PATCH 1/3] powerpc/sriov: Remove VF eeh_dev state when disabling SR-IOV Oliver O'Halloran
@ 2019-08-21  6:26 ` Oliver O'Halloran
  2019-08-22  5:59   ` Sam Bobroff
  2019-08-21  6:26 ` [PATCH 3/3] powerpc/pcidn: Warn when sriov pci_dn management is used incorrectly Oliver O'Halloran
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Oliver O'Halloran @ 2019-08-21  6:26 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: sbobroff, Oliver O'Halloran

The powerpc PCI code requires that a pci_dn structure exists for all
devices in the system. This is fine for real devices since at boot a pci_dn
is created for each PCI device in the DT and it's fine for hotplugged devices
since the hotplug slot driver will manage the pci_dn's devices in hotplug
slots. For SR-IOV, we need the platform / pcibios to manage the pci_dn for
virtual functions since firmware is unaware of VFs, and they aren't
"hot plugged" in the traditional sense.

Management of the pci_dn is handled by the, poorly named, functions:
add_pci_dev_data() and remove_pci_dev_data(). The entire body of these
functions is #ifdef`ed around CONFIG_PCI_IOV and they cannot be used
in any other context, so make them only available when CONFIG_PCI_IOV
is selected, and rename them to reflect their actual usage rather than
having them masquerade as generic code.

Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
 arch/powerpc/include/asm/pci-bridge.h     |  7 +++++--
 arch/powerpc/kernel/pci_dn.c              | 15 +++++----------
 arch/powerpc/platforms/powernv/pci-ioda.c |  4 ++--
 arch/powerpc/platforms/pseries/pci.c      |  4 ++--
 4 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
index ea6ec65..69f4cb3 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -223,12 +223,15 @@ struct pci_dn {
 extern struct pci_dn *pci_get_pdn_by_devfn(struct pci_bus *bus,
 					   int devfn);
 extern struct pci_dn *pci_get_pdn(struct pci_dev *pdev);
-extern struct pci_dn *add_dev_pci_data(struct pci_dev *pdev);
-extern void remove_dev_pci_data(struct pci_dev *pdev);
 extern struct pci_dn *pci_add_device_node_info(struct pci_controller *hose,
 					       struct device_node *dn);
 extern void pci_remove_device_node_info(struct device_node *dn);
 
+#ifdef CONFIG_PCI_IOV
+struct pci_dn *add_sriov_vf_pdns(struct pci_dev *pdev);
+void remove_sriov_vf_pdns(struct pci_dev *pdev);
+#endif
+
 static inline int pci_device_from_OF_node(struct device_node *np,
 					  u8 *bus, u8 *devfn)
 {
diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
index 795c4e3..24da1d8 100644
--- a/arch/powerpc/kernel/pci_dn.c
+++ b/arch/powerpc/kernel/pci_dn.c
@@ -125,7 +125,7 @@ struct pci_dn *pci_get_pdn(struct pci_dev *pdev)
 }
 
 #ifdef CONFIG_PCI_IOV
-static struct pci_dn *add_one_dev_pci_data(struct pci_dn *parent,
+static struct pci_dn *add_one_sriov_vf_pdn(struct pci_dn *parent,
 					   int vf_index,
 					   int busno, int devfn)
 {
@@ -151,11 +151,9 @@ static struct pci_dn *add_one_dev_pci_data(struct pci_dn *parent,
 
 	return pdn;
 }
-#endif
 
-struct pci_dn *add_dev_pci_data(struct pci_dev *pdev)
+struct pci_dn *add_sriov_vf_pdns(struct pci_dev *pdev)
 {
-#ifdef CONFIG_PCI_IOV
 	struct pci_dn *parent, *pdn;
 	int i;
 
@@ -176,7 +174,7 @@ struct pci_dn *add_dev_pci_data(struct pci_dev *pdev)
 	for (i = 0; i < pci_sriov_get_totalvfs(pdev); i++) {
 		struct eeh_dev *edev __maybe_unused;
 
-		pdn = add_one_dev_pci_data(parent, i,
+		pdn = add_one_sriov_vf_pdn(parent, i,
 					   pci_iov_virtfn_bus(pdev, i),
 					   pci_iov_virtfn_devfn(pdev, i));
 		if (!pdn) {
@@ -192,14 +190,11 @@ struct pci_dn *add_dev_pci_data(struct pci_dev *pdev)
 		edev->physfn = pdev;
 #endif /* CONFIG_EEH */
 	}
-#endif /* CONFIG_PCI_IOV */
-
 	return pci_get_pdn(pdev);
 }
 
-void remove_dev_pci_data(struct pci_dev *pdev)
+void remove_sriov_vf_pdns(struct pci_dev *pdev)
 {
-#ifdef CONFIG_PCI_IOV
 	struct pci_dn *parent;
 	struct pci_dn *pdn, *tmp;
 	int i;
@@ -271,8 +266,8 @@ void remove_dev_pci_data(struct pci_dev *pdev)
 			kfree(pdn);
 		}
 	}
-#endif /* CONFIG_PCI_IOV */
 }
+#endif /* CONFIG_PCI_IOV */
 
 struct pci_dn *pci_add_device_node_info(struct pci_controller *hose,
 					struct device_node *dn)
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index d8080558d0..f1fa489 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -1719,14 +1719,14 @@ int pnv_pcibios_sriov_disable(struct pci_dev *pdev)
 	pnv_pci_sriov_disable(pdev);
 
 	/* Release PCI data */
-	remove_dev_pci_data(pdev);
+	remove_sriov_vf_pdns(pdev);
 	return 0;
 }
 
 int pnv_pcibios_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
 {
 	/* Allocate PCI data */
-	add_dev_pci_data(pdev);
+	add_sriov_vf_pdns(pdev);
 
 	return pnv_pci_sriov_enable(pdev, num_vfs);
 }
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c
index 7228309..911534b 100644
--- a/arch/powerpc/platforms/pseries/pci.c
+++ b/arch/powerpc/platforms/pseries/pci.c
@@ -192,7 +192,7 @@ int pseries_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
 int pseries_pcibios_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
 {
 	/* Allocate PCI data */
-	add_dev_pci_data(pdev);
+	add_sriov_vf_pdns(pdev);
 	return pseries_pci_sriov_enable(pdev, num_vfs);
 }
 
@@ -204,7 +204,7 @@ int pseries_pcibios_sriov_disable(struct pci_dev *pdev)
 	/* Releasing pe_num_map */
 	kfree(pdn->pe_num_map);
 	/* Release PCI data */
-	remove_dev_pci_data(pdev);
+	remove_sriov_vf_pdns(pdev);
 	pci_vf_drivers_autoprobe(pdev, true);
 	return 0;
 }
-- 
2.9.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/3] powerpc/pcidn: Warn when sriov pci_dn management is used incorrectly
  2019-08-21  6:26 [PATCH 1/3] powerpc/sriov: Remove VF eeh_dev state when disabling SR-IOV Oliver O'Halloran
  2019-08-21  6:26 ` [PATCH 2/3] powerpc/pcidn: Make VF pci_dn management CONFIG_PCI_IOV specific Oliver O'Halloran
@ 2019-08-21  6:26 ` Oliver O'Halloran
  2019-08-22  5:59   ` Sam Bobroff
  2019-08-22  5:49 ` [PATCH 1/3] powerpc/sriov: Remove VF eeh_dev state when disabling SR-IOV Sam Bobroff
  2020-01-29  5:17 ` Michael Ellerman
  3 siblings, 1 reply; 7+ messages in thread
From: Oliver O'Halloran @ 2019-08-21  6:26 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: sbobroff, Oliver O'Halloran

These functions can only be used on a SR-IOV capable physical function and
they're only called in pcibios_sriov_enable / disable. Make them emit a
warning in the future if they're used incorrectly and remove the dead
code that checks if the device is a VF.

Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
 arch/powerpc/kernel/pci_dn.c | 17 +++--------------
 1 file changed, 3 insertions(+), 14 deletions(-)

diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
index 24da1d8..69dafc3 100644
--- a/arch/powerpc/kernel/pci_dn.c
+++ b/arch/powerpc/kernel/pci_dn.c
@@ -158,8 +158,8 @@ struct pci_dn *add_sriov_vf_pdns(struct pci_dev *pdev)
 	int i;
 
 	/* Only support IOV for now */
-	if (!pdev->is_physfn)
-		return pci_get_pdn(pdev);
+	if (WARN_ON(!pdev->is_physfn))
+		return NULL;
 
 	/* Check if VFs have been populated */
 	pdn = pci_get_pdn(pdev);
@@ -199,19 +199,8 @@ void remove_sriov_vf_pdns(struct pci_dev *pdev)
 	struct pci_dn *pdn, *tmp;
 	int i;
 
-	/*
-	 * VF and VF PE are created/released dynamically, so we need to
-	 * bind/unbind them.  Otherwise the VF and VF PE would be mismatched
-	 * when re-enabling SR-IOV.
-	 */
-	if (pdev->is_virtfn) {
-		pdn = pci_get_pdn(pdev);
-		pdn->pe_number = IODA_INVALID_PE;
-		return;
-	}
-
 	/* Only support IOV PF for now */
-	if (!pdev->is_physfn)
+	if (WARN_ON(!pdev->is_physfn))
 		return;
 
 	/* Check if VFs have been populated */
-- 
2.9.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] powerpc/sriov: Remove VF eeh_dev state when disabling SR-IOV
  2019-08-21  6:26 [PATCH 1/3] powerpc/sriov: Remove VF eeh_dev state when disabling SR-IOV Oliver O'Halloran
  2019-08-21  6:26 ` [PATCH 2/3] powerpc/pcidn: Make VF pci_dn management CONFIG_PCI_IOV specific Oliver O'Halloran
  2019-08-21  6:26 ` [PATCH 3/3] powerpc/pcidn: Warn when sriov pci_dn management is used incorrectly Oliver O'Halloran
@ 2019-08-22  5:49 ` Sam Bobroff
  2020-01-29  5:17 ` Michael Ellerman
  3 siblings, 0 replies; 7+ messages in thread
From: Sam Bobroff @ 2019-08-22  5:49 UTC (permalink / raw)
  To: Oliver O'Halloran; +Cc: linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 2389 bytes --]

On Wed, Aug 21, 2019 at 04:26:53PM +1000, Oliver O'Halloran wrote:
> When disabling virtual functions on an SR-IOV adapter we currently do not
> correctly remove the EEH state for the now-dead virtual functions. When
> removing the pci_dn that was created for the VF when SR-IOV was enabled
> we free the corresponding eeh_dev without removing it from the child device
> list of the eeh_pe that contained it. This can result in crashes due to the
> use-after-free.
> 
> Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
> ---
> No Fixes: here since I'm not sure if the commit that added this actually
> introduced the bug. EEH is amazing.

Yep.

> I suspect backporting this would cause more problems than it solves since
> reliably replicating the crash required enabling memory poisoning and
> hacking a device driver to remove the PCI error handling callbacks so
> the EEH fallback path (which removes and re-probes PCI devices)
> would be used.

I gave this a quick test with some added instrumentation, and I can see
that the new code is used during VF removal and it doesn't cause any new
problems. I agree that even if it's difficult to trigger, it was
definitely a bug.

Reviewed-by: Sam Bobroff <sbobroff@linux.ibm.com>
Tested-by: Sam Bobroff <sbobroff@linux.ibm.com>
> ---
>  arch/powerpc/kernel/pci_dn.c | 15 ++++++++++++++-
>  1 file changed, 14 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
> index 6556b57..795c4e3 100644
> --- a/arch/powerpc/kernel/pci_dn.c
> +++ b/arch/powerpc/kernel/pci_dn.c
> @@ -244,9 +244,22 @@ void remove_dev_pci_data(struct pci_dev *pdev)
>  				continue;
>  
>  #ifdef CONFIG_EEH
> -			/* Release EEH device for the VF */
> +			/*
> +			 * Release EEH state for this VF. The PCI core
> +			 * has already torn down the pci_dev for this VF, but
> +			 * we're responsible to removing the eeh_dev since it
> +			 * has the same lifetime as the pci_dn that spawned it.
> +			 */
>  			edev = pdn_to_eeh_dev(pdn);
>  			if (edev) {
> +				/*
> +				 * We allocate pci_dn's for the totalvfs count,
> +				 * but only only the vfs that were activated
> +				 * have a configured PE.
> +				 */
> +				if (edev->pe)
> +					eeh_rmv_from_parent_pe(edev);
> +
>  				pdn->edev = NULL;
>  				kfree(edev);
>  			}
> -- 
> 2.9.5
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 3/3] powerpc/pcidn: Warn when sriov pci_dn management is used incorrectly
  2019-08-21  6:26 ` [PATCH 3/3] powerpc/pcidn: Warn when sriov pci_dn management is used incorrectly Oliver O'Halloran
@ 2019-08-22  5:59   ` Sam Bobroff
  0 siblings, 0 replies; 7+ messages in thread
From: Sam Bobroff @ 2019-08-22  5:59 UTC (permalink / raw)
  To: Oliver O'Halloran; +Cc: linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 1803 bytes --]

On Wed, Aug 21, 2019 at 04:26:55PM +1000, Oliver O'Halloran wrote:
> These functions can only be used on a SR-IOV capable physical function and
> they're only called in pcibios_sriov_enable / disable. Make them emit a
> warning in the future if they're used incorrectly and remove the dead
> code that checks if the device is a VF.
> 
> Signed-off-by: Oliver O'Halloran <oohall@gmail.com>

Looks good, but you might want to consider using WARN_ON_ONCE() just in
case it gets hit a lot.

Reviewed-by: Sam Bobroff <sbobroff@linux.ibm.com>

> ---
>  arch/powerpc/kernel/pci_dn.c | 17 +++--------------
>  1 file changed, 3 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
> index 24da1d8..69dafc3 100644
> --- a/arch/powerpc/kernel/pci_dn.c
> +++ b/arch/powerpc/kernel/pci_dn.c
> @@ -158,8 +158,8 @@ struct pci_dn *add_sriov_vf_pdns(struct pci_dev *pdev)
>  	int i;
>  
>  	/* Only support IOV for now */
> -	if (!pdev->is_physfn)
> -		return pci_get_pdn(pdev);
> +	if (WARN_ON(!pdev->is_physfn))
> +		return NULL;
>  
>  	/* Check if VFs have been populated */
>  	pdn = pci_get_pdn(pdev);
> @@ -199,19 +199,8 @@ void remove_sriov_vf_pdns(struct pci_dev *pdev)
>  	struct pci_dn *pdn, *tmp;
>  	int i;
>  
> -	/*
> -	 * VF and VF PE are created/released dynamically, so we need to
> -	 * bind/unbind them.  Otherwise the VF and VF PE would be mismatched
> -	 * when re-enabling SR-IOV.
> -	 */
> -	if (pdev->is_virtfn) {
> -		pdn = pci_get_pdn(pdev);
> -		pdn->pe_number = IODA_INVALID_PE;
> -		return;
> -	}
> -
>  	/* Only support IOV PF for now */
> -	if (!pdev->is_physfn)
> +	if (WARN_ON(!pdev->is_physfn))
>  		return;
>  
>  	/* Check if VFs have been populated */
> -- 
> 2.9.5
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] powerpc/pcidn: Make VF pci_dn management CONFIG_PCI_IOV specific
  2019-08-21  6:26 ` [PATCH 2/3] powerpc/pcidn: Make VF pci_dn management CONFIG_PCI_IOV specific Oliver O'Halloran
@ 2019-08-22  5:59   ` Sam Bobroff
  0 siblings, 0 replies; 7+ messages in thread
From: Sam Bobroff @ 2019-08-22  5:59 UTC (permalink / raw)
  To: Oliver O'Halloran; +Cc: linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 5882 bytes --]

On Wed, Aug 21, 2019 at 04:26:54PM +1000, Oliver O'Halloran wrote:
> The powerpc PCI code requires that a pci_dn structure exists for all
> devices in the system. This is fine for real devices since at boot a pci_dn
> is created for each PCI device in the DT and it's fine for hotplugged devices
> since the hotplug slot driver will manage the pci_dn's devices in hotplug
> slots. For SR-IOV, we need the platform / pcibios to manage the pci_dn for
> virtual functions since firmware is unaware of VFs, and they aren't
> "hot plugged" in the traditional sense.
> 
> Management of the pci_dn is handled by the, poorly named, functions:
> add_pci_dev_data() and remove_pci_dev_data(). The entire body of these
> functions is #ifdef`ed around CONFIG_PCI_IOV and they cannot be used
> in any other context, so make them only available when CONFIG_PCI_IOV
> is selected, and rename them to reflect their actual usage rather than
> having them masquerade as generic code.
> 
> Signed-off-by: Oliver O'Halloran <oohall@gmail.com>

Nice cleanup,

Reviewed-by: Sam Bobroff <sbobroff@linux.ibm.com>

> ---
>  arch/powerpc/include/asm/pci-bridge.h     |  7 +++++--
>  arch/powerpc/kernel/pci_dn.c              | 15 +++++----------
>  arch/powerpc/platforms/powernv/pci-ioda.c |  4 ++--
>  arch/powerpc/platforms/pseries/pci.c      |  4 ++--
>  4 files changed, 14 insertions(+), 16 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
> index ea6ec65..69f4cb3 100644
> --- a/arch/powerpc/include/asm/pci-bridge.h
> +++ b/arch/powerpc/include/asm/pci-bridge.h
> @@ -223,12 +223,15 @@ struct pci_dn {
>  extern struct pci_dn *pci_get_pdn_by_devfn(struct pci_bus *bus,
>  					   int devfn);
>  extern struct pci_dn *pci_get_pdn(struct pci_dev *pdev);
> -extern struct pci_dn *add_dev_pci_data(struct pci_dev *pdev);
> -extern void remove_dev_pci_data(struct pci_dev *pdev);
>  extern struct pci_dn *pci_add_device_node_info(struct pci_controller *hose,
>  					       struct device_node *dn);
>  extern void pci_remove_device_node_info(struct device_node *dn);
>  
> +#ifdef CONFIG_PCI_IOV
> +struct pci_dn *add_sriov_vf_pdns(struct pci_dev *pdev);
> +void remove_sriov_vf_pdns(struct pci_dev *pdev);
> +#endif
> +
>  static inline int pci_device_from_OF_node(struct device_node *np,
>  					  u8 *bus, u8 *devfn)
>  {
> diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
> index 795c4e3..24da1d8 100644
> --- a/arch/powerpc/kernel/pci_dn.c
> +++ b/arch/powerpc/kernel/pci_dn.c
> @@ -125,7 +125,7 @@ struct pci_dn *pci_get_pdn(struct pci_dev *pdev)
>  }
>  
>  #ifdef CONFIG_PCI_IOV
> -static struct pci_dn *add_one_dev_pci_data(struct pci_dn *parent,
> +static struct pci_dn *add_one_sriov_vf_pdn(struct pci_dn *parent,
>  					   int vf_index,
>  					   int busno, int devfn)
>  {
> @@ -151,11 +151,9 @@ static struct pci_dn *add_one_dev_pci_data(struct pci_dn *parent,
>  
>  	return pdn;
>  }
> -#endif
>  
> -struct pci_dn *add_dev_pci_data(struct pci_dev *pdev)
> +struct pci_dn *add_sriov_vf_pdns(struct pci_dev *pdev)
>  {
> -#ifdef CONFIG_PCI_IOV
>  	struct pci_dn *parent, *pdn;
>  	int i;
>  
> @@ -176,7 +174,7 @@ struct pci_dn *add_dev_pci_data(struct pci_dev *pdev)
>  	for (i = 0; i < pci_sriov_get_totalvfs(pdev); i++) {
>  		struct eeh_dev *edev __maybe_unused;
>  
> -		pdn = add_one_dev_pci_data(parent, i,
> +		pdn = add_one_sriov_vf_pdn(parent, i,
>  					   pci_iov_virtfn_bus(pdev, i),
>  					   pci_iov_virtfn_devfn(pdev, i));
>  		if (!pdn) {
> @@ -192,14 +190,11 @@ struct pci_dn *add_dev_pci_data(struct pci_dev *pdev)
>  		edev->physfn = pdev;
>  #endif /* CONFIG_EEH */
>  	}
> -#endif /* CONFIG_PCI_IOV */
> -
>  	return pci_get_pdn(pdev);
>  }
>  
> -void remove_dev_pci_data(struct pci_dev *pdev)
> +void remove_sriov_vf_pdns(struct pci_dev *pdev)
>  {
> -#ifdef CONFIG_PCI_IOV
>  	struct pci_dn *parent;
>  	struct pci_dn *pdn, *tmp;
>  	int i;
> @@ -271,8 +266,8 @@ void remove_dev_pci_data(struct pci_dev *pdev)
>  			kfree(pdn);
>  		}
>  	}
> -#endif /* CONFIG_PCI_IOV */
>  }
> +#endif /* CONFIG_PCI_IOV */
>  
>  struct pci_dn *pci_add_device_node_info(struct pci_controller *hose,
>  					struct device_node *dn)
> diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
> index d8080558d0..f1fa489 100644
> --- a/arch/powerpc/platforms/powernv/pci-ioda.c
> +++ b/arch/powerpc/platforms/powernv/pci-ioda.c
> @@ -1719,14 +1719,14 @@ int pnv_pcibios_sriov_disable(struct pci_dev *pdev)
>  	pnv_pci_sriov_disable(pdev);
>  
>  	/* Release PCI data */
> -	remove_dev_pci_data(pdev);
> +	remove_sriov_vf_pdns(pdev);
>  	return 0;
>  }
>  
>  int pnv_pcibios_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
>  {
>  	/* Allocate PCI data */
> -	add_dev_pci_data(pdev);
> +	add_sriov_vf_pdns(pdev);
>  
>  	return pnv_pci_sriov_enable(pdev, num_vfs);
>  }
> diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c
> index 7228309..911534b 100644
> --- a/arch/powerpc/platforms/pseries/pci.c
> +++ b/arch/powerpc/platforms/pseries/pci.c
> @@ -192,7 +192,7 @@ int pseries_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
>  int pseries_pcibios_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
>  {
>  	/* Allocate PCI data */
> -	add_dev_pci_data(pdev);
> +	add_sriov_vf_pdns(pdev);
>  	return pseries_pci_sriov_enable(pdev, num_vfs);
>  }
>  
> @@ -204,7 +204,7 @@ int pseries_pcibios_sriov_disable(struct pci_dev *pdev)
>  	/* Releasing pe_num_map */
>  	kfree(pdn->pe_num_map);
>  	/* Release PCI data */
> -	remove_dev_pci_data(pdev);
> +	remove_sriov_vf_pdns(pdev);
>  	pci_vf_drivers_autoprobe(pdev, true);
>  	return 0;
>  }
> -- 
> 2.9.5
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] powerpc/sriov: Remove VF eeh_dev state when disabling SR-IOV
  2019-08-21  6:26 [PATCH 1/3] powerpc/sriov: Remove VF eeh_dev state when disabling SR-IOV Oliver O'Halloran
                   ` (2 preceding siblings ...)
  2019-08-22  5:49 ` [PATCH 1/3] powerpc/sriov: Remove VF eeh_dev state when disabling SR-IOV Sam Bobroff
@ 2020-01-29  5:17 ` Michael Ellerman
  3 siblings, 0 replies; 7+ messages in thread
From: Michael Ellerman @ 2020-01-29  5:17 UTC (permalink / raw)
  To: Oliver O'Halloran, linuxppc-dev; +Cc: sbobroff, Oliver O'Halloran

On Wed, 2019-08-21 at 06:26:53 UTC, Oliver O'Halloran wrote:
> When disabling virtual functions on an SR-IOV adapter we currently do not
> correctly remove the EEH state for the now-dead virtual functions. When
> removing the pci_dn that was created for the VF when SR-IOV was enabled
> we free the corresponding eeh_dev without removing it from the child device
> list of the eeh_pe that contained it. This can result in crashes due to the
> use-after-free.
> 
> Signed-off-by: Oliver O'Halloran <oohall@gmail.com>

Series applied to powerpc next, thanks.

https://git.kernel.org/powerpc/c/1fb4124ca9d456656a324f1ee29b7bf942f59ac8

cheers

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-01-29  5:25 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-21  6:26 [PATCH 1/3] powerpc/sriov: Remove VF eeh_dev state when disabling SR-IOV Oliver O'Halloran
2019-08-21  6:26 ` [PATCH 2/3] powerpc/pcidn: Make VF pci_dn management CONFIG_PCI_IOV specific Oliver O'Halloran
2019-08-22  5:59   ` Sam Bobroff
2019-08-21  6:26 ` [PATCH 3/3] powerpc/pcidn: Warn when sriov pci_dn management is used incorrectly Oliver O'Halloran
2019-08-22  5:59   ` Sam Bobroff
2019-08-22  5:49 ` [PATCH 1/3] powerpc/sriov: Remove VF eeh_dev state when disabling SR-IOV Sam Bobroff
2020-01-29  5:17 ` Michael Ellerman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).