diff mbox series

[Very,RFC,17/46] powernv/eeh: add pnv_eeh_find_edev()

Message ID 20191120012859.23300-18-oohall@gmail.com (mailing list archive)
State RFC
Headers show
Series [Very,RFC,01/46] powerpc/eeh: Don't attempt to restore VF config space after reset | expand

Checks

Context Check Description
snowpatch_ozlabs/apply_patch warning Failed to apply on branch powerpc/merge (784eee1cc44801366d4f197e0ade7739ee8e1e83)
snowpatch_ozlabs/apply_patch warning Failed to apply on branch powerpc/next (0695f8bca93ea0c57f0e8e21b4b4db70183b3d1c)
snowpatch_ozlabs/apply_patch warning Failed to apply on branch linus/master (c74386d50fbaf4a54fd3fe560f1abc709c0cff4b)
snowpatch_ozlabs/apply_patch warning Failed to apply on branch powerpc/fixes (7d6475051fb3d9339c5c760ed9883bc0a9048b21)
snowpatch_ozlabs/apply_patch warning Failed to apply on branch linux-next (5d1131b4d61e52e5702e0fa4bcbec81ac7d6ef52)
snowpatch_ozlabs/apply_patch fail Failed to apply to any branch

Commit Message

Oliver O'Halloran Nov. 20, 2019, 1:28 a.m. UTC
To get away from using pci_dn we need a way to find the edev for a given
bdfn. The easiest way to do this is to find the ioda_pe for that BDFN in
the PHB's reverse mapping table and scan the device list of the
corresponding eeh_pe.

Is this slow? Yeah probably. Is it slower than the existing "traverse the
pdn tree" method? Probably not.

Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
 arch/powerpc/platforms/powernv/eeh-powernv.c | 31 ++++++++++++++++++++
 arch/powerpc/platforms/powernv/pci.h         |  2 ++
 2 files changed, 33 insertions(+)

Comments

Alexey Kardashevskiy Nov. 25, 2019, 12:30 a.m. UTC | #1
On 20/11/2019 12:28, Oliver O'Halloran wrote:
> To get away from using pci_dn we need a way to find the edev for a given
> bdfn. The easiest way to do this is to find the ioda_pe for that BDFN in
> the PHB's reverse mapping table and scan the device list of the
> corresponding eeh_pe.
> 
> Is this slow? Yeah probably. Is it slower than the existing "traverse the
> pdn tree" method? Probably not.
> 
> Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
> ---
>  arch/powerpc/platforms/powernv/eeh-powernv.c | 31 ++++++++++++++++++++
>  arch/powerpc/platforms/powernv/pci.h         |  2 ++
>  2 files changed, 33 insertions(+)
> 
> diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c
> index f58fe6bda46e..a974822c5097 100644
> --- a/arch/powerpc/platforms/powernv/eeh-powernv.c
> +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
> @@ -278,6 +278,37 @@ int pnv_eeh_post_init(void)
>  	return ret;
>  }
>  
> +struct eeh_dev *pnv_eeh_find_edev(struct pnv_phb *phb, u16 bdfn)
> +{
> +	struct pnv_ioda_pe *ioda_pe;
> +	struct eeh_dev *tmp, *edev;
> +	struct eeh_pe *pe;
> +
> +	/* EEH not enabled ? */
> +	if (!(phb->flags & PNV_PHB_FLAG_EEH))
> +		return NULL;
> +
> +	/* Fish the EEH PE from the IODA PE */
> +	ioda_pe = __pnv_ioda_get_pe(phb, bdfn);
> +	if (!ioda_pe)
> +		return NULL;
> +
> +	/*
> +	 * FIXME: Doing a tree-traversal followed by a list traversal
> +	 * on every config access is dumb. Not much dumber than the pci_dn
> +	 * tree traversal we did before, but still quite dumb.


Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>


Although I would reduce the comment above to "FIXME: replace 3
traversals with something better".



> +	 */
> +	pe = eeh_pe_get(phb->hose, ioda_pe->pe_number, 0);
> +	if (!pe)
> +		return NULL;
> +
> +	eeh_pe_for_each_dev(pe, edev, tmp)
> +		if (edev->bdfn == bdfn)
> +			return edev;
> +
> +	return NULL;
> +}
> +
>  static inline bool pnv_eeh_cfg_blocked(struct eeh_dev *edev)
>  {
>  	if (!edev || !edev->pe)
> diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
> index 3c33a0c91a69..a343f3c8e65c 100644
> --- a/arch/powerpc/platforms/powernv/pci.h
> +++ b/arch/powerpc/platforms/powernv/pci.h
> @@ -196,6 +196,8 @@ extern void pnv_set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq);
>  extern unsigned long pnv_pci_ioda2_get_table_size(__u32 page_shift,
>  		__u64 window_size, __u32 levels);
>  extern int pnv_eeh_post_init(void);
> +struct eeh_dev;
> +struct eeh_dev *pnv_eeh_find_edev(struct pnv_phb *phb, u16 bdfn);
>  
>  __printf(3, 4)
>  extern void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level,
>
diff mbox series

Patch

diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c
index f58fe6bda46e..a974822c5097 100644
--- a/arch/powerpc/platforms/powernv/eeh-powernv.c
+++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
@@ -278,6 +278,37 @@  int pnv_eeh_post_init(void)
 	return ret;
 }
 
+struct eeh_dev *pnv_eeh_find_edev(struct pnv_phb *phb, u16 bdfn)
+{
+	struct pnv_ioda_pe *ioda_pe;
+	struct eeh_dev *tmp, *edev;
+	struct eeh_pe *pe;
+
+	/* EEH not enabled ? */
+	if (!(phb->flags & PNV_PHB_FLAG_EEH))
+		return NULL;
+
+	/* Fish the EEH PE from the IODA PE */
+	ioda_pe = __pnv_ioda_get_pe(phb, bdfn);
+	if (!ioda_pe)
+		return NULL;
+
+	/*
+	 * FIXME: Doing a tree-traversal followed by a list traversal
+	 * on every config access is dumb. Not much dumber than the pci_dn
+	 * tree traversal we did before, but still quite dumb.
+	 */
+	pe = eeh_pe_get(phb->hose, ioda_pe->pe_number, 0);
+	if (!pe)
+		return NULL;
+
+	eeh_pe_for_each_dev(pe, edev, tmp)
+		if (edev->bdfn == bdfn)
+			return edev;
+
+	return NULL;
+}
+
 static inline bool pnv_eeh_cfg_blocked(struct eeh_dev *edev)
 {
 	if (!edev || !edev->pe)
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index 3c33a0c91a69..a343f3c8e65c 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -196,6 +196,8 @@  extern void pnv_set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq);
 extern unsigned long pnv_pci_ioda2_get_table_size(__u32 page_shift,
 		__u64 window_size, __u32 levels);
 extern int pnv_eeh_post_init(void);
+struct eeh_dev;
+struct eeh_dev *pnv_eeh_find_edev(struct pnv_phb *phb, u16 bdfn);
 
 __printf(3, 4)
 extern void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level,