From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933531AbXCJHwM (ORCPT ); Sat, 10 Mar 2007 02:52:12 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S933528AbXCJHwL (ORCPT ); Sat, 10 Mar 2007 02:52:11 -0500 Received: from mx2.suse.de ([195.135.220.15]:44947 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933533AbXCJHwA (ORCPT ); Sat, 10 Mar 2007 02:52:00 -0500 Subject: patch pci-repair-pci_save-restore_state-so-we-can-restore-one-save-many-times.patch added to gregkh-2.6 tree To: ebiederm@xmission.com, akpm@linux-foundation.org, auke-jan.h.kok@intel.com, bunk@stusta.de, gregkh@suse.de, jeff@garzik.org, jens.axboe@oracle.com, linux-kernel@vger.kernel.org, linux-pci@atrey.karlin.mff.cuni.cz, michal.k.k.piotrowski@gmail.com, mingo@elte.hu, mst@mellanox.co.il, pavel@ucw.cz, tglx@linutronix.de, torvalds@linux-foundation.org From: Date: Fri, 09 Mar 2007 23:50:20 -0800 In-Reply-To: Message-Id: <20070310075157.6162AB9484B@imap.suse.de> Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org This is a note to let you know that I've just added the patch titled Subject: pci: Repair pci_save/restore_state so we can restore one save many times. to my gregkh-2.6 tree. Its filename is pci-repair-pci_save-restore_state-so-we-can-restore-one-save-many-times.patch This tree can be found at http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/ >>From owner-linux-pci@atrey.karlin.mff.cuni.cz Thu Mar 8 12:06:39 2007 From: Eric W. Biederman Date: Thu, 08 Mar 2007 13:06:13 -0700 Subject: pci: Repair pci_save/restore_state so we can restore one save many times. To: Andrew Morton , Linus Torvalds Cc: Jeff Garzik , "Kok, Auke" , Ingo Molnar , "Michael S. Tsirkin" , Pavel Machek , Jens Axboe , Adrian Bunk , Linux Kernel Mailing List , Thomas Gleixner , linux-pm@lists.osdl.org, Michal Piotrowski , Greg Kroah-Hartman , , michael@ellerman.id.au Message-ID: From: Eric W. Biederman Because we do not reserve space for the pci-x and pci-e state in struct pci dev we need to dynamically allocate it. However because we need to support restore being called multiple times after a single save it is never safe to free the buffers we have allocated to hold the state. So this patch modifies the save routines to first check to see if we have already allocated a state buffer before allocating a new one. Then the restore routines are modified to not free the state after restoring it. Simple and it fixes some subtle error path handling bugs, that are hard to test for. Signed-off-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 12 ++++++------ include/linux/pci.h | 5 ----- 2 files changed, 6 insertions(+), 11 deletions(-) --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -551,7 +551,9 @@ static int pci_save_pcie_state(struct pc if (pos <= 0) return 0; - save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL); + save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); + if (!save_state) + save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL); if (!save_state) { dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n"); return -ENOMEM; @@ -582,8 +584,6 @@ static void pci_restore_pcie_state(struc pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]); pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]); pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]); - pci_remove_saved_cap(save_state); - kfree(save_state); } @@ -597,7 +597,9 @@ static int pci_save_pcix_state(struct pc if (pos <= 0) return 0; - save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL); + save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); + if (!save_state) + save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL); if (!save_state) { dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n"); return -ENOMEM; @@ -622,8 +624,6 @@ static void pci_restore_pcix_state(struc cap = (u16 *)&save_state->data[0]; pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]); - pci_remove_saved_cap(save_state); - kfree(save_state); } --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -222,11 +222,6 @@ static inline void pci_add_saved_cap(str hlist_add_head(&new_cap->next, &pci_dev->saved_cap_space); } -static inline void pci_remove_saved_cap(struct pci_cap_saved_state *cap) -{ - hlist_del(&cap->next); -} - /* * For PCI devices, the region numbers are assigned this way: * Patches currently in gregkh-2.6 which might be from ebiederm@xmission.com are