From patchwork Fri Jun 18 06:58:34 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Isaku Yamahata X-Patchwork-Id: 56140 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 53E38B7D5B for ; Fri, 18 Jun 2010 17:05:24 +1000 (EST) Received: from localhost ([127.0.0.1]:46718 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OPVdd-00030C-7I for incoming@patchwork.ozlabs.org; Fri, 18 Jun 2010 03:05:17 -0400 Received: from [140.186.70.92] (port=58461 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OPVan-0001Wc-K9 for qemu-devel@nongnu.org; Fri, 18 Jun 2010 03:02:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OPVak-0003Hk-Uz for qemu-devel@nongnu.org; Fri, 18 Jun 2010 03:02:21 -0400 Received: from mail.valinux.co.jp ([210.128.90.3]:53201) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OPVak-0003Gx-Dj for qemu-devel@nongnu.org; Fri, 18 Jun 2010 03:02:18 -0400 Received: from ps.local.valinux.co.jp (vagw.valinux.co.jp [210.128.90.14]) by mail.valinux.co.jp (Postfix) with SMTP id 4D3CB1072C5; Fri, 18 Jun 2010 16:02:16 +0900 (JST) Received: (nullmailer pid 28771 invoked by uid 1000); Fri, 18 Jun 2010 06:58:35 -0000 From: Isaku Yamahata To: qemu-devel@nongnu.org Date: Fri, 18 Jun 2010 15:58:34 +0900 Message-Id: X-Mailer: git-send-email 1.6.6.1 In-Reply-To: References: In-Reply-To: References: X-Virus-Scanned: clamav-milter 0.95.2 at va-mail.local.valinux.co.jp X-Virus-Status: Clean X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) Cc: blauwirbel@gmail.com, yamahata@valinux.co.jp, mst@redhat.com Subject: [Qemu-devel] [PATCH v3 2/3] pci: set PCI multi-function bit appropriately. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Set PCI multi-function bit appropriately. PCI address, devfn ,is exported to users as addr property, so users can populate pci function(PCIDevice in qemu) at arbitrary devfn. It means each function(PCIDevice) don't know whether pci device (PCIDevice[8]) is multi function or not. So this patch makes pci generic layer set the bit appropriately. Signed-off-by: Isaku Yamahata --- changes v2 -> v3: - introduce PCI_FUNC_MAX - more commit log changes v1 -> v2: don't set header type register in configuration space. --- hw/pci.c | 27 +++++++++++++++++++++++++++ hw/pci.h | 1 + 2 files changed, 28 insertions(+), 0 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index 62308df..d17770e 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -574,6 +574,32 @@ static void pci_init_wmask_bridge(PCIDevice *d) pci_set_word(d->wmask + PCI_BRIDGE_CONTROL, 0xffff); } +static void pci_init_multifunction(PCIBus *bus, PCIDevice *dev) +{ + uint8_t slot = PCI_SLOT(dev->devfn); + uint8_t func; + + /* we are here before bus->devices[dev->devfn] = dev */ + assert(bus->devices[dev->devfn] == NULL); + + for (func = 0; func < PCI_FUNC_MAX; ++func) { + if (bus->devices[PCI_DEVFN(slot, func)]) { + break; + } + } + if (func == PCI_FUNC_MAX) { + return; + } + + for (func = 0; func < PCI_FUNC_MAX; ++func) { + if (bus->devices[PCI_DEVFN(slot, func)]) { + bus->devices[PCI_DEVFN(slot, func)]->config[PCI_HEADER_TYPE] |= + PCI_HEADER_TYPE_MULTI_FUNCTION; + } + } + dev->config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION; +} + static void pci_config_alloc(PCIDevice *pci_dev) { int config_size = pci_config_size(pci_dev); @@ -627,6 +653,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, if (is_bridge) { pci_init_wmask_bridge(pci_dev); } + pci_init_multifunction(bus, pci_dev); if (!config_read) config_read = pci_default_read_config; diff --git a/hw/pci.h b/hw/pci.h index 4d682d4..76adc66 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -14,6 +14,7 @@ #define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) #define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) #define PCI_FUNC(devfn) ((devfn) & 0x07) +#define PCI_FUNC_MAX 8 /* Class, Vendor and Device IDs from Linux's pci_ids.h */ #include "pci_ids.h"