From patchwork Thu Aug 29 02:52:27 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhenzhong Duan X-Patchwork-Id: 2851089 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: patchwork-linux-pci@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 7C1FC9F271 for ; Thu, 29 Aug 2013 02:52:34 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6F16C202F9 for ; Thu, 29 Aug 2013 02:52:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4F3B120272 for ; Thu, 29 Aug 2013 02:52:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752656Ab3H2Cwb (ORCPT ); Wed, 28 Aug 2013 22:52:31 -0400 Received: from aserp1040.oracle.com ([141.146.126.69]:20390 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751772Ab3H2Cwa (ORCPT ); Wed, 28 Aug 2013 22:52:30 -0400 Received: from ucsinet22.oracle.com (ucsinet22.oracle.com [156.151.31.94]) by aserp1040.oracle.com (Sentrion-MTA-4.3.1/Sentrion-MTA-4.3.1) with ESMTP id r7T2qOHe025892 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 29 Aug 2013 02:52:25 GMT Received: from userz7022.oracle.com (userz7022.oracle.com [156.151.31.86]) by ucsinet22.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id r7T2qN9D001813 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Thu, 29 Aug 2013 02:52:23 GMT Received: from abhmt104.oracle.com (abhmt104.oracle.com [141.146.116.56]) by userz7022.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id r7T2qNnQ001805; Thu, 29 Aug 2013 02:52:23 GMT Received: from [192.168.1.100] (/117.79.232.230) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Wed, 28 Aug 2013 19:52:22 -0700 Message-ID: <521EB76B.8090903@oracle.com> Date: Thu, 29 Aug 2013 10:52:27 +0800 From: Zhenzhong Duan Reply-To: zhenzhong.duan@oracle.com Organization: oracle User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:17.0) Gecko/20130801 Thunderbird/17.0.8 MIME-Version: 1.0 To: "linux-pci@vger.kernel.org" , "linux-kernel@vger.kernel.org" , xen-devel CC: Bjorn Helgaas , Konrad Rzeszutek Wilk , Feng Jin , Sucheta Chakraborty Subject: [PATCH 2/3 v3] Refactor MSI restore call-chain to drop unnecessary argument X-Source-IP: ucsinet22.oracle.com [156.151.31.94] Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Spam-Status: No, score=-9.4 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Driver init call graph under baremetal: driver_init-> msix_capability_init-> msix_program_entries-> msix_mask_irq-> entry->masked = 1 request_irq-> __setup_irq-> irq_startup-> unmask_msi_irq-> msix_mask_irq-> entry->masked = 0 So entry->masked is always updated with newest value and its value could be used to restore to mask register in device. But in initial domain (aka priviliged guest), it's different. Driver init call graph under initial domain: driver_init-> msix_capability_init-> msix_program_entries-> msix_mask_irq-> entry->masked = 1 request_irq-> __setup_irq-> irq_startup-> __startup_pirq-> EVTCHNOP_bind_pirq hypercall (trap into Xen) [Xen:] pirq_guest_bind-> startup_msi_irq-> unmask_msi_irq-> msi_set_mask_bit-> entry->msi_attrib.masked = 0 So entry->msi_attrib.masked in xen side always has newest value. entry->masked in initial domain is untouched and is 1 after msix_capability_init. Based on above, it's Xen's duty to restore entry->msi_attrib.masked to device, but with current code, entry->masked is used and MSI-x interrupt is masked. Before patch, restore call graph under initial domain: pci_reset_function-> pci_restore_state-> __pci_restore_msix_state-> arch_restore_msi_irqs-> xen_initdom_restore_msi_irqs-> PHYSDEVOP_restore_msi hypercall (first mask restore) msix_mask_irq(entry, entry->masked) (second mask restore) So msix_mask_irq call in initial domain call graph needs to be removed. Based on this we can move the restore of the mask in default_restore_msi_irqs which would avoid restoring the invalid mask under Xen. Furthermore this simplifies the API by making everything related to restoring an MSI be in the platform specific APIs instead of just parts of it. After patch, restore call graph under initial domain: pci_reset_function-> pci_restore_state-> __pci_restore_msix_state-> arch_restore_msi_irqs-> xen_initdom_restore_msi_irqs-> PHYSDEVOP_restore_msi hypercall (first mask restore) Logic for baremetal is not changed. Before patch, restore call graph under baremetal: pci_reset_function-> pci_restore_state-> __pci_restore_msix_state-> arch_restore_msi_irqs-> default_restore_msi_irqs-> msix_mask_irq(entry, entry->masked) (first mask restore) After patch, restore call graph under baremetal: pci_reset_function-> pci_restore_state-> __pci_restore_msix_state-> arch_restore_msi_irqs-> default_restore_msi_irqs-> msix_mask_irq(entry, entry->masked) (first mask restore) The process for MSI code is similiar. -v3: Update patch description per Konrad suggestion, thanks. Tested-by: Sucheta Chakraborty Signed-off-by: Zhenzhong Duan --- drivers/pci/msi.c | 17 ++++++++++++++--- 1 files changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 87223ae..922fb49 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -216,6 +216,8 @@ void unmask_msi_irq(struct irq_data *data) #ifdef HAVE_DEFAULT_MSI_RESTORE_IRQS void default_restore_msi_irqs(struct pci_dev *dev, int irq) { + int pos; + u16 control; struct msi_desc *entry; entry = NULL; @@ -228,8 +230,19 @@ void default_restore_msi_irqs(struct pci_dev *dev, int irq) entry = irq_get_msi_desc(irq); } - if (entry) + if (entry) { write_msi_msg(irq, &entry->msg); + if (dev->msix_enabled) { + msix_mask_irq(entry, entry->masked); + readl(entry->mask_base); + } else { + pos = entry->msi_attrib.pos; + pci_read_config_word(dev, pos + PCI_MSI_FLAGS, + &control); + msi_mask_irq(entry, msi_capable_mask(control), + entry->masked); + } + } } #endif @@ -406,7 +419,6 @@ static void __pci_restore_msi_state(struct pci_dev *dev) arch_restore_msi_irqs(dev, dev->irq); pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control); - msi_mask_irq(entry, msi_capable_mask(control), entry->masked); control &= ~PCI_MSI_FLAGS_QSIZE; control |= (entry->msi_attrib.multiple << 4) | PCI_MSI_FLAGS_ENABLE; pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control); @@ -430,7 +442,6 @@ static void __pci_restore_msix_state(struct pci_dev *dev) list_for_each_entry(entry, &dev->msi_list, list) { arch_restore_msi_irqs(dev, entry->irq); - msix_mask_irq(entry, entry->masked); } control &= ~PCI_MSIX_FLAGS_MASKALL;