From patchwork Wed Dec 8 08:46:25 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Isaku Yamahata X-Patchwork-Id: 74654 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 49835B70B8 for ; Wed, 8 Dec 2010 19:48:08 +1100 (EST) Received: from localhost ([127.0.0.1]:58521 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PQFgy-0002GY-Hm for incoming@patchwork.ozlabs.org; Wed, 08 Dec 2010 03:48:04 -0500 Received: from [140.186.70.92] (port=43062 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PQFff-0002DF-Qo for qemu-devel@nongnu.org; Wed, 08 Dec 2010 03:46:46 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PQFfY-0000ZN-4g for qemu-devel@nongnu.org; Wed, 08 Dec 2010 03:46:43 -0500 Received: from mail.valinux.co.jp ([210.128.90.3]:47632) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PQFfX-0000Yz-HH for qemu-devel@nongnu.org; Wed, 08 Dec 2010 03:46:36 -0500 Received: from ps.local.valinux.co.jp (vagw.valinux.co.jp [210.128.90.14]) by mail.valinux.co.jp (Postfix) with SMTP id 9A77B27FBB; Wed, 8 Dec 2010 17:46:33 +0900 (JST) Received: (nullmailer pid 32029 invoked by uid 1000); Wed, 08 Dec 2010 08:46:28 -0000 From: Isaku Yamahata To: qemu-devel@nongnu.org Date: Wed, 8 Dec 2010 17:46:25 +0900 Message-Id: <6f3293fffaa9ca13d3cd18f28afe4ed08ec3e167.1291797833.git.yamahata@valinux.co.jp> X-Mailer: git-send-email 1.7.1.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: yamahata@valinux.co.jp, mst@redhat.com Subject: [Qemu-devel] [PATTCH v2 3/6] pci/aer: fix error injection 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 From: Michael S. Tsirkin Fix the injection logic upon aer message to follow 6.2.4.1.2 more closely: specifically only send an msi interrupt when the logical or of the enabled bits changed, not when a bit which was previously clear becomes set. Signed-off-by: Michael S. Tsirkin Signed-off-by: Isaku Yamahata --- Changes v1 -> v2: - reorder --- hw/pcie_aer.c | 51 +++++++++++++++++++++++++++++++++++---------------- 1 files changed, 35 insertions(+), 16 deletions(-) diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c index 80cc438..bc98da0 100644 --- a/hw/pcie_aer.c +++ b/hw/pcie_aer.c @@ -257,6 +257,22 @@ static unsigned int pcie_aer_root_get_vector(PCIDevice *dev) return (root_status & PCI_ERR_ROOT_IRQ) >> PCI_ERR_ROOT_IRQ_SHIFT; } +/* Given a status register, get corresponding bits in the command register */ +static uint32_t pcie_aer_status_to_cmd(uint32_t status) +{ + uint32_t cmd = 0; + if (status & PCI_ERR_ROOT_COR_RCV) { + cmd |= PCI_ERR_ROOT_CMD_COR_EN; + } + if (status & PCI_ERR_ROOT_NONFATAL_RCV) { + cmd |= PCI_ERR_ROOT_CMD_NONFATAL_EN; + } + if (status & PCI_ERR_ROOT_FATAL_RCV) { + cmd |= PCI_ERR_ROOT_CMD_FATAL_EN; + } + return cmd; +} + /* * return value: * true: error message is sent up @@ -272,14 +288,14 @@ static bool pcie_aer_msg_root_port(PCIDevice *dev, const PCIEAERMsg *msg) uint16_t cmd; uint8_t *aer_cap; uint32_t root_cmd; - uint32_t root_status; + uint32_t root_status, prev_status; bool msi_trigger; msg_sent = false; cmd = pci_get_word(dev->config + PCI_COMMAND); aer_cap = dev->config + dev->exp.aer_cap; root_cmd = pci_get_long(aer_cap + PCI_ERR_ROOT_COMMAND); - root_status = pci_get_long(aer_cap + PCI_ERR_ROOT_STATUS); + prev_status = root_status = pci_get_long(aer_cap + PCI_ERR_ROOT_STATUS); msi_trigger = false; if (cmd & PCI_COMMAND_SERR) { @@ -337,20 +353,23 @@ static bool pcie_aer_msg_root_port(PCIDevice *dev, const PCIEAERMsg *msg) } pci_set_long(aer_cap + PCI_ERR_ROOT_STATUS, root_status); - if (root_cmd & msg->severity) { - /* 6.2.4.1.2 Interrupt Generation */ - if (msix_enabled(dev)) { - if (msi_trigger) { - msix_notify(dev, pcie_aer_root_get_vector(dev)); - } - } else if (msi_enabled(dev)) { - if (msi_trigger) { - msi_notify(dev, pcie_aer_root_get_vector(dev)); - } - } else { - qemu_set_irq(dev->irq[dev->exp.aer_intx], 1); - } - msg_sent = true; + /* 6.2.4.1.2 Interrupt Generation */ + /* All the above did was set some bits in the status register. + * Specifically these that match message severity. + * The below code relies on this fact. */ + if (!(root_cmd & msg->severity) || + (pcie_aer_status_to_cmd(prev_status) & root_cmd)) { + /* Condition is not being set or was already true so nothing to do. */ + return msg_sent; + } + + msg_sent = true; + if (msix_enabled(dev)) { + msix_notify(dev, pcie_aer_root_get_vector(dev)); + } else if (msi_enabled(dev)) { + msi_notify(dev, pcie_aer_root_get_vector(dev)); + } else { + qemu_set_irq(dev->irq[dev->exp.aer_intx], 1); } return msg_sent; }