diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2015-11-18 11:34:04 +1100 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-11-19 14:43:23 +1100 |
commit | 53def38014107ca522af8ee0a1004d36b31e3681 (patch) | |
tree | b0a2b44b8cdf41b6189ea20f86e96195a216a67f | |
parent | 396de731b044578233b7f2f977c876971586e1c0 (diff) | |
download | skiboot-53def38014107ca522af8ee0a1004d36b31e3681.zip skiboot-53def38014107ca522af8ee0a1004d36b31e3681.tar.gz skiboot-53def38014107ca522af8ee0a1004d36b31e3681.tar.bz2 |
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 <benh@kernel.crashing.org>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r-- | hw/phb3.c | 24 |
1 files changed, 19 insertions, 5 deletions
@@ -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; } |