From patchwork Mon Jul 10 15:52:29 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Zyngier X-Patchwork-Id: 9833335 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 8578360318 for ; Mon, 10 Jul 2017 15:53:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 78DE8285FB for ; Mon, 10 Jul 2017 15:53:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 778F128616; Mon, 10 Jul 2017 15:53:59 +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=unavailable 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 4EC84285FC for ; Mon, 10 Jul 2017 15:53:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932097AbdGJPxS (ORCPT ); Mon, 10 Jul 2017 11:53:18 -0400 Received: from foss.arm.com ([217.140.101.70]:37232 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754203AbdGJPwj (ORCPT ); Mon, 10 Jul 2017 11:52:39 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 613061596; Mon, 10 Jul 2017 08:52:39 -0700 (PDT) Received: from approximate.cambridge.arm.com (approximate.cambridge.arm.com [10.1.207.16]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 3B2793F5B0; Mon, 10 Jul 2017 08:52:38 -0700 (PDT) From: Marc Zyngier To: Bjorn Helgaas , Mathias Nyman , Greg Kroah-Hartman Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, Ard Biesheuvel Subject: [PATCH 1/2] PCI: Implement pci_reset_function_locked Date: Mon, 10 Jul 2017 16:52:29 +0100 Message-Id: <20170710155230.8622-2-marc.zyngier@arm.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170710155230.8622-1-marc.zyngier@arm.com> References: <20170710155230.8622-1-marc.zyngier@arm.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 The implementation of PCI workarounds may require that the device is reset from its probe function. This implies that the PCI device lock is already held, and makes calling pci_reset_function impossible (since it will itself try to take that lock). This patch introduces pci_reset_function_locked, which is the equivalent of pci_reset_function, except that it requires the PCI device lock to be already held by the caller. Signed-off-by: Marc Zyngier --- drivers/pci/pci.c | 35 +++++++++++++++++++++++++++++++++++ include/linux/pci.h | 1 + 2 files changed, 36 insertions(+) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 563901cd9c06..a2c3e8b94f65 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4287,6 +4287,41 @@ int pci_reset_function(struct pci_dev *dev) EXPORT_SYMBOL_GPL(pci_reset_function); /** + * pci_reset_function_locked - quiesce and reset a PCI device function + * @dev: PCI device to reset + * + * Some devices allow an individual function to be reset without affecting + * other functions in the same device. The PCI device must be responsive + * to PCI config space in order to use this function. + * + * This function does not just reset the PCI portion of a device, but + * clears all the state associated with the device. This function differs + * from __pci_reset_function in that it saves and restores device state + * over the reset. it also differs from pci_reset_function in that it + * requires the PCI device lock to be held. + * + * Returns 0 if the device function was successfully reset or negative if the + * device doesn't support resetting a single function. + */ +int pci_reset_function_locked(struct pci_dev *dev) +{ + int rc; + + rc = pci_dev_reset(dev, 1); + if (rc) + return rc; + + pci_dev_save_and_disable(dev); + + rc = __pci_dev_reset(dev, 0); + + pci_dev_restore(dev); + + return rc; +} +EXPORT_SYMBOL_GPL(pci_reset_function_locked); + +/** * pci_try_reset_function - quiesce and reset a PCI device function * @dev: PCI device to reset * diff --git a/include/linux/pci.h b/include/linux/pci.h index 8039f9f0ca05..16be18678ca1 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1049,6 +1049,7 @@ void pcie_flr(struct pci_dev *dev); int __pci_reset_function(struct pci_dev *dev); int __pci_reset_function_locked(struct pci_dev *dev); int pci_reset_function(struct pci_dev *dev); +int pci_reset_function_locked(struct pci_dev *dev); int pci_try_reset_function(struct pci_dev *dev); int pci_probe_reset_slot(struct pci_slot *slot); int pci_reset_slot(struct pci_slot *slot);