From patchwork Fri Oct 28 22:58:16 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keith Busch X-Patchwork-Id: 9402797 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id BF5C86022E for ; Fri, 28 Oct 2016 22:47:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AF1722A8D3 for ; Fri, 28 Oct 2016 22:47:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A43052A8D5; Fri, 28 Oct 2016 22:47:41 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1D2B02A8D4 for ; Fri, 28 Oct 2016 22:47:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754380AbcJ1Wri (ORCPT ); Fri, 28 Oct 2016 18:47:38 -0400 Received: from mga01.intel.com ([192.55.52.88]:46396 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755983AbcJ1Wri (ORCPT ); Fri, 28 Oct 2016 18:47:38 -0400 Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga101.fm.intel.com with ESMTP; 28 Oct 2016 15:47:37 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.31,560,1473145200"; d="scan'208";a="185150154" Received: from unknown (HELO localhost.lm.intel.com) ([10.232.112.96]) by fmsmga004.fm.intel.com with ESMTP; 28 Oct 2016 15:47:37 -0700 From: Keith Busch To: linux-pci@vger.kernel.org, Bjorn Helgaas Cc: Lukas Wunner , Wei Zhang , Keith Busch Subject: [PATCHv4 next 2/3] pci: No config access for removed devices Date: Fri, 28 Oct 2016 18:58:16 -0400 Message-Id: <1477695497-6207-3-git-send-email-keith.busch@intel.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1477695497-6207-1-git-send-email-keith.busch@intel.com> References: <1477695497-6207-1-git-send-email-keith.busch@intel.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP If we've detected that the PCI device is removed, there is no need to access the device's config space. This patch has all the device config reads and writes return error when in such a state. If the device is not present on a config read, the value returned will be set to all 1's. This is the same as what hardware is expected to return when accessing a removed device, but software can do this faster without relying on hardware. When checking if a device is present, we short-cut the removal by returning the known state instead of querying the bus. Signed-off-by: Keith Busch Cc: Lukas Wunner --- drivers/pci/pci.c | 2 ++ include/linux/pci.h | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index ba34907..c412095 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4966,6 +4966,8 @@ bool pci_device_is_present(struct pci_dev *pdev) { u32 v; + if (pdev->is_removed) + return false; return pci_bus_read_dev_vendor_id(pdev->bus, pdev->devfn, &v, 0); } EXPORT_SYMBOL_GPL(pci_device_is_present); diff --git a/include/linux/pci.h b/include/linux/pci.h index 2115d19..a92eedb 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -936,28 +936,46 @@ struct pci_ops *pci_bus_set_ops(struct pci_bus *bus, struct pci_ops *ops); static inline int pci_read_config_byte(const struct pci_dev *dev, int where, u8 *val) { + if (unlikely(dev->is_removed)) { + *val = ~0; + return -ENODEV; + } return pci_bus_read_config_byte(dev->bus, dev->devfn, where, val); } static inline int pci_read_config_word(const struct pci_dev *dev, int where, u16 *val) { + if (unlikely(dev->is_removed)) { + *val = ~0; + return -ENODEV; + } return pci_bus_read_config_word(dev->bus, dev->devfn, where, val); } static inline int pci_read_config_dword(const struct pci_dev *dev, int where, u32 *val) { + if (unlikely(dev->is_removed)) { + *val = ~0; + return -ENODEV; + } return pci_bus_read_config_dword(dev->bus, dev->devfn, where, val); } static inline int pci_write_config_byte(const struct pci_dev *dev, int where, u8 val) { + if (unlikely(dev->is_removed)) + return -ENODEV; return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val); } static inline int pci_write_config_word(const struct pci_dev *dev, int where, u16 val) { + if (unlikely(dev->is_removed)) + return -ENODEV; return pci_bus_write_config_word(dev->bus, dev->devfn, where, val); } static inline int pci_write_config_dword(const struct pci_dev *dev, int where, u32 val) { + if (unlikely(dev->is_removed)) + return -ENODEV; return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val); }