From patchwork Sat Jun 13 07:52:14 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yu Zhao X-Patchwork-Id: 30032 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 n5D7qD0o004216 for ; Sat, 13 Jun 2009 07:52:13 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752581AbZFMHwJ (ORCPT ); Sat, 13 Jun 2009 03:52:09 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753313AbZFMHwJ (ORCPT ); Sat, 13 Jun 2009 03:52:09 -0400 Received: from mga01.intel.com ([192.55.52.88]:21520 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752581AbZFMHwI (ORCPT ); Sat, 13 Jun 2009 03:52:08 -0400 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga101.fm.intel.com with ESMTP; 13 Jun 2009 00:38:53 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.42,213,1243839600"; d="scan'208";a="698997388" Received: from yzhao-otc.sh.intel.com ([10.239.48.81]) by fmsmga001.fm.intel.com with ESMTP; 13 Jun 2009 00:55:27 -0700 From: Yu Zhao To: jbarnes@virtuousgeek.org Cc: linux-pci@vger.kernel.org, Yu Zhao Subject: [PATCH resend 2/3] PCI: support PM D0hot->D3 transition reset Date: Sat, 13 Jun 2009 15:52:14 +0800 Message-Id: <1244879535-3351-2-git-send-email-yu.zhao@intel.com> X-Mailer: git-send-email 1.6.1 In-Reply-To: <1244879535-3351-1-git-send-email-yu.zhao@intel.com> References: <1244879535-3351-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 PM 1.2 specifies that the device will perform an internal reset upon transitioning from D3hot to D0 when the NO_SOFT_RESET bit is clear. This method can be used to reset a function if neither PCIe FLR nor PCI AF FLR are supported. Reviewed-by: Kenji Kaneshige Signed-off-by: Yu Zhao --- drivers/pci/pci.c | 34 ++++++++++++++++++++++++++++++++++ 1 files changed, 34 insertions(+), 0 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6a052ad..2e58acc 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2132,6 +2132,36 @@ clear: return 0; } +static int pci_pm_reset(struct pci_dev *dev, int probe) +{ + u16 csr; + + if (!dev->pm_cap) + return -ENOTTY; + + pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &csr); + if (csr & PCI_PM_CTRL_NO_SOFT_RESET) + return -ENOTTY; + + if (probe) + return 0; + + if (dev->current_state != PCI_D0) + return -EINVAL; + + csr &= ~PCI_PM_CTRL_STATE_MASK; + csr |= PCI_D3hot; + pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); + msleep(pci_pm_d3_delay); + + csr &= ~PCI_PM_CTRL_STATE_MASK; + csr |= PCI_D0; + pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); + msleep(pci_pm_d3_delay); + + return 0; +} + static int pci_dev_reset(struct pci_dev *dev, int probe) { int rc; @@ -2149,6 +2179,10 @@ static int pci_dev_reset(struct pci_dev *dev, int probe) goto done; rc = pci_af_flr(dev, probe); + if (rc != -ENOTTY) + goto done; + + rc = pci_pm_reset(dev, probe); done: if (!probe) { up(&dev->dev.sem);