[Skiboot] [PATCH] hw/phb3: Flush cache line after updating P/Q bits

Benjamin Herrenschmidt benh at kernel.crashing.org
Wed Nov 18 11:34:04 AEDT 2015


When doing an MSI EOI, we update the P and Q bits in the IVE. That causes
the corresponding cache line to be dirty in the L3 which will cause a
subsequent update by the PHB (upon recieving the next MSI) to get a few
retries until it gets flushed.

We can improve the situation (and thus performance) by doing a dcbf
instruction to force a flush of the update we do in SW.

Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
---

diff --git a/hw/phb3.c b/hw/phb3.c
index 36e8c58..220740a 100644
--- a/hw/phb3.c
+++ b/hw/phb3.c
@@ -1045,7 +1045,7 @@ static int64_t phb3_map_pe_dma_window_real(struct phb *phb,
 	return OPAL_SUCCESS;
 }
 
-static void phb3_pci_msi_check_q(struct phb3 *p, uint32_t ive_num)
+static bool phb3_pci_msi_check_q(struct phb3 *p, uint32_t ive_num)
 {
 	uint64_t ive, ivc, ffi, state;
 	uint8_t *q_byte;
@@ -1067,7 +1067,7 @@ static void phb3_pci_msi_check_q(struct phb3 *p, uint32_t ive_num)
 
 		/* Q still not set, bail out */
 		if (!(*q_byte & 0x1))
-			return;
+			return false;
 	}
 
 	/* Lock FFI and send interrupt */
@@ -1076,7 +1076,7 @@ static void phb3_pci_msi_check_q(struct phb3 *p, uint32_t ive_num)
 		if (!state)
 			break;
 		if (state == ~0ULL) /* PHB Fenced */
-			return;
+			return false;
 	}
 
 	/* Clear Q bit and update IVC */
@@ -1092,6 +1092,16 @@ static void phb3_pci_msi_check_q(struct phb3 *p, uint32_t ive_num)
 	 */
 	ffi = SETFIELD(PHB_FFI_REQUEST_ISN, 0ul, ive_num) | PHB_FFI_LOCK_CLEAR;
 	out_be64(p->regs + PHB_FFI_REQUEST, ffi);
+
+	return true;
+}
+
+static void phb3_pci_msi_flush_ive(struct phb3 *p, uint32_t ive_num)
+{
+	asm volatile("dcbf %0,%1"
+		     :
+		     : "b" (p->tbl_ivt), "r" (ive_num * IVT_TABLE_STRIDE * 8)
+		     : "memory");
 }
 
 static int64_t phb3_pci_msi_eoi(struct phb *phb,
@@ -1127,6 +1137,8 @@ static int64_t phb3_pci_msi_eoi(struct phb *phb,
 	/* Handle Q bit */
 	phb3_pci_msi_check_q(p, ive_num);
 
+	phb3_pci_msi_flush_ive(p, ive_num);
+
 	return OPAL_SUCCESS;
 }
 
@@ -1637,8 +1649,10 @@ static int64_t phb3_msi_set_xive(void *data,
 	 * The OS should make sure the interrupt handler has
 	 * been installed already.
 	 */
-	if (prio != 0xff)
-		phb3_pci_msi_check_q(p, ive_num);
+	if (prio != 0xff) {
+		if (phb3_pci_msi_check_q(p, ive_num))
+			phb3_pci_msi_flush_ive(p, ive_num);
+	}
 
 	return OPAL_SUCCESS;
 }


More information about the Skiboot mailing list