[Very RFC 17/46] powernv/eeh: add pnv_eeh_find_edev()
Alexey Kardashevskiy
aik at ozlabs.ru
Mon Nov 25 11:30:33 AEDT 2019
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 at 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 at 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,
>
--
Alexey
More information about the Linuxppc-dev
mailing list