diff mbox

powerpc/powernv: Fix TCE kill on NVLink2

Message ID 1494512781-31941-1-git-send-email-leitao@debian.org
State New
Headers show

Commit Message

Breno Leitao May 11, 2017, 2:26 p.m. UTC
From: Alistair Popple <alistair@popple.id.au>

BugLink: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1690155

Commit 616badd2fb49 ("powerpc/powernv: Use OPAL call for TCE kill on
NVLink2") forced all TCE kills to go via the OPAL call for
NVLink2. However the PHB3 implementation of TCE kill was still being
called directly from some functions which in some circumstances caused
a machine check.

This patch adds an equivalent IODA2 version of the function which uses
the correct invalidation method depending on PHB model and changes all
external callers to use it instead.

Fixes: 616badd2fb49 ("powerpc/powernv: Use OPAL call for TCE kill on NVLink2")
Cc: stable@vger.kernel.org # v4.11+
Signed-off-by: Alistair Popple <alistair@popple.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
(cherry picked from commit 6b3d12a948d27977816a15eb48409a298902a548)
Signed-off-by: Breno Leitao <breno.leitao@gmail.com>
---
 arch/powerpc/platforms/powernv/npu-dma.c  |  8 ++++----
 arch/powerpc/platforms/powernv/pci-ioda.c | 10 +++++++++-
 arch/powerpc/platforms/powernv/pci.h      |  2 +-
 3 files changed, 14 insertions(+), 6 deletions(-)

Comments

Seth Forshee May 11, 2017, 2:46 p.m. UTC | #1
On Thu, May 11, 2017 at 11:26:21AM -0300, Breno Leitao wrote:
> From: Alistair Popple <alistair@popple.id.au>
> 
> BugLink: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1690155
> 
> Commit 616badd2fb49 ("powerpc/powernv: Use OPAL call for TCE kill on
> NVLink2") forced all TCE kills to go via the OPAL call for
> NVLink2. However the PHB3 implementation of TCE kill was still being
> called directly from some functions which in some circumstances caused
> a machine check.
> 
> This patch adds an equivalent IODA2 version of the function which uses
> the correct invalidation method depending on PHB model and changes all
> external callers to use it instead.
> 
> Fixes: 616badd2fb49 ("powerpc/powernv: Use OPAL call for TCE kill on NVLink2")
> Cc: stable@vger.kernel.org # v4.11+
> Signed-off-by: Alistair Popple <alistair@popple.id.au>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> (cherry picked from commit 6b3d12a948d27977816a15eb48409a298902a548)
> Signed-off-by: Breno Leitao <breno.leitao@gmail.com>

Applied to artful master-next.
Seth Forshee May 11, 2017, 4:48 p.m. UTC | #2
On Thu, May 11, 2017 at 09:46:57AM -0500, Seth Forshee wrote:
> On Thu, May 11, 2017 at 11:26:21AM -0300, Breno Leitao wrote:
> > From: Alistair Popple <alistair@popple.id.au>
> > 
> > BugLink: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1690155
> > 
> > Commit 616badd2fb49 ("powerpc/powernv: Use OPAL call for TCE kill on
> > NVLink2") forced all TCE kills to go via the OPAL call for
> > NVLink2. However the PHB3 implementation of TCE kill was still being
> > called directly from some functions which in some circumstances caused
> > a machine check.
> > 
> > This patch adds an equivalent IODA2 version of the function which uses
> > the correct invalidation method depending on PHB model and changes all
> > external callers to use it instead.
> > 
> > Fixes: 616badd2fb49 ("powerpc/powernv: Use OPAL call for TCE kill on NVLink2")
> > Cc: stable@vger.kernel.org # v4.11+
> > Signed-off-by: Alistair Popple <alistair@popple.id.au>
> > Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> > (cherry picked from commit 6b3d12a948d27977816a15eb48409a298902a548)
> > Signed-off-by: Breno Leitao <breno.leitao@gmail.com>
> 
> Applied to artful master-next.

Forgot to include an ack for zesty.

Acked-by: Seth Forshee <seth.forshee@canonical.com>
Thadeu Lima de Souza Cascardo May 16, 2017, 7:51 p.m. UTC | #3
On Thu, May 11, 2017 at 11:26:21AM -0300, Breno Leitao wrote:
> From: Alistair Popple <alistair@popple.id.au>
> 
> BugLink: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1690155
> 
> Commit 616badd2fb49 ("powerpc/powernv: Use OPAL call for TCE kill on
> NVLink2") forced all TCE kills to go via the OPAL call for
> NVLink2. However the PHB3 implementation of TCE kill was still being
> called directly from some functions which in some circumstances caused
> a machine check.
> 
> This patch adds an equivalent IODA2 version of the function which uses
> the correct invalidation method depending on PHB model and changes all
> external callers to use it instead.
> 
> Fixes: 616badd2fb49 ("powerpc/powernv: Use OPAL call for TCE kill on NVLink2")
> Cc: stable@vger.kernel.org # v4.11+
> Signed-off-by: Alistair Popple <alistair@popple.id.au>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> (cherry picked from commit 6b3d12a948d27977816a15eb48409a298902a548)
> Signed-off-by: Breno Leitao <breno.leitao@gmail.com>
> ---
>  arch/powerpc/platforms/powernv/npu-dma.c  |  8 ++++----
>  arch/powerpc/platforms/powernv/pci-ioda.c | 10 +++++++++-
>  arch/powerpc/platforms/powernv/pci.h      |  2 +-
>  3 files changed, 14 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/powernv/npu-dma.c b/arch/powerpc/platforms/powernv/npu-dma.c
> index 73b155fd4481..34339c7e676b 100644
> --- a/arch/powerpc/platforms/powernv/npu-dma.c
> +++ b/arch/powerpc/platforms/powernv/npu-dma.c
> @@ -180,7 +180,7 @@ long pnv_npu_set_window(struct pnv_ioda_pe *npe, int num,
>  		pe_err(npe, "Failed to configure TCE table, err %lld\n", rc);
>  		return rc;
>  	}
> -	pnv_pci_phb3_tce_invalidate_entire(phb, false);
> +	pnv_pci_ioda2_tce_invalidate_entire(phb, false);
>  
>  	/* Add the table to the list so its TCE cache will get invalidated */
>  	pnv_pci_link_table_and_group(phb->hose->node, num,
> @@ -204,7 +204,7 @@ long pnv_npu_unset_window(struct pnv_ioda_pe *npe, int num)
>  		pe_err(npe, "Unmapping failed, ret = %lld\n", rc);
>  		return rc;
>  	}
> -	pnv_pci_phb3_tce_invalidate_entire(phb, false);
> +	pnv_pci_ioda2_tce_invalidate_entire(phb, false);
>  
>  	pnv_pci_unlink_table_and_group(npe->table_group.tables[num],
>  			&npe->table_group);
> @@ -270,7 +270,7 @@ static int pnv_npu_dma_set_bypass(struct pnv_ioda_pe *npe)
>  			0 /* bypass base */, top);
>  
>  	if (rc == OPAL_SUCCESS)
> -		pnv_pci_phb3_tce_invalidate_entire(phb, false);
> +		pnv_pci_ioda2_tce_invalidate_entire(phb, false);
>  
>  	return rc;
>  }
> @@ -334,7 +334,7 @@ void pnv_npu_take_ownership(struct pnv_ioda_pe *npe)
>  		pe_err(npe, "Failed to disable bypass, err %lld\n", rc);
>  		return;
>  	}
> -	pnv_pci_phb3_tce_invalidate_entire(npe->phb, false);
> +	pnv_pci_ioda2_tce_invalidate_entire(npe->phb, false);
>  }
>  
>  struct pnv_ioda_pe *pnv_pci_npu_setup_iommu(struct pnv_ioda_pe *npe)
> diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
> index 5c448a3568ac..c01e51c2e303 100644
> --- a/arch/powerpc/platforms/powernv/pci-ioda.c
> +++ b/arch/powerpc/platforms/powernv/pci-ioda.c
> @@ -1879,7 +1879,7 @@ static struct iommu_table_ops pnv_ioda1_iommu_ops = {
>  #define PHB3_TCE_KILL_INVAL_PE		PPC_BIT(1)
>  #define PHB3_TCE_KILL_INVAL_ONE		PPC_BIT(2)
>  
> -void pnv_pci_phb3_tce_invalidate_entire(struct pnv_phb *phb, bool rm)
> +static void pnv_pci_phb3_tce_invalidate_entire(struct pnv_phb *phb, bool rm)
>  {
>  	__be64 __iomem *invalidate = pnv_ioda_get_inval_reg(phb, rm);
>  	const unsigned long val = PHB3_TCE_KILL_INVAL_ALL;
> @@ -1975,6 +1975,14 @@ static void pnv_pci_ioda2_tce_invalidate(struct iommu_table *tbl,
>  	}
>  }
>  
> +void pnv_pci_ioda2_tce_invalidate_entire(struct pnv_phb *phb, bool rm)
> +{
> +	if (phb->model == PNV_PHB_MODEL_NPU || phb->model == PNV_PHB_MODEL_PHB3)
> +		pnv_pci_phb3_tce_invalidate_entire(phb, rm);
> +	else
> +		opal_pci_tce_kill(phb->opal_id, OPAL_PCI_TCE_KILL, 0, 0, 0, 0);
> +}
> +
>  static int pnv_ioda2_tce_build(struct iommu_table *tbl, long index,
>  		long npages, unsigned long uaddr,
>  		enum dma_data_direction direction,
> diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
> index e1d3e5526b54..5d6599373f32 100644
> --- a/arch/powerpc/platforms/powernv/pci.h
> +++ b/arch/powerpc/platforms/powernv/pci.h
> @@ -229,7 +229,7 @@ extern void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level,
>  
>  /* Nvlink functions */
>  extern void pnv_npu_try_dma_set_bypass(struct pci_dev *gpdev, bool bypass);
> -extern void pnv_pci_phb3_tce_invalidate_entire(struct pnv_phb *phb, bool rm);
> +extern void pnv_pci_ioda2_tce_invalidate_entire(struct pnv_phb *phb, bool rm);
>  extern struct pnv_ioda_pe *pnv_pci_npu_setup_iommu(struct pnv_ioda_pe *npe);
>  extern long pnv_npu_set_window(struct pnv_ioda_pe *npe, int num,
>  		struct iommu_table *tbl);
> -- 
> 2.11.0
> 
> 
> -- 
> kernel-team mailing list
> kernel-team@lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team

Affects very specific architecture.

Acked-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
Thadeu Lima de Souza Cascardo May 16, 2017, 7:53 p.m. UTC | #4
Applied to zesty master-next branch.

Thanks.
Cascardo.
diff mbox

Patch

diff --git a/arch/powerpc/platforms/powernv/npu-dma.c b/arch/powerpc/platforms/powernv/npu-dma.c
index 73b155fd4481..34339c7e676b 100644
--- a/arch/powerpc/platforms/powernv/npu-dma.c
+++ b/arch/powerpc/platforms/powernv/npu-dma.c
@@ -180,7 +180,7 @@  long pnv_npu_set_window(struct pnv_ioda_pe *npe, int num,
 		pe_err(npe, "Failed to configure TCE table, err %lld\n", rc);
 		return rc;
 	}
-	pnv_pci_phb3_tce_invalidate_entire(phb, false);
+	pnv_pci_ioda2_tce_invalidate_entire(phb, false);
 
 	/* Add the table to the list so its TCE cache will get invalidated */
 	pnv_pci_link_table_and_group(phb->hose->node, num,
@@ -204,7 +204,7 @@  long pnv_npu_unset_window(struct pnv_ioda_pe *npe, int num)
 		pe_err(npe, "Unmapping failed, ret = %lld\n", rc);
 		return rc;
 	}
-	pnv_pci_phb3_tce_invalidate_entire(phb, false);
+	pnv_pci_ioda2_tce_invalidate_entire(phb, false);
 
 	pnv_pci_unlink_table_and_group(npe->table_group.tables[num],
 			&npe->table_group);
@@ -270,7 +270,7 @@  static int pnv_npu_dma_set_bypass(struct pnv_ioda_pe *npe)
 			0 /* bypass base */, top);
 
 	if (rc == OPAL_SUCCESS)
-		pnv_pci_phb3_tce_invalidate_entire(phb, false);
+		pnv_pci_ioda2_tce_invalidate_entire(phb, false);
 
 	return rc;
 }
@@ -334,7 +334,7 @@  void pnv_npu_take_ownership(struct pnv_ioda_pe *npe)
 		pe_err(npe, "Failed to disable bypass, err %lld\n", rc);
 		return;
 	}
-	pnv_pci_phb3_tce_invalidate_entire(npe->phb, false);
+	pnv_pci_ioda2_tce_invalidate_entire(npe->phb, false);
 }
 
 struct pnv_ioda_pe *pnv_pci_npu_setup_iommu(struct pnv_ioda_pe *npe)
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 5c448a3568ac..c01e51c2e303 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -1879,7 +1879,7 @@  static struct iommu_table_ops pnv_ioda1_iommu_ops = {
 #define PHB3_TCE_KILL_INVAL_PE		PPC_BIT(1)
 #define PHB3_TCE_KILL_INVAL_ONE		PPC_BIT(2)
 
-void pnv_pci_phb3_tce_invalidate_entire(struct pnv_phb *phb, bool rm)
+static void pnv_pci_phb3_tce_invalidate_entire(struct pnv_phb *phb, bool rm)
 {
 	__be64 __iomem *invalidate = pnv_ioda_get_inval_reg(phb, rm);
 	const unsigned long val = PHB3_TCE_KILL_INVAL_ALL;
@@ -1975,6 +1975,14 @@  static void pnv_pci_ioda2_tce_invalidate(struct iommu_table *tbl,
 	}
 }
 
+void pnv_pci_ioda2_tce_invalidate_entire(struct pnv_phb *phb, bool rm)
+{
+	if (phb->model == PNV_PHB_MODEL_NPU || phb->model == PNV_PHB_MODEL_PHB3)
+		pnv_pci_phb3_tce_invalidate_entire(phb, rm);
+	else
+		opal_pci_tce_kill(phb->opal_id, OPAL_PCI_TCE_KILL, 0, 0, 0, 0);
+}
+
 static int pnv_ioda2_tce_build(struct iommu_table *tbl, long index,
 		long npages, unsigned long uaddr,
 		enum dma_data_direction direction,
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index e1d3e5526b54..5d6599373f32 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -229,7 +229,7 @@  extern void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level,
 
 /* Nvlink functions */
 extern void pnv_npu_try_dma_set_bypass(struct pci_dev *gpdev, bool bypass);
-extern void pnv_pci_phb3_tce_invalidate_entire(struct pnv_phb *phb, bool rm);
+extern void pnv_pci_ioda2_tce_invalidate_entire(struct pnv_phb *phb, bool rm);
 extern struct pnv_ioda_pe *pnv_pci_npu_setup_iommu(struct pnv_ioda_pe *npe);
 extern long pnv_npu_set_window(struct pnv_ioda_pe *npe, int num,
 		struct iommu_table *tbl);