From patchwork Fri Jul 11 07:21:10 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alvise Rigo X-Patchwork-Id: 369018 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 8FBFE1400E6 for ; Fri, 11 Jul 2014 17:24:21 +1000 (EST) Received: from localhost ([::1]:42669 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X5VBr-0003KU-OX for incoming@patchwork.ozlabs.org; Fri, 11 Jul 2014 03:24:19 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40531) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X5V9N-0007aB-5t for qemu-devel@nongnu.org; Fri, 11 Jul 2014 03:21:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1X5V9G-0006E9-Bp for qemu-devel@nongnu.org; Fri, 11 Jul 2014 03:21:45 -0400 Received: from mail-we0-f169.google.com ([74.125.82.169]:42313) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X5V9G-0006Dc-0x for qemu-devel@nongnu.org; Fri, 11 Jul 2014 03:21:38 -0400 Received: by mail-we0-f169.google.com with SMTP id t60so605952wes.0 for ; Fri, 11 Jul 2014 00:21:35 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=TqLlyF6AB5gCZMkqWruGpnBBdzU5xwewYlJOosu6Ego=; b=j4sXGl5Alz+ieiS+GsZStb+QNzxA7Fng7CMBbJUmboI1B4RdKiibIpTEwty/6ludNj pHjrxuxUeYhQEinFqnptYY5a4TMDl6cfghb698IQNhXADz0Kx3wP5Mjv7FQnke+Roi2u +nv73KKb41AbKKT9BSBfB/6SuATFFF+P01oz9zg74x4X6ysW7q4qICCO1Ljv7KAy/i7d 3QFttrKFWDTqgi3P7O3FbERCgRVdfCkndd4PvY5RT7V7Q5fxdTZSPLTZ4ogD/EQ+Na+y rOPSGiJzmlAuKSOr4i9dvQcmZp6xfNZODMjrKdex/jZmyfiJLoHdxz72CERAt3tsFM49 DXiQ== X-Gm-Message-State: ALoCoQkesyquNNmUSoWluGIYKoNZzFwumdy4tZqZhSdkC5tTKUpUCv6TEnXEzSMLkDsrazDRuJVR X-Received: by 10.180.184.36 with SMTP id er4mr2553008wic.37.1405063295821; Fri, 11 Jul 2014 00:21:35 -0700 (PDT) Received: from localhost.localdomain (AGrenoble-651-1-561-138.w90-52.abo.wanadoo.fr. [90.52.105.138]) by mx.google.com with ESMTPSA id fc7sm3310882wjc.37.2014.07.11.00.21.34 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 11 Jul 2014 00:21:34 -0700 (PDT) From: Alvise Rigo To: qemu-devel@nongnu.org, rob.herring@linaro.org Date: Fri, 11 Jul 2014 09:21:10 +0200 Message-Id: <1405063270-18902-9-git-send-email-a.rigo@virtualopensystems.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1405063270-18902-1-git-send-email-a.rigo@virtualopensystems.com> References: <1405063270-18902-1-git-send-email-a.rigo@virtualopensystems.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 74.125.82.169 Cc: tech@virtualopensystems.com, Alvise Rigo Subject: [Qemu-devel] [RFC PATCH 8/8] generic_pci: add interrupt map structures 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 Create a generic_pci_host state to include the IRQ map to be used when resolving the PCI interrupts. These structures can be useful to support more complicated scenarios, like with multi functions PCI devices. Signed-off-by: Alvise Rigo --- hw/pci-host/generic-pci.c | 37 ++++++++++++++++++++++++++----------- include/hw/pci-host/pci_generic.h | 15 +++++++++++++-- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/hw/pci-host/generic-pci.c b/hw/pci-host/generic-pci.c index 1bde69c..24c0ce8 100644 --- a/hw/pci-host/generic-pci.c +++ b/hw/pci-host/generic-pci.c @@ -62,14 +62,19 @@ static void pci_generic_host_init(Object *obj) PCI_DEVFN(0, 0), TYPE_PCIE_BUS); h->bus = &s->pci_bus; - object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_GENERIC_PCI_HOST); - qdev_set_parent_bus(DEVICE(&s->pci_dev), BUS(&s->pci_bus)); + object_initialize(&s->pci_gen, sizeof(s->pci_gen), TYPE_GENERIC_PCI_HOST); + qdev_set_parent_bus(DEVICE(&s->pci_gen), BUS(&s->pci_bus)); } static int generic_pci_map_irq_fn(PCIDevice *pci_dev, int pin) { + BusState *bus = qdev_get_parent_bus(&pci_dev->qdev); + PCIBus *pci_bus = PCI_BUS(bus); + PCIDevice *pdev = pci_bus->devices[PCI_DEVFN(0, 0)]; + GenericPCIHostState *gps = PCI_GEN_HOST(pdev); + if (!pin) { - return PCI_SLOT(pci_dev->devfn); + return gps->irqmap.slot_idx_map[PCI_SLOT(pci_dev->devfn)]; } hw_error("generic_pci: only one pin per device supported."); @@ -117,7 +122,7 @@ static void pci_generic_host_realize(DeviceState *dev, Error **errp) sysbus_init_mmio(sbd, &s->pci_mem_window); /* TODO Remove once realize propagates to child devices. */ - object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp); + object_property_set_bool(OBJECT(&s->pci_gen), true, "realized", errp); } static void pci_generic_host_class_init(ObjectClass *klass, void *data) @@ -146,11 +151,11 @@ struct dt_irq_mapping { /* Generate the irq_mapping data and return the number of the device attached * to the device bus. * */ -static int generate_int_mapping(struct dt_irq_mapping *irq_map) +static int generate_int_mapping(struct dt_irq_mapping *irq_map, PCIVPBState *s) { BusState *inner_bus; BusChild *inner; - int num_slots = 0; + int slot_count = 0; uint64_t *data_ptr = irq_map->data; QLIST_FOREACH(inner_bus, &irq_map->dev->child_bus, sibling) { @@ -158,19 +163,29 @@ static int generate_int_mapping(struct dt_irq_mapping *irq_map) DeviceState *dev = inner->child; PCIDevice *pdev = PCI_DEVICE(dev); int pci_slot = PCI_SLOT(pdev->devfn); + uint8_t *slot_idx = s->pci_gen.irqmap.slot_idx_map; + uint8_t *slot_irq = s->pci_gen.irqmap.slot_irq_map; + + if (slot_count > MAX_PCI_DEVICES) { + hw_error("generic_pci: too many PCI devices."); + } + + /* Every PCI slot has one interrupt mapped. */ + slot_idx[pci_slot] = slot_count; + slot_irq[slot_count] = irq_map->base_irq_num + slot_count; uint64_t buffer[IRQ_MAPPING_CELLS] = {1, pci_slot << 11, 2, 0x00000000, 1, 0x1, - 1, irq_map->gic_phandle, 1, 0, 1, irq_map->base_irq_num + pci_slot, + 1, irq_map->gic_phandle, 1, 0, 1, slot_irq[slot_count], 1, 0x1}; memcpy(data_ptr, buffer, IRQ_MAPPING_CELLS * sizeof(*buffer)); - num_slots++; + slot_count++; data_ptr += IRQ_MAPPING_CELLS; } } - return num_slots; + return slot_count; } static void generate_dt_node(DeviceState *dev) @@ -215,7 +230,7 @@ static void generate_dt_node(DeviceState *dev) .data = int_mapping_data }; - num_dev = generate_int_mapping(&dt_map); + num_dev = generate_int_mapping(&dt_map, s); qemu_fdt_setprop_sized_cells_from_array(fdt, nodename, "interrupt-map", (num_dev * IRQ_MAPPING_CELLS)/2, int_mapping_data); @@ -228,7 +243,7 @@ static void generate_dt_node(DeviceState *dev) static const TypeInfo pci_generic_host_info = { .name = TYPE_GENERIC_PCI_HOST, .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCIDevice), + .instance_size = sizeof(GenericPCIHostState), .class_init = pci_generic_host_class_init, }; diff --git a/include/hw/pci-host/pci_generic.h b/include/hw/pci-host/pci_generic.h index 039549f..c65bc6c 100644 --- a/include/hw/pci-host/pci_generic.h +++ b/include/hw/pci-host/pci_generic.h @@ -14,6 +14,17 @@ struct dt_data { }; typedef struct { + PCIDevice parent_obj; + + struct irqmap { + /* slot_idx_map[i] = index inside slot_irq_map for device at slot i */ + uint8_t slot_idx_map[PCI_SLOT_MAX]; + /* slot_irq_map[i] = irq num. of the i-th device attached to the bus */ + uint8_t slot_irq_map[MAX_PCI_DEVICES]; + } irqmap; +} GenericPCIHostState; + +typedef struct { PCIHostState parent_obj; qemu_irq irq[MAX_PCI_DEVICES]; @@ -27,7 +38,7 @@ typedef struct { MemoryRegion pci_io_window; MemoryRegion pci_mem_window; PCIBus pci_bus; - PCIDevice pci_dev; + GenericPCIHostState pci_gen; /* Device tree data set by the machine */ struct dt_data dt_data; @@ -45,7 +56,7 @@ typedef struct GenericPCIClass { #define TYPE_GENERIC_PCI_HOST "generic_pci_host" #define PCI_GEN_HOST(obj) \ - OBJECT_CHECK(PCIDevice, (obj), TYPE_GENERIC_PCIHOST) + OBJECT_CHECK(GenericPCIHostState, (obj), TYPE_GENERIC_PCI_HOST) #define GENERIC_PCI_CLASS(klass) \ OBJECT_CLASS_CHECK(GenericPCIClass, (klass), TYPE_GENERIC_PCI)