From 53def38014107ca522af8ee0a1004d36b31e3681 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 18 Nov 2015 11:34:04 +1100 Subject: hw/phb3: Flush cache line after updating P/Q bits 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 Signed-off-by: Stewart Smith --- hw/phb3.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) 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; } -- cgit v1.1