From a3041e3bdb9fb7adb6505e5f3ff4edb63fde1e84 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 9 Aug 2016 16:38:18 +1000 Subject: lpc: Optimize SerIRQ dispatch based on which PSI IRQ fired We keep a mask for which SerIRQ is associated with which of the 4 PSI IRQs and we only dispatch the ones that correspond to the PSI interrupt that fired. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Stewart Smith --- hw/lpc.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'hw/lpc.c') diff --git a/hw/lpc.c b/hw/lpc.c index b252a54..7b6071d 100644 --- a/hw/lpc.c +++ b/hw/lpc.c @@ -89,7 +89,7 @@ DEFINE_LOG_ENTRY(OPAL_RC_LPC_SYNC, OPAL_PLATFORM_ERR_EVT, OPAL_LPC, #define LPC_HC_IRQSER_START_8CLK 0x02000000 #define LPC_HC_IRQMASK 0x34 /* same bit defs as LPC_HC_IRQSTAT */ #define LPC_HC_IRQSTAT 0x38 -#define LPC_HC_IRQ_SERIRQ0 0x80000000 /* all bits down to ... */ +#define LPC_HC_IRQ_SERIRQ0 0x80000000u /* all bits down to ... */ #define LPC_HC_IRQ_SERIRQ16 0x00008000 /* IRQ16=IOCHK#, IRQ2=SMI# */ #define LPC_HC_IRQ_SERIRQ_ALL 0xffff8000 #define LPC_HC_IRQ_LRESET 0x00000400 @@ -123,6 +123,7 @@ struct lpcm { struct list_head clients; bool has_serirq; uint8_t sirq_routes[LPC_NUM_SERIRQ]; + uint32_t sirq_rmasks[4]; }; struct lpc_client_entry { @@ -658,6 +659,7 @@ void lpc_route_serirq(uint32_t chip_id, uint32_t sirq, uint32_t psi_idx) { struct proc_chip *chip; struct lpcm *lpc; + uint32_t psi_old; if (sirq >= LPC_NUM_SERIRQ) { prerror("LPC[%03x]: Routing request for invalid SerIRQ %d\n", @@ -670,6 +672,9 @@ void lpc_route_serirq(uint32_t chip_id, uint32_t sirq, uint32_t psi_idx) return; lpc = chip->lpc; lock(&lpc->lock); + psi_old = lpc->sirq_routes[sirq]; + lpc->sirq_rmasks[psi_old] &= ~(LPC_HC_IRQ_SERIRQ0 >> sirq); + lpc->sirq_rmasks[psi_idx] |= (LPC_HC_IRQ_SERIRQ0 >> sirq); __lpc_route_serirq(lpc, sirq, psi_idx); unlock(&lpc->lock); } @@ -714,8 +719,11 @@ static void lpc_init_interrupts_one(struct proc_chip *chip) case PROC_CHIP_P9_CUMULUS: /* On P9, we additionall setup the routing */ lpc->has_serirq = true; - for (i = 0; i < LPC_NUM_SERIRQ; i++) - __lpc_route_serirq(lpc, i, lpc->sirq_routes[i]); + for (i = 0; i < LPC_NUM_SERIRQ; i++) { + uint32_t pin = lpc->sirq_routes[i]; + __lpc_route_serirq(lpc, i, pin); + lpc->sirq_rmasks[pin] |= LPC_HC_IRQ_SERIRQ0 >> i; + } lpc_setup_serirq(lpc); break; default: @@ -891,11 +899,11 @@ void lpc_interrupt(uint32_t chip_id) unlock(&lpc->lock); } -void lpc_serirq(uint32_t chip_id, uint32_t index __unused) +void lpc_serirq(uint32_t chip_id, uint32_t index) { struct proc_chip *chip = get_chip(chip_id); struct lpcm *lpc; - uint32_t irqs; + uint32_t irqs, rmask; int rc; /* No initialized LPC controller on that chip */ @@ -911,11 +919,14 @@ void lpc_serirq(uint32_t chip_id, uint32_t index __unused) prerror("LPC: Failed to read LPC IRQ state\n"); goto bail; } + rmask = lpc->sirq_rmasks[index]; - DBG_IRQ("LPC: IRQ on chip 0x%x, irqs=0x%08x\n", chip_id, irqs); + DBG_IRQ("LPC: IRQ on chip 0x%x, irqs=0x%08x rmask=0x%08x\n", + chip_id, irqs, rmask); + irqs &= rmask; /* Handle SerIRQ interrupts */ - if (irqs & LPC_HC_IRQ_SERIRQ_ALL) + if (irqs) lpc_dispatch_ser_irqs(lpc, irqs, true); bail: -- cgit v1.1