From b887d2e63c8857149ef59eb6e05adfaa018b8ebf Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 14 Aug 2006 23:11:05 -0700 Subject: PM: PCI and IDE handle PM_EVENT_PRETHAW Convert some framework code to handle the new PRETHAW message. - IDE just treats it like a FREEZE. - The pci_choose_state() thingie still doesn't use PCI_D0 when it gets a FREEZE (and now PRETHAW) event, which seems rather buglike but wasn't something to change with this patch. Signed-off-by: David Brownell Cc: "Rafael J. Wysocki" Cc: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/pci/pci.c') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 9f79dd6d51ab..8ab027886034 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -432,10 +432,12 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) case PM_EVENT_ON: return PCI_D0; case PM_EVENT_FREEZE: + case PM_EVENT_PRETHAW: + /* REVISIT both freeze and pre-thaw "should" use D0 */ case PM_EVENT_SUSPEND: return PCI_D3hot; default: - printk("They asked me for state %d\n", state.event); + printk("Unrecognized suspend event %d\n", state.event); BUG(); } return PCI_D0; -- cgit v1.2.3 From 0637a70a5db98182d9ad3d6ae1ee30acf20afde9 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 26 Sep 2006 10:52:41 +0200 Subject: [PATCH] x86: Allow disabling early pci scans with pci=noearly or disallowing conf1 Some buggy systems can machine check when config space accesses happen for some non existent devices. i386/x86-64 do some early device scans that might trigger this. Allow pci=noearly to disable this. Also when type 1 is disabling also don't do any early accesses which are always type1. This moves the pci= configuration parsing to be a early parameter. I don't think this can break anything because it only changes a single global that is only used by PCI. Cc: gregkh@suse.de Cc: Trammell Hudson Signed-off-by: Andi Kleen --- drivers/pci/pci.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/pci/pci.c') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 9f79dd6d51ab..684deb6b03aa 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -953,13 +953,12 @@ static int __devinit pci_setup(char *str) } str = k; } - return 1; + return 0; } +early_param("pci", pci_setup); device_initcall(pci_init); -__setup("pci=", pci_setup); - #if defined(CONFIG_ISA) || defined(CONFIG_EISA) /* FIXME: Some boxes have multiple ISA bridges! */ struct pci_dev *isa_bridge; -- cgit v1.2.3 From b56a5a23bfecd9cac9187164a9d5f22d287c48b9 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 21 Aug 2006 16:22:22 +0300 Subject: PCI: Restore PCI Express capability registers after PM event Restore PCI Express capability registers after PM event. This includes maxumum MTU for PCI express and other vital data. Signed-off-by: Michael S. Tsirkin Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'drivers/pci/pci.c') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 590f4e6f505d..a544997399b3 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -445,6 +445,51 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) EXPORT_SYMBOL(pci_choose_state); +static int pci_save_pcie_state(struct pci_dev *dev) +{ + int pos, i = 0; + struct pci_cap_saved_state *save_state; + u16 *cap; + + pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (pos <= 0) + return 0; + + 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; + } + cap = (u16 *)&save_state->data[0]; + + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &cap[i++]); + pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]); + pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]); + pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]); + pci_add_saved_cap(dev, save_state); + return 0; +} + +static void pci_restore_pcie_state(struct pci_dev *dev) +{ + int i = 0, pos; + struct pci_cap_saved_state *save_state; + u16 *cap; + + save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); + pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (!save_state || pos <= 0) + return; + cap = (u16 *)&save_state->data[0]; + + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, cap[i++]); + 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); +} + /** * pci_save_state - save the PCI configuration space of a device before suspending * @dev: - PCI device that we're dealing with @@ -460,6 +505,8 @@ pci_save_state(struct pci_dev *dev) return i; if ((i = pci_save_msix_state(dev)) != 0) return i; + if ((i = pci_save_pcie_state(dev)) != 0) + return i; return 0; } @@ -473,6 +520,9 @@ pci_restore_state(struct pci_dev *dev) int i; int val; + /* PCI Express register must be restored first */ + pci_restore_pcie_state(dev); + /* * The Base Address register should be programmed before the command * register(s) -- cgit v1.2.3