From patchwork Wed Aug 8 02:10:32 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 175850 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id DD4E62C0086 for ; Wed, 8 Aug 2012 12:58:04 +1000 (EST) Received: from localhost ([::1]:40592 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SyvkB-0002WN-Sh for incoming@patchwork.ozlabs.org; Tue, 07 Aug 2012 22:11:31 -0400 Received: from eggs.gnu.org ([208.118.235.92]:34664) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Syvja-00011M-Cj for qemu-devel@nongnu.org; Tue, 07 Aug 2012 22:10:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SyvjY-0005Hh-AS for qemu-devel@nongnu.org; Tue, 07 Aug 2012 22:10:54 -0400 Received: from ozlabs.org ([203.10.76.45]:37751) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SyvjX-0005Gw-NG; Tue, 07 Aug 2012 22:10:52 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 6DA4A2C00BC; Wed, 8 Aug 2012 12:10:49 +1000 (EST) From: David Gibson To: agraf@suse.de, qemu-ppc@nongnu.org Date: Wed, 8 Aug 2012 12:10:32 +1000 Message-Id: <1344391839-2006-4-git-send-email-david@gibson.dropbear.id.au> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1344391839-2006-1-git-send-email-david@gibson.dropbear.id.au> References: <1344391839-2006-1-git-send-email-david@gibson.dropbear.id.au> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 203.10.76.45 Cc: Alexey Kardashevskiy , aliguori@us.ibm.com, qemu-devel@nongnu.org, David Gibson Subject: [Qemu-devel] [PATCH 03/10] pseries: Rework irq assignment to avoid carrying qemu_irqs around X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Currently, the interfaces in the pseries machine code for assignment and setup of interrupts pass around qemu_irq objects. That was done in an attempt not to be too closely linked to the specific XICS interrupt controller. However interactions with the device tree setup made that attempt rather futile, and XICS is part of the PAPR spec anyway, so this really just meant we had to carry both the qemu_irq pointers and the XICS irq numbers around. This mess will just get worse when we add upcoming PCI MSI support, since that will require tracking a bunch more interrupt. Therefore, this patch reworks the spapr code to just use XICS irq numbers (roughly equivalent to GSIs on x86) and only retrieve the qemu_irq pointers from the XICS code when we need them (a trivial lookup). This is a reworked and generalized version of an earlier spapr_pci specific patch from Alexey Kardashevskiy. Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson --- hw/spapr.c | 18 +++++++----------- hw/spapr.h | 11 +++++------ hw/spapr_llan.c | 2 +- hw/spapr_pci.c | 14 ++++++-------- hw/spapr_pci.h | 8 ++++++-- hw/spapr_vio.c | 12 ++++++------ hw/spapr_vio.h | 8 ++++++-- hw/spapr_vty.c | 2 +- hw/xics.c | 12 +++++++++--- hw/xics.h | 5 +++-- 10 files changed, 50 insertions(+), 42 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 3a303cd..cdc66d1 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -83,11 +83,9 @@ sPAPREnvironment *spapr; -qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num, - enum xics_irq_type type) +int spapr_allocate_irq(int hint, enum xics_irq_type type) { - uint32_t irq; - qemu_irq qirq; + int irq; if (hint) { irq = hint; @@ -96,16 +94,14 @@ qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num, irq = spapr->next_irq++; } - qirq = xics_assign_irq(spapr->icp, irq, type); - if (!qirq) { - return NULL; + /* Configure irq type */ + if (!xics_get_qirq(spapr->icp, irq)) { + return 0; } - if (irq_num) { - *irq_num = irq; - } + xics_set_irq_type(spapr->icp, irq, type); - return qirq; + return irq; } static int spapr_set_associativity(void *fdt, sPAPREnvironment *spapr) diff --git a/hw/spapr.h b/hw/spapr.h index 9153f29..c5de18d 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -288,17 +288,16 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn); target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode, target_ulong *args); -qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num, - enum xics_irq_type type); +int spapr_allocate_irq(int hint, enum xics_irq_type type); -static inline qemu_irq spapr_allocate_msi(uint32_t hint, uint32_t *irq_num) +static inline int spapr_allocate_msi(int hint) { - return spapr_allocate_irq(hint, irq_num, XICS_MSI); + return spapr_allocate_irq(hint, XICS_MSI); } -static inline qemu_irq spapr_allocate_lsi(uint32_t hint, uint32_t *irq_num) +static inline int spapr_allocate_lsi(int hint) { - return spapr_allocate_irq(hint, irq_num, XICS_LSI); + return spapr_allocate_irq(hint, XICS_LSI); } static inline uint32_t rtas_ld(target_ulong phys, int n) diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c index 01e54f3..bd3f131 100644 --- a/hw/spapr_llan.c +++ b/hw/spapr_llan.c @@ -169,7 +169,7 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf, } if (sdev->signal_state & 1) { - qemu_irq_pulse(sdev->qirq); + qemu_irq_pulse(spapr_vio_qirq(sdev)); } return size; diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 2913540..65ae8c4 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -223,7 +223,7 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level) */ sPAPRPHBState *phb = opaque; - qemu_set_irq(phb->lsi_table[irq_num].qirq, level); + qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level); } static uint64_t spapr_io_read(void *opaque, target_phys_addr_t addr, @@ -329,16 +329,14 @@ static int spapr_phb_init(SysBusDevice *s) /* Initialize the LSI table */ for (i = 0; i < PCI_NUM_PINS; i++) { - qemu_irq qirq; - uint32_t num; + uint32_t irq; - qirq = spapr_allocate_lsi(0, &num); - if (!qirq) { + irq = spapr_allocate_lsi(0); + if (!irq) { return -1; } - phb->lsi_table[i].dt_irq = num; - phb->lsi_table[i].qirq = qirq; + phb->lsi_table[i].irq = irq; } return 0; @@ -477,7 +475,7 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, irqmap[2] = 0; irqmap[3] = cpu_to_be32(j+1); irqmap[4] = cpu_to_be32(xics_phandle); - irqmap[5] = cpu_to_be32(phb->lsi_table[lsi_num].dt_irq); + irqmap[5] = cpu_to_be32(phb->lsi_table[lsi_num].irq); irqmap[6] = cpu_to_be32(0x8); } } diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index dd66f4b..6bba885 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -40,13 +40,17 @@ typedef struct sPAPRPHBState { DMAContext *dma; struct { - uint32_t dt_irq; - qemu_irq qirq; + uint32_t irq; } lsi_table[PCI_NUM_PINS]; QLIST_ENTRY(sPAPRPHBState) list; } sPAPRPHBState; +static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin) +{ + return xics_get_qirq(spapr->icp, phb->lsi_table[pin].irq); +} + #define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL #define SPAPR_PCI_IO_WIN_SIZE 0x10000 diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index 05b5503..3abe853 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -49,7 +49,7 @@ #endif static Property spapr_vio_props[] = { - DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, vio_irq_num, 0), \ + DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, irq, 0), \ DEFINE_PROP_END_OF_LIST(), }; @@ -132,8 +132,8 @@ static int vio_make_devnode(VIOsPAPRDevice *dev, } } - if (dev->qirq) { - uint32_t ints_prop[] = {cpu_to_be32(dev->vio_irq_num), 0}; + if (dev->irq) { + uint32_t ints_prop[] = {cpu_to_be32(dev->irq), 0}; ret = fdt_setprop(fdt, node_off, "interrupts", ints_prop, sizeof(ints_prop)); @@ -306,7 +306,7 @@ int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq) dev->crq.qnext = (dev->crq.qnext + 16) % dev->crq.qsize; if (dev->signal_state & 1) { - qemu_irq_pulse(dev->qirq); + qemu_irq_pulse(spapr_vio_qirq(dev)); } return 0; @@ -459,8 +459,8 @@ static int spapr_vio_busdev_init(DeviceState *qdev) dev->qdev.id = id; } - dev->qirq = spapr_allocate_msi(dev->vio_irq_num, &dev->vio_irq_num); - if (!dev->qirq) { + dev->irq = spapr_allocate_msi(dev->irq); + if (!dev->irq) { return -1; } diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h index 6f9a498..ea6aa43 100644 --- a/hw/spapr_vio.h +++ b/hw/spapr_vio.h @@ -61,8 +61,7 @@ struct VIOsPAPRDevice { DeviceState qdev; uint32_t reg; uint32_t flags; - qemu_irq qirq; - uint32_t vio_irq_num; + uint32_t irq; target_ulong signal_state; VIOsPAPR_CRQ crq; DMAContext *dma; @@ -85,6 +84,11 @@ extern int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus); extern int spapr_vio_signal(VIOsPAPRDevice *dev, target_ulong mode); +static inline qemu_irq spapr_vio_qirq(VIOsPAPRDevice *dev) +{ + return xics_get_qirq(spapr->icp, dev->irq); +} + static inline bool spapr_vio_dma_valid(VIOsPAPRDevice *dev, uint64_t taddr, uint32_t size, DMADirection dir) { diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c index 99e52cc..5da17a3 100644 --- a/hw/spapr_vty.c +++ b/hw/spapr_vty.c @@ -26,7 +26,7 @@ static void vty_receive(void *opaque, const uint8_t *buf, int size) if ((dev->in == dev->out) && size) { /* toggle line to simulate edge interrupt */ - qemu_irq_pulse(dev->sdev.qirq); + qemu_irq_pulse(spapr_vio_qirq(&dev->sdev)); } for (i = 0; i < size; i++) { assert((dev->in - dev->out) < VTERM_BUFSIZE); diff --git a/hw/xics.c b/hw/xics.c index 668a0d6..b415aa2 100644 --- a/hw/xics.c +++ b/hw/xics.c @@ -315,18 +315,24 @@ static void ics_eoi(struct ics_state *ics, int nr) * Exported functions */ -qemu_irq xics_assign_irq(struct icp_state *icp, int irq, - enum xics_irq_type type) +qemu_irq xics_get_qirq(struct icp_state *icp, int irq) { if ((irq < icp->ics->offset) || (irq >= (icp->ics->offset + icp->ics->nr_irqs))) { return NULL; } + return icp->ics->qirqs[irq - icp->ics->offset]; +} + +void xics_set_irq_type(struct icp_state *icp, int irq, + enum xics_irq_type type) +{ + assert ((irq >= icp->ics->offset) + && (irq < (icp->ics->offset + icp->ics->nr_irqs))); assert((type == XICS_MSI) || (type == XICS_LSI)); icp->ics->irqs[irq - icp->ics->offset].type = type; - return icp->ics->qirqs[irq - icp->ics->offset]; } static target_ulong h_cppr(CPUPPCState *env, sPAPREnvironment *spapr, diff --git a/hw/xics.h b/hw/xics.h index 2080159..99b96ac 100644 --- a/hw/xics.h +++ b/hw/xics.h @@ -36,8 +36,9 @@ enum xics_irq_type { XICS_LSI, /* Level-signalled interrupt */ }; -qemu_irq xics_assign_irq(struct icp_state *icp, int irq, - enum xics_irq_type type); +qemu_irq xics_get_qirq(struct icp_state *icp, int irq); +void xics_set_irq_type(struct icp_state *icp, int irq, + enum xics_irq_type type); struct icp_state *xics_system_init(int nr_irqs);