From patchwork Fri Jun 4 00:45:48 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brad Peters X-Patchwork-Id: 54530 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from bilbo.ozlabs.org (localhost [127.0.0.1]) by ozlabs.org (Postfix) with ESMTP id 3DF90B7FAF for ; Fri, 4 Jun 2010 10:46:14 +1000 (EST) Received: from e38.co.us.ibm.com (e38.co.us.ibm.com [32.97.110.159]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "e38.co.us.ibm.com", Issuer "Equifax" (verified OK)) by ozlabs.org (Postfix) with ESMTPS id BEF7EB7D59 for ; Fri, 4 Jun 2010 10:46:02 +1000 (EST) Received: from d03relay01.boulder.ibm.com (d03relay01.boulder.ibm.com [9.17.195.226]) by e38.co.us.ibm.com (8.14.4/8.13.1) with ESMTP id o540dP56012793 for ; Thu, 3 Jun 2010 18:39:25 -0600 Received: from d03av04.boulder.ibm.com (d03av04.boulder.ibm.com [9.17.195.170]) by d03relay01.boulder.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id o540jtlY084862 for ; Thu, 3 Jun 2010 18:45:56 -0600 Received: from d03av04.boulder.ibm.com (loopback [127.0.0.1]) by d03av04.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id o540jsYc021162 for ; Thu, 3 Jun 2010 18:45:55 -0600 Received: from [9.65.68.52] (sig-9-65-68-52.mts.ibm.com [9.65.68.52]) by d03av04.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id o540joXY020790 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Thu, 3 Jun 2010 18:45:53 -0600 Message-ID: <4C084CBC.7090002@linux.vnet.ibm.com> Date: Thu, 03 Jun 2010 17:45:48 -0700 From: Brad Peters User-Agent: Thunderbird 2.0.0.23 (X11/20090817) MIME-Version: 1.0 To: linuxppc-dev@lists.ozlabs.org, rlary@linux.vnet.ibm.com Subject: [PATCH] - PCI EEH pci_restore_state fix allowing for repeated adapter recovery per state save X-Enigmail-Version: 0.96.0 OpenPGP: id=D217D861 X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Patch Overview: The pci_restore_state API is shared by both power management code and Extended Error Handling (EEH) code on Power. This patch adds an additional recovery function to pci_restore_state API. The problem being addressed is that Power Management semantics only allow the saved state of PCI device to be restored once per save. With this patch, EEH is able to restore the saved state each time a PCI error is detected, enabling recovery in the face of repeated errors. There was some discussion of renaming the existing and new functions to more clearly break out unconditional restore from the default conditional one, but a name change seemed a heavy-handed change to force on the 200+ current users. Bit more detail: PCI device drivers which support EEH/AER save their pci state once during driver initialization and during EEH/AER error recovery, restore the original saved state. What we found was that our pci driver code would recover from the first EEH error and fail to recover on subsequent EEH errors. This issue results from pci_restore_state() function restoring the state during initialization on the first EEH error. What this patch does is to provide the pci_force_restore_state() for use by PCI drivers which support EEH/AER that require the original saved state be restored each time an EEH/AER error is detected. Signed-off by: Brad Peters Signed-off by: Richard A Lary diff -uNrp -X linux-2.6.34/Documentation/dontdiff linux-2.6.34.orig/drivers/pci/pci.c linux-2.6.34/drivers/pci/pci.c --- linux-2.6.34.orig/drivers/pci/pci.c 2010-05-16 14:17:36.000000000 -0700 +++ linux-2.6.34/drivers/pci/pci.c 2010-05-26 17:16:20.000000000 -0700 @@ -920,19 +920,11 @@ pci_save_state(struct pci_dev *dev) return 0; } -/** - * pci_restore_state - Restore the saved state of a PCI device - * @dev: - PCI device that we're dealing with - */ -int -pci_restore_state(struct pci_dev *dev) +static void __pci_restore_state(struct pci_dev *dev) { int i; u32 val; - if (!dev->state_saved) - return 0; - /* PCI Express register must be restored first */ pci_restore_pcie_state(dev); @@ -953,12 +945,44 @@ pci_restore_state(struct pci_dev *dev) pci_restore_pcix_state(dev); pci_restore_msi_state(dev); pci_restore_iov_state(dev); +} + + +/** + * pci_restore_state - Restore the saved state of a PCI device + * only if dev->state_saved is not 0. Used by + * power management suspend/restore routines. + * @dev: - PCI device that we're dealing with + */ +int +pci_restore_state(struct pci_dev *dev) +{ + + if (!dev->state_saved) + return 0; + + __pci_restore_state(dev); dev->state_saved = false; return 0; } +/** + * pci_force_restore_state - Restore the saved state of a PCI device + * even if dev->state_saved is 0. Used by + * EEH and AER PCI error recovery. + * @dev: - PCI device that we're dealing with + */ +int +pci_force_restore_state(struct pci_dev *dev) +{ + __pci_restore_state(dev); + + return 0; +} + + static int do_pci_enable_device(struct pci_dev *dev, int bars) { int err; @@ -3039,6 +3063,7 @@ EXPORT_SYMBOL(pci_select_bars); EXPORT_SYMBOL(pci_set_power_state); EXPORT_SYMBOL(pci_save_state); EXPORT_SYMBOL(pci_restore_state); +EXPORT_SYMBOL(pci_force_restore_state); EXPORT_SYMBOL(pci_pme_capable); EXPORT_SYMBOL(pci_pme_active); EXPORT_SYMBOL(pci_wake_from_d3); diff -uNrp -X linux-2.6.34/Documentation/dontdiff linux-2.6.34.orig/include/linux/pci.h linux-2.6.34/include/linux/pci.h --- linux-2.6.34.orig/include/linux/pci.h 2010-05-16 14:17:36.000000000 -0700 +++ linux-2.6.34/include/linux/pci.h 2010-05-26 17:16:21.000000000 -0700 @@ -792,6 +792,7 @@ size_t pci_get_rom_size(struct pci_dev * /* Power management related routines */ int pci_save_state(struct pci_dev *dev); int pci_restore_state(struct pci_dev *dev); +int pci_force_restore_state(struct pci_dev *dev); int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state); int pci_set_power_state(struct pci_dev *dev, pci_power_t state); pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state); @@ -1155,6 +1156,11 @@ static inline int pci_restore_state(stru return 0; } +static inline int pci_force_restore_state(struct pci_dev *dev) +{ + return 0; +} + static inline int pci_set_power_state(struct pci_dev *dev, pci_power_t state) { return 0;