]> git.pld-linux.org Git - packages/kernel.git/blame - linux-2.4.7-suspend.patch
- no // in paths, other cosmetics
[packages/kernel.git] / linux-2.4.7-suspend.patch
CommitLineData
12a6d182
JR
1diff -urNp linux-1391/arch/i386/kernel/dmi_scan.c linux-1420/arch/i386/kernel/dmi_scan.c
2--- linux-1391/arch/i386/kernel/dmi_scan.c
3+++ linux-1420/arch/i386/kernel/dmi_scan.c
4@@ -546,6 +546,22 @@ static __init int print_if_true(struct d
5 }
6
7 /*
8+ * Dell Inspiron 8000 APM BIOS fails to correctly save and restore the
9+ * config space of some PCI devices.
10+ */
11+
12+static __init int broken_apm_pci_restore(struct dmi_blacklist *d)
13+{
14+#ifdef CONFIG_PCI
15+ extern int pci_bridge_force_restore;
16+
17+ printk(KERN_WARNING "%s detected. Forcing restore of PCI configuration space on APM resume.\n", d->ident);
18+ pci_bridge_force_restore = 1;
19+#endif
20+ return 0;
21+}
22+
23+/*
24 * Process the DMI blacklists
25 */
26
27@@ -871,6 +887,16 @@ static __initdata struct dmi_blacklist d
28 MATCH(DMI_SYS_VENDOR, "IBM"),
29 NO_MATCH, NO_MATCH, NO_MATCH
30 } },
31+ { broken_apm_pci_restore, "Dell Inspiron 8000", { /* Work around broken Dell BIOS */
32+ MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
33+ MATCH(DMI_PRODUCT_NAME, "Inspiron 8000"),
34+ NO_MATCH, NO_MATCH
35+ } },
36+ { broken_apm_pci_restore, "Dell Inspiron 8100", { /* Work around broken Dell BIOS */
37+ MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
38+ MATCH(DMI_PRODUCT_NAME, "Inspiron 8100"),
39+ NO_MATCH, NO_MATCH
40+ } },
41
42 { NULL, }
43 };
44diff -urNp linux-1391/drivers/pci/bridge.c linux-1420/drivers/pci/bridge.c
45--- linux-1391/drivers/pci/bridge.c 1970-01-01 01:00:00.000000000 +0100
46+++ linux-1420/drivers/pci/bridge.c
47@@ -0,0 +1,149 @@
48+
49+/*
50+ * Copyright (c) 2001 Red Hat, Inc. All rights reserved.
51+ *
52+ * This software may be freely redistributed under the terms
53+ * of the GNU public license.
54+ *
55+ * You should have received a copy of the GNU General Public License
56+ * along with this program; if not, write to the Free Software
57+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
58+ *
59+ * Author: Arjan van de Ven <arjanv@redhat.com>
60+ *
61+ */
62+
63+
64+/*
65+ * Generic PCI driver for PCI bridges for powermanagement purposes
66+ *
67+ */
68+
69+#include <linux/config.h>
70+#include <linux/module.h>
71+#include <linux/kernel.h>
72+#include <linux/pci.h>
73+#include <linux/init.h>
74+
75+static struct pci_device_id bridge_pci_table[] __devinitdata = {
76+ {/* handle all PCI bridges */
77+ class: ((PCI_CLASS_BRIDGE_PCI << 8) | 0x00),
78+ class_mask: ~0,
79+ vendor: PCI_ANY_ID,
80+ device: PCI_ANY_ID,
81+ subvendor: PCI_ANY_ID,
82+ subdevice: PCI_ANY_ID,
83+ },
84+ {0,},
85+};
86+
87+static int bridge_probe(struct pci_dev *pdev, const struct pci_device_id *id);
88+static int pci_bridge_save_state_bus(struct pci_bus *bus, int force);
89+int pci_generic_resume_compare(struct pci_dev *pdev);
90+
91+int pci_bridge_force_restore = 0;
92+
93+
94+
95+
96+static int __init bridge_setup(char *str)
97+{
98+ if (!strcmp(str,"force"))
99+ pci_bridge_force_restore = 1;
100+ else if (!strcmp(str,"noforce"))
101+ pci_bridge_force_restore = 0;
102+ return 0;
103+}
104+
105+__setup("resume=",bridge_setup);
106+
107+
108+static int pci_bridge_save_state_bus(struct pci_bus *bus, int force)
109+{
110+ struct list_head *list;
111+ int error = 0;
112+
113+ list_for_each(list, &bus->children) {
114+ error = pci_bridge_save_state_bus(pci_bus_b(list),force);
115+ if (error) return error;
116+ }
117+ list_for_each(list, &bus->devices) {
118+ pci_generic_suspend_save(pci_dev_b(list),0);
119+ }
120+ return 0;
121+}
122+
123+
124+static int pci_bridge_restore_state_bus(struct pci_bus *bus, int force)
125+{
126+ struct list_head *list;
127+ int error = 0;
128+ static int printed_warning=0;
129+
130+ list_for_each(list, &bus->children) {
131+ error = pci_bridge_restore_state_bus(pci_bus_b(list),force);
132+ if (error) return error;
133+ }
134+ list_for_each(list, &bus->devices) {
135+ if (force)
136+ pci_generic_resume_restore(pci_dev_b(list));
137+ else {
138+ error = pci_generic_resume_compare(pci_dev_b(list));
139+ if (error && !printed_warning++) {
140+ printk(KERN_WARNING "resume warning: bios doesn't restore PCI state properly\n");
141+ printk(KERN_WARNING "resume warning: if resume failed, try booting with resume=force\n");
142+ }
143+ if (error)
144+ return error;
145+ }
146+ }
147+ return 0;
148+}
149+
150+static int bridge_suspend(struct pci_dev *dev, u32 force)
151+{
152+ pci_generic_suspend_save(dev,force);
153+ if (dev->subordinate)
154+ pci_bridge_save_state_bus(dev->subordinate,force);
155+ return 0;
156+}
157+
158+static int bridge_resume(struct pci_dev *dev)
159+{
160+
161+ pci_generic_resume_restore(dev);
162+ if (dev->subordinate)
163+ pci_bridge_restore_state_bus(dev->subordinate,pci_bridge_force_restore);
164+ return 0;
165+}
166+
167+
168+MODULE_DEVICE_TABLE(pci, bridge_pci_table);
169+static struct pci_driver bridge_ops = {
170+ name: "PCI Bridge",
171+ id_table: bridge_pci_table,
172+ probe: bridge_probe,
173+ suspend: bridge_suspend,
174+ resume: bridge_resume
175+};
176+
177+static int __devinit bridge_probe(struct pci_dev *pdev, const struct pci_device_id *id)
178+{
179+ return 0;
180+}
181+
182+static int __init bridge_init(void)
183+{
184+ pci_register_driver(&bridge_ops);
185+ return 0;
186+}
187+
188+static void __exit bridge_exit(void)
189+{
190+ pci_unregister_driver(&bridge_ops);
191+}
192+
193+
194+module_init(bridge_init)
195+module_exit(bridge_exit)
196+
197diff -urNp linux-1391/drivers/pci/Makefile linux-1420/drivers/pci/Makefile
198--- linux-1391/drivers/pci/Makefile
199+++ linux-1420/drivers/pci/Makefile
200@@ -13,7 +13,7 @@ O_TARGET := driver.o
201
202 export-objs := pci.o
203
204-obj-$(CONFIG_PCI) += pci.o quirks.o compat.o names.o
205+obj-$(CONFIG_PCI) += pci.o quirks.o compat.o names.o bridge.o
206 obj-$(CONFIG_PROC_FS) += proc.o
207
208 ifndef CONFIG_SPARC64
209diff -urNp linux-1391/drivers/pci/pci.c linux-1420/drivers/pci/pci.c
210--- linux-1391/drivers/pci/pci.c
211+++ linux-1420/drivers/pci/pci.c
212@@ -380,6 +380,48 @@ pci_enable_device_bars(struct pci_dev *d
213 return 0;
214 }
215
216+int
217+pci_compare_state(struct pci_dev *dev, u32 *buffer)
218+{
219+ int i;
220+ unsigned int temp;
221+
222+ if (buffer) {
223+ for (i = 0; i < 16; i++) {
224+ pci_read_config_dword(dev,i*4,&temp);
225+ if (temp!=buffer[i])
226+ return 1;
227+ }
228+ }
229+ return 0;
230+}
231+
232+int pci_generic_suspend_save(struct pci_dev *pdev, u32 state)
233+{
234+ if (pdev)
235+ pci_save_state(pdev,pdev->saved_state);
236+ return 0;
237+}
238+
239+int pci_generic_resume_restore(struct pci_dev *pdev)
240+{
241+ if (pdev)
242+ pci_restore_state(pdev,pdev->saved_state);
243+ return 0;
244+}
245+
246+int pci_generic_resume_compare(struct pci_dev *pdev)
247+{
248+ int retval=0;
249+ if (pdev)
250+ retval = pci_compare_state(pdev,pdev->saved_state);
251+ return retval;
252+}
253+
254+EXPORT_SYMBOL_GPL(pci_generic_suspend_save);
255+EXPORT_SYMBOL_GPL(pci_generic_resume_restore);
256+EXPORT_SYMBOL_GPL(pci_generic_resume_compare);
257+
258 /**
259 * pci_enable_device - Initialize device before it's used by a driver.
260 * @dev: PCI device to be initialized
261diff -urNp linux-1391/include/linux/pci.h linux-1420/include/linux/pci.h
262--- linux-1391/include/linux/pci.h
263+++ linux-1420/include/linux/pci.h
264@@ -410,6 +410,7 @@ struct pci_dev {
265
266 char name[90]; /* device name */
267 char slot_name[8]; /* slot name */
268+ u32 saved_state[16]; /* for saving the config space before suspend */
269 int active; /* ISAPnP: device is active */
270 int ro; /* ISAPnP: read only */
271 unsigned short regs; /* ISAPnP: supported registers */
272@@ -612,6 +613,8 @@ int pci_save_state(struct pci_dev *dev,
273 int pci_restore_state(struct pci_dev *dev, u32 *buffer);
274 int pci_set_power_state(struct pci_dev *dev, int state);
275 int pci_enable_wake(struct pci_dev *dev, u32 state, int enable);
276+int pci_generic_suspend_save(struct pci_dev *pdev, u32 state);
277+int pci_generic_resume_restore(struct pci_dev *pdev);
278
279 /* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */
280
281@@ -707,6 +710,7 @@ static inline int pci_restore_state(stru
282 static inline int pci_set_power_state(struct pci_dev *dev, int state) { return 0; }
283 static inline int pci_enable_wake(struct pci_dev *dev, u32 state, int enable) { return 0; }
284
285+
286 #define pci_for_each_dev(dev) \
287 for(dev = NULL; 0; )
288
This page took 0.921147 seconds and 4 git commands to generate.