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 [EMAIL PROTECTED] Thu Mar  8 12:06:39 2007
From: Eric W. Biederman <[EMAIL PROTECTED]>
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 <[EMAIL PROTECTED]>, Linus Torvalds <[EMAIL PROTECTED]>
Cc: Jeff Garzik <[EMAIL PROTECTED]>, "Kok, Auke" <[EMAIL PROTECTED]>, Ingo 
Molnar <[EMAIL PROTECTED]>, "Michael S. Tsirkin" <[EMAIL PROTECTED]>, Pavel 
Machek <[EMAIL PROTECTED]>, Jens Axboe <[EMAIL PROTECTED]>, Adrian Bunk <[EMAIL 
PROTECTED]>, Linux Kernel Mailing List <linux-kernel@vger.kernel.org>, Thomas 
Gleixner <[EMAIL PROTECTED]>, [EMAIL PROTECTED], Michal Piotrowski <[EMAIL 
PROTECTED]>, Greg Kroah-Hartman <[EMAIL PROTECTED]>, <[EMAIL PROTECTED]>, 
[EMAIL PROTECTED]
Message-ID: <[EMAIL PROTECTED]>


From: Eric W. Biederman <[EMAIL PROTECTED]>

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 <[EMAIL PROTECTED]>
Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>

---
 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 [EMAIL PROTECTED] are

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to