From patchwork Mon May 25 02:19:10 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yu Zhao X-Patchwork-Id: 25719 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n4P2J71V028701 for ; Mon, 25 May 2009 02:19:08 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752099AbZEYCTF (ORCPT ); Sun, 24 May 2009 22:19:05 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1750908AbZEYCTF (ORCPT ); Sun, 24 May 2009 22:19:05 -0400 Received: from mga11.intel.com ([192.55.52.93]:22950 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752099AbZEYCTD (ORCPT ); Sun, 24 May 2009 22:19:03 -0400 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga102.fm.intel.com with ESMTP; 24 May 2009 19:12:51 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.41,242,1241420400"; d="scan'208";a="693248335" Received: from yzhao-otc.sh.intel.com ([10.239.48.165]) by fmsmga001.fm.intel.com with ESMTP; 24 May 2009 19:22:35 -0700 From: Yu Zhao To: jbarnes@virtuousgeek.org Cc: linux-pci@vger.kernel.org, Yu Zhao Subject: [PATCH 3/3] PCI: support Secondary Bus Reset Date: Mon, 25 May 2009 10:19:10 +0800 Message-Id: <1243217950-4030-3-git-send-email-yu.zhao@intel.com> X-Mailer: git-send-email 1.6.1 In-Reply-To: <1243217950-4030-1-git-send-email-yu.zhao@intel.com> References: <1243217950-4030-1-git-send-email-yu.zhao@intel.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org PCI-to-PCI Bridge 1.2 specifies that the Secondary Bus Reset bit can force the assertion of RST# on the secondary interface, which can be used to reset all devices including subordinates under this bus. This can be used to reset a function if this function is the only device under this bus. Signed-off-by: Yu Zhao --- drivers/pci/pci.c | 31 +++++++++++++++++++++++++++++++ 1 files changed, 31 insertions(+), 0 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 19a5479..3711e74 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2160,6 +2160,33 @@ static int pci_pm_reset(struct pci_dev *dev, int probe) return 0; } +static int pci_secondary_bus_reset(struct pci_dev *dev, int probe) +{ + u16 ctrl; + struct pci_dev *pdev; + + if (dev->subordinate) + return -ENOTTY; + + list_for_each_entry(pdev, &dev->bus->devices, bus_list) + if (pdev != dev) + return -ENOTTY; + + if (probe) + return 0; + + pci_read_config_word(dev->bus->self, PCI_BRIDGE_CONTROL, &ctrl); + ctrl |= PCI_BRIDGE_CTL_BUS_RESET; + pci_write_config_word(dev->bus->self, PCI_BRIDGE_CONTROL, ctrl); + msleep(100); + + ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET; + pci_write_config_word(dev->bus->self, PCI_BRIDGE_CONTROL, ctrl); + msleep(100); + + return 0; +} + static int pci_dev_reset(struct pci_dev *dev, int probe) { int rc; @@ -2181,6 +2208,10 @@ static int pci_dev_reset(struct pci_dev *dev, int probe) goto done; rc = pci_pm_reset(dev, probe); + if (rc != -ENOTTY) + goto done; + + rc = pci_secondary_bus_reset(dev, probe); done: if (!probe) { up(&dev->dev.sem);