From a1409adac748f0db655e096521bbe6904aadeb98 Mon Sep 17 00:00:00 2001 From: Alistair Popple Date: Wed, 11 Apr 2018 16:38:55 +1000 Subject: [PATCH] powerpc/powernv/npu: Prevent overwriting of pnv_npu2_init_contex() callback parameters There is a single npu context per set of callback parameters. Callers should be prevented from overwriting existing callback values so instead return an error if different parameters are passed. Fixes: 1ab66d1fbada ("powerpc/powernv: Introduce address translation services for Nvlink2") Cc: stable@vger.kernel.org # v4.12+ Signed-off-by: Alistair Popple Reviewed-by: Mark Hairgrove Tested-by: Mark Hairgrove Reviewed-by: Balbir Singh Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/powernv.h | 2 +- arch/powerpc/platforms/powernv/npu-dma.c | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/include/asm/powernv.h b/arch/powerpc/include/asm/powernv.h index d1c2d2e658cf..2f3ff7a27881 100644 --- a/arch/powerpc/include/asm/powernv.h +++ b/arch/powerpc/include/asm/powernv.h @@ -15,7 +15,7 @@ extern void powernv_set_nmmu_ptcr(unsigned long ptcr); extern struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev, unsigned long flags, - struct npu_context *(*cb)(struct npu_context *, void *), + void (*cb)(struct npu_context *, void *), void *priv); extern void pnv_npu2_destroy_context(struct npu_context *context, struct pci_dev *gpdev); diff --git a/arch/powerpc/platforms/powernv/npu-dma.c b/arch/powerpc/platforms/powernv/npu-dma.c index 5ff7c6e0e6da..ccd57d1b5bf8 100644 --- a/arch/powerpc/platforms/powernv/npu-dma.c +++ b/arch/powerpc/platforms/powernv/npu-dma.c @@ -407,7 +407,7 @@ struct npu_context { bool nmmu_flush; /* Callback to stop translation requests on a given GPU */ - struct npu_context *(*release_cb)(struct npu_context *, void *); + void (*release_cb)(struct npu_context *context, void *priv); /* * Private pointer passed to the above callback for usage by @@ -707,7 +707,7 @@ static const struct mmu_notifier_ops nv_nmmu_notifier_ops = { */ struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev, unsigned long flags, - struct npu_context *(*cb)(struct npu_context *, void *), + void (*cb)(struct npu_context *, void *), void *priv) { int rc; @@ -765,8 +765,18 @@ struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev, */ spin_lock(&npu_context_lock); npu_context = mm->context.npu_context; - if (npu_context) + if (npu_context) { + if (npu_context->release_cb != cb || + npu_context->priv != priv) { + spin_unlock(&npu_context_lock); + opal_npu_destroy_context(nphb->opal_id, mm->context.id, + PCI_DEVID(gpdev->bus->number, + gpdev->devfn)); + return ERR_PTR(-EINVAL); + } + WARN_ON(!kref_get_unless_zero(&npu_context->kref)); + } spin_unlock(&npu_context_lock); if (!npu_context) { -- 2.25.1