aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-07-13 16:23:51 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-07-13 16:23:51 -0400
commit327309e899662b482c58cf25f574513d38b5788c (patch)
tree069de438aa0e92dd9b6ba28e6b207e2cd07151a5 /drivers/pci
parent0c168775709faa74c1b87f1e61046e0c51ade7f3 (diff)
parentc32511e2718618f0b53479eb36e07439aa363a74 (diff)
Merge upstream 2.6.13-rc3 into ieee80211 branch of netdev-2.6.
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/Makefile1
-rw-r--r--drivers/pci/hotplug.c2
-rw-r--r--drivers/pci/hotplug/Kconfig5
-rw-r--r--drivers/pci/hotplug/Makefile1
-rw-r--r--drivers/pci/hotplug/sgi_hotplug.c611
-rw-r--r--drivers/pci/pci-acpi.c110
-rw-r--r--drivers/pci/pci-driver.c198
-rw-r--r--drivers/pci/pci.c28
-rw-r--r--drivers/pci/pci.h4
-rw-r--r--drivers/pci/pcie/portdrv.h5
-rw-r--r--drivers/pci/pcie/portdrv_core.c14
-rw-r--r--drivers/pci/pcie/portdrv_pci.c79
-rw-r--r--drivers/pci/probe.c24
-rw-r--r--drivers/pci/quirks.c1
-rw-r--r--drivers/pci/search.c1
-rw-r--r--drivers/pci/setup-bus.c3
16 files changed, 938 insertions, 149 deletions
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 7dea494c0d7b..3657f6199c48 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
19# 19#
20# Some architectures use the generic PCI setup functions 20# Some architectures use the generic PCI setup functions
21# 21#
22obj-$(CONFIG_X86) += setup-bus.o
22obj-$(CONFIG_ALPHA) += setup-bus.o setup-irq.o 23obj-$(CONFIG_ALPHA) += setup-bus.o setup-irq.o
23obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o 24obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o
24obj-$(CONFIG_PARISC) += setup-bus.o 25obj-$(CONFIG_PARISC) += setup-bus.o
diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c
index 3903f8c559b6..b844bc972324 100644
--- a/drivers/pci/hotplug.c
+++ b/drivers/pci/hotplug.c
@@ -54,7 +54,7 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
54 54
55 envp[i++] = scratch; 55 envp[i++] = scratch;
56 length += scnprintf (scratch, buffer_size - length, 56 length += scnprintf (scratch, buffer_size - length,
57 "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x\n", 57 "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
58 pdev->vendor, pdev->device, 58 pdev->vendor, pdev->device,
59 pdev->subsystem_vendor, pdev->subsystem_device, 59 pdev->subsystem_vendor, pdev->subsystem_device,
60 (u8)(pdev->class >> 16), (u8)(pdev->class >> 8), 60 (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index 1a4d4ca2a4dc..9c4a39ee89b5 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -187,9 +187,10 @@ config HOTPLUG_PCI_RPA_DLPAR
187 187
188config HOTPLUG_PCI_SGI 188config HOTPLUG_PCI_SGI
189 tristate "SGI PCI Hotplug Support" 189 tristate "SGI PCI Hotplug Support"
190 depends on HOTPLUG_PCI && IA64_SGI_SN2 190 depends on HOTPLUG_PCI && (IA64_SGI_SN2 || IA64_GENERIC)
191 help 191 help
192 Say Y here if you have an SGI IA64 Altix system. 192 Say Y here if you want to use the SGI Altix Hotplug
193 Driver for PCI devices.
193 194
194 When in doubt, say N. 195 When in doubt, say N.
195 196
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
index 3e632ff8c717..31a307004b94 100644
--- a/drivers/pci/hotplug/Makefile
+++ b/drivers/pci/hotplug/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o
14obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o 14obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o
15obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o 15obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o
16obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o 16obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o
17obj-$(CONFIG_HOTPLUG_PCI_SGI) += sgi_hotplug.o
17 18
18pci_hotplug-objs := pci_hotplug_core.o 19pci_hotplug-objs := pci_hotplug_core.o
19 20
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
new file mode 100644
index 000000000000..323041fd41dc
--- /dev/null
+++ b/drivers/pci/hotplug/sgi_hotplug.c
@@ -0,0 +1,611 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2005 Silicon Graphics, Inc. All rights reserved.
7 *
8 * This work was based on the 2.4/2.6 kernel development by Dick Reigner.
9 * Work to add BIOS PROM support was completed by Mike Habeck.
10 */
11
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/pci.h>
16#include <linux/proc_fs.h>
17#include <linux/types.h>
18
19#include <asm/sn/addrs.h>
20#include <asm/sn/l1.h>
21#include <asm/sn/module.h>
22#include <asm/sn/pcibr_provider.h>
23#include <asm/sn/pcibus_provider_defs.h>
24#include <asm/sn/pcidev.h>
25#include <asm/sn/sn_sal.h>
26#include <asm/sn/types.h>
27
28#include "../pci.h"
29#include "pci_hotplug.h"
30
31MODULE_LICENSE("GPL");
32MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)");
33MODULE_DESCRIPTION("SGI Altix Hot Plug PCI Controller Driver");
34
35#define PCIIO_ASIC_TYPE_TIOCA 4
36#define PCI_SLOT_ALREADY_UP 2 /* slot already up */
37#define PCI_SLOT_ALREADY_DOWN 3 /* slot already down */
38#define PCI_L1_ERR 7 /* L1 console command error */
39#define PCI_EMPTY_33MHZ 15 /* empty 33 MHz bus */
40#define PCI_L1_QSIZE 128 /* our L1 message buffer size */
41#define SN_MAX_HP_SLOTS 32 /* max number of hotplug slots */
42#define SGI_HOTPLUG_PROM_REV 0x0420 /* Min. required PROM version */
43
44/* internal list head */
45static struct list_head sn_hp_list;
46
47/* hotplug_slot struct's private pointer */
48struct slot {
49 int device_num;
50 struct pci_bus *pci_bus;
51 /* this struct for glue internal only */
52 struct hotplug_slot *hotplug_slot;
53 struct list_head hp_list;
54};
55
56struct pcibr_slot_enable_resp {
57 int resp_sub_errno;
58 char resp_l1_msg[PCI_L1_QSIZE + 1];
59};
60
61struct pcibr_slot_disable_resp {
62 int resp_sub_errno;
63 char resp_l1_msg[PCI_L1_QSIZE + 1];
64};
65
66enum sn_pci_req_e {
67 PCI_REQ_SLOT_ELIGIBLE,
68 PCI_REQ_SLOT_DISABLE
69};
70
71static int enable_slot(struct hotplug_slot *slot);
72static int disable_slot(struct hotplug_slot *slot);
73static int get_power_status(struct hotplug_slot *slot, u8 *value);
74
75static struct hotplug_slot_ops sn_hotplug_slot_ops = {
76 .owner = THIS_MODULE,
77 .enable_slot = enable_slot,
78 .disable_slot = disable_slot,
79 .get_power_status = get_power_status,
80};
81
82static DECLARE_MUTEX(sn_hotplug_sem);
83
84static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
85{
86 struct pcibus_info *pcibus_info;
87 int bricktype;
88 int bus_num;
89
90 pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
91
92 /* Check to see if this is a valid slot on 'pci_bus' */
93 if (!(pcibus_info->pbi_valid_devices & (1 << device)))
94 return -EPERM;
95
96 bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
97 bus_num = pcibus_info->pbi_buscommon.bs_persist_busnum & 0xf;
98
99 /* Do not allow hotplug operations on base I/O cards */
100 if ((bricktype == L1_BRICKTYPE_IX || bricktype == L1_BRICKTYPE_IA) &&
101 (bus_num == 1 && device != 1))
102 return -EPERM;
103
104 return 1;
105}
106
107static int sn_pci_bus_valid(struct pci_bus *pci_bus)
108{
109 struct pcibus_info *pcibus_info;
110 int asic_type;
111 int bricktype;
112
113 pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
114
115 /* Don't register slots hanging off the TIOCA bus */
116 asic_type = pcibus_info->pbi_buscommon.bs_asic_type;
117 if (asic_type == PCIIO_ASIC_TYPE_TIOCA)
118 return -EPERM;
119
120 /* Only register slots in I/O Bricks that support hotplug */
121 bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
122 switch (bricktype) {
123 case L1_BRICKTYPE_IX:
124 case L1_BRICKTYPE_PX:
125 case L1_BRICKTYPE_IA:
126 case L1_BRICKTYPE_PA:
127 return 1;
128 break;
129 default:
130 return -EPERM;
131 break;
132 }
133
134 return -EIO;
135}
136
137static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
138 struct pci_bus *pci_bus, int device)
139{
140 struct pcibus_info *pcibus_info;
141 struct slot *slot;
142
143 pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
144
145 bss_hotplug_slot->private = kcalloc(1, sizeof(struct slot),
146 GFP_KERNEL);
147 if (!bss_hotplug_slot->private)
148 return -ENOMEM;
149 slot = (struct slot *)bss_hotplug_slot->private;
150
151 bss_hotplug_slot->name = kmalloc(33, GFP_KERNEL);
152 if (!bss_hotplug_slot->name) {
153 kfree(bss_hotplug_slot->private);
154 return -ENOMEM;
155 }
156
157 slot->device_num = device;
158 slot->pci_bus = pci_bus;
159
160 sprintf(bss_hotplug_slot->name, "module_%c%c%c%c%.2d_b_%d_s_%d",
161 '0'+RACK_GET_CLASS(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
162 '0'+RACK_GET_GROUP(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
163 '0'+RACK_GET_NUM(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
164 MODULE_GET_BTCHAR(pcibus_info->pbi_moduleid),
165 MODULE_GET_BPOS(pcibus_info->pbi_moduleid),
166 ((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf,
167 device + 1);
168
169 slot->hotplug_slot = bss_hotplug_slot;
170 list_add(&slot->hp_list, &sn_hp_list);
171
172 return 0;
173}
174
175static struct hotplug_slot * sn_hp_destroy(void)
176{
177 struct slot *slot;
178 struct list_head *list;
179 struct hotplug_slot *bss_hotplug_slot = NULL;
180
181 list_for_each(list, &sn_hp_list) {
182 slot = list_entry(list, struct slot, hp_list);
183 bss_hotplug_slot = slot->hotplug_slot;
184 list_del(&((struct slot *)bss_hotplug_slot->private)->
185 hp_list);
186 break;
187 }
188 return bss_hotplug_slot;
189}
190
191static void sn_bus_alloc_data(struct pci_dev *dev)
192{
193 struct list_head *node;
194 struct pci_bus *subordinate_bus;
195 struct pci_dev *child;
196
197 sn_pci_fixup_slot(dev);
198
199 /* Recursively sets up the sn_irq_info structs */
200 if (dev->subordinate) {
201 subordinate_bus = dev->subordinate;
202 list_for_each(node, &subordinate_bus->devices) {
203 child = list_entry(node, struct pci_dev, bus_list);
204 sn_bus_alloc_data(child);
205 }
206 }
207}
208
209static void sn_bus_free_data(struct pci_dev *dev)
210{
211 struct list_head *node;
212 struct pci_bus *subordinate_bus;
213 struct pci_dev *child;
214
215 /* Recursively clean up sn_irq_info structs */
216 if (dev->subordinate) {
217 subordinate_bus = dev->subordinate;
218 list_for_each(node, &subordinate_bus->devices) {
219 child = list_entry(node, struct pci_dev, bus_list);
220 sn_bus_free_data(child);
221 }
222 }
223 sn_pci_unfixup_slot(dev);
224}
225
226static u8 sn_power_status_get(struct hotplug_slot *bss_hotplug_slot)
227{
228 struct slot *slot = (struct slot *)bss_hotplug_slot->private;
229 struct pcibus_info *pcibus_info;
230 u8 retval;
231
232 pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
233 retval = pcibus_info->pbi_enabled_devices & (1 << slot->device_num);
234
235 return retval ? 1 : 0;
236}
237
238static void sn_slot_mark_enable(struct hotplug_slot *bss_hotplug_slot,
239 int device_num)
240{
241 struct slot *slot = (struct slot *)bss_hotplug_slot->private;
242 struct pcibus_info *pcibus_info;
243
244 pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
245 pcibus_info->pbi_enabled_devices |= (1 << device_num);
246}
247
248static void sn_slot_mark_disable(struct hotplug_slot *bss_hotplug_slot,
249 int device_num)
250{
251 struct slot *slot = (struct slot *)bss_hotplug_slot->private;
252 struct pcibus_info *pcibus_info;
253
254 pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
255 pcibus_info->pbi_enabled_devices &= ~(1 << device_num);
256}
257
258static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,
259 int device_num)
260{
261 struct slot *slot = (struct slot *)bss_hotplug_slot->private;
262 struct pcibus_info *pcibus_info;
263 struct pcibr_slot_enable_resp resp;
264 int rc;
265
266 pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
267
268 /*
269 * Power-on and initialize the slot in the SN
270 * PCI infrastructure.
271 */
272 rc = sal_pcibr_slot_enable(pcibus_info, device_num, &resp);
273
274 if (rc == PCI_SLOT_ALREADY_UP) {
275 dev_dbg(slot->pci_bus->self, "is already active\n");
276 return -EPERM;
277 }
278
279 if (rc == PCI_L1_ERR) {
280 dev_dbg(slot->pci_bus->self,
281 "L1 failure %d with message: %s",
282 resp.resp_sub_errno, resp.resp_l1_msg);
283 return -EPERM;
284 }
285
286 if (rc) {
287 dev_dbg(slot->pci_bus->self,
288 "insert failed with error %d sub-error %d\n",
289 rc, resp.resp_sub_errno);
290 return -EIO;
291 }
292
293 sn_slot_mark_enable(bss_hotplug_slot, device_num);
294
295 return 0;
296}
297
298static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot,
299 int device_num, int action)
300{
301 struct slot *slot = (struct slot *)bss_hotplug_slot->private;
302 struct pcibus_info *pcibus_info;
303 struct pcibr_slot_disable_resp resp;
304 int rc;
305
306 pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
307
308 rc = sal_pcibr_slot_disable(pcibus_info, device_num, action, &resp);
309
310 if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_SLOT_ALREADY_DOWN) {
311 dev_dbg(slot->pci_bus->self, "Slot %s already inactive\n");
312 return -ENODEV;
313 }
314
315 if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_EMPTY_33MHZ) {
316 dev_dbg(slot->pci_bus->self,
317 "Cannot remove last 33MHz card\n");
318 return -EPERM;
319 }
320
321 if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_L1_ERR) {
322 dev_dbg(slot->pci_bus->self,
323 "L1 failure %d with message \n%s\n",
324 resp.resp_sub_errno, resp.resp_l1_msg);
325 return -EPERM;
326 }
327
328 if (action == PCI_REQ_SLOT_ELIGIBLE && rc) {
329 dev_dbg(slot->pci_bus->self,
330 "remove failed with error %d sub-error %d\n",
331 rc, resp.resp_sub_errno);
332 return -EIO;
333 }
334
335 if (action == PCI_REQ_SLOT_ELIGIBLE && !rc)
336 return 0;
337
338 if (action == PCI_REQ_SLOT_DISABLE && !rc) {
339 sn_slot_mark_disable(bss_hotplug_slot, device_num);
340 dev_dbg(slot->pci_bus->self, "remove successful\n");
341 return 0;
342 }
343
344 if (action == PCI_REQ_SLOT_DISABLE && rc) {
345 dev_dbg(slot->pci_bus->self,"remove failed rc = %d\n", rc);
346 return rc;
347 }
348
349 return rc;
350}
351
352static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
353{
354 struct slot *slot = (struct slot *)bss_hotplug_slot->private;
355 struct pci_bus *new_bus = NULL;
356 struct pci_dev *dev;
357 int func, num_funcs;
358 int new_ppb = 0;
359 int rc;
360
361 /* Serialize the Linux PCI infrastructure */
362 down(&sn_hotplug_sem);
363
364 /*
365 * Power-on and initialize the slot in the SN
366 * PCI infrastructure.
367 */
368 rc = sn_slot_enable(bss_hotplug_slot, slot->device_num);
369 if (rc) {
370 up(&sn_hotplug_sem);
371 return rc;
372 }
373
374 num_funcs = pci_scan_slot(slot->pci_bus, PCI_DEVFN(slot->device_num+1,
375 PCI_FUNC(0)));
376 if (!num_funcs) {
377 dev_dbg(slot->pci_bus->self, "no device in slot\n");
378 up(&sn_hotplug_sem);
379 return -ENODEV;
380 }
381
382 sn_pci_controller_fixup(pci_domain_nr(slot->pci_bus),
383 slot->pci_bus->number,
384 slot->pci_bus);
385 /*
386 * Map SN resources for all functions on the card
387 * to the Linux PCI interface and tell the drivers
388 * about them.
389 */
390 for (func = 0; func < num_funcs; func++) {
391 dev = pci_get_slot(slot->pci_bus,
392 PCI_DEVFN(slot->device_num + 1,
393 PCI_FUNC(func)));
394
395
396 if (dev) {
397 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
398 unsigned char sec_bus;
399 pci_read_config_byte(dev, PCI_SECONDARY_BUS,
400 &sec_bus);
401 new_bus = pci_add_new_bus(dev->bus, dev,
402 sec_bus);
403 pci_scan_child_bus(new_bus);
404 sn_pci_controller_fixup(pci_domain_nr(new_bus),
405 new_bus->number,
406 new_bus);
407 new_ppb = 1;
408 }
409 sn_bus_alloc_data(dev);
410 pci_dev_put(dev);
411 }
412 }
413
414 /* Call the driver for the new device */
415 pci_bus_add_devices(slot->pci_bus);
416 /* Call the drivers for the new devices subordinate to PPB */
417 if (new_ppb)
418 pci_bus_add_devices(new_bus);
419
420 up(&sn_hotplug_sem);
421
422 if (rc == 0)
423 dev_dbg(slot->pci_bus->self,
424 "insert operation successful\n");
425 else
426 dev_dbg(slot->pci_bus->self,
427 "insert operation failed rc = %d\n", rc);
428
429 return rc;
430}
431
432static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
433{
434 struct slot *slot = (struct slot *)bss_hotplug_slot->private;
435 struct pci_dev *dev;
436 int func;
437 int rc;
438
439 /* Acquire update access to the bus */
440 down(&sn_hotplug_sem);
441
442 /* is it okay to bring this slot down? */
443 rc = sn_slot_disable(bss_hotplug_slot, slot->device_num,
444 PCI_REQ_SLOT_ELIGIBLE);
445 if (rc)
446 goto leaving;
447
448 /* Free the SN resources assigned to the Linux device.*/
449 for (func = 0; func < 8; func++) {
450 dev = pci_get_slot(slot->pci_bus,
451 PCI_DEVFN(slot->device_num+1,
452 PCI_FUNC(func)));
453 if (dev) {
454 /*
455 * Some drivers may use dma accesses during the
456 * driver remove function. We release the sysdata
457 * areas after the driver remove functions have
458 * been called.
459 */
460 sn_bus_store_sysdata(dev);
461 sn_bus_free_data(dev);
462 pci_remove_bus_device(dev);
463 pci_dev_put(dev);
464 }
465 }
466
467 /* free the collected sysdata pointers */
468 sn_bus_free_sysdata();
469
470 /* Deactivate slot */
471 rc = sn_slot_disable(bss_hotplug_slot, slot->device_num,
472 PCI_REQ_SLOT_DISABLE);
473 leaving:
474 /* Release the bus lock */
475 up(&sn_hotplug_sem);
476
477 return rc;
478}
479
480static int get_power_status(struct hotplug_slot *bss_hotplug_slot, u8 *value)
481{
482 down(&sn_hotplug_sem);
483 *value = sn_power_status_get(bss_hotplug_slot);
484 up(&sn_hotplug_sem);
485 return 0;
486}
487
488static void sn_release_slot(struct hotplug_slot *bss_hotplug_slot)
489{
490 kfree(bss_hotplug_slot->info);
491 kfree(bss_hotplug_slot->name);
492 kfree(bss_hotplug_slot->private);
493 kfree(bss_hotplug_slot);
494}
495
496static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
497{
498 int device;
499 struct hotplug_slot *bss_hotplug_slot;
500 int rc = 0;
501
502 /*
503 * Currently only four devices are supported,
504 * in the future there maybe more -- up to 32.
505 */
506
507 for (device = 0; device < SN_MAX_HP_SLOTS ; device++) {
508 if (sn_pci_slot_valid(pci_bus, device) != 1)
509 continue;
510
511 bss_hotplug_slot = kcalloc(1,sizeof(struct hotplug_slot),
512 GFP_KERNEL);
513 if (!bss_hotplug_slot) {
514 rc = -ENOMEM;
515 goto alloc_err;
516 }
517
518 bss_hotplug_slot->info =
519 kcalloc(1,sizeof(struct hotplug_slot_info),
520 GFP_KERNEL);
521 if (!bss_hotplug_slot->info) {
522 rc = -ENOMEM;
523 goto alloc_err;
524 }
525
526 if (sn_hp_slot_private_alloc(bss_hotplug_slot,
527 pci_bus, device)) {
528 rc = -ENOMEM;
529 goto alloc_err;
530 }
531
532 bss_hotplug_slot->ops = &sn_hotplug_slot_ops;
533 bss_hotplug_slot->release = &sn_release_slot;
534
535 rc = pci_hp_register(bss_hotplug_slot);
536 if (rc)
537 goto register_err;
538 }
539 dev_dbg(pci_bus->self, "Registered bus with hotplug\n");
540 return rc;
541
542register_err:
543 dev_dbg(pci_bus->self, "bus failed to register with err = %d\n",
544 rc);
545
546alloc_err:
547 if (rc == -ENOMEM)
548 dev_dbg(pci_bus->self, "Memory allocation error\n");
549
550 /* destroy THIS element */
551 if (bss_hotplug_slot)
552 sn_release_slot(bss_hotplug_slot);
553
554 /* destroy anything else on the list */
555 while ((bss_hotplug_slot = sn_hp_destroy()))
556 pci_hp_deregister(bss_hotplug_slot);
557
558 return rc;
559}
560
561static int sn_pci_hotplug_init(void)
562{
563 struct pci_bus *pci_bus = NULL;
564 int rc;
565 int registered = 0;
566
567 INIT_LIST_HEAD(&sn_hp_list);
568
569 if (sn_sal_rev() < SGI_HOTPLUG_PROM_REV) {
570 printk(KERN_ERR "%s: PROM version must be greater than 4.05\n",
571 __FUNCTION__);
572 return -EPERM;
573 }
574
575 while ((pci_bus = pci_find_next_bus(pci_bus))) {
576 if (!pci_bus->sysdata)
577 continue;
578
579 rc = sn_pci_bus_valid(pci_bus);
580 if (rc != 1) {
581 dev_dbg(pci_bus->self, "not a valid hotplug bus\n");
582 continue;
583 }
584 dev_dbg(pci_bus->self, "valid hotplug bus\n");
585
586 rc = sn_hotplug_slot_register(pci_bus);
587 if (!rc)
588 registered = 1;
589 else {
590 registered = 0;
591 break;
592 }
593 }
594
595 return registered == 1 ? 0 : -ENODEV;
596}
597
598static void sn_pci_hotplug_exit(void)
599{
600 struct hotplug_slot *bss_hotplug_slot;
601
602 while ((bss_hotplug_slot = sn_hp_destroy())) {
603 pci_hp_deregister(bss_hotplug_slot);
604 }
605
606 if (!list_empty(&sn_hp_list))
607 printk(KERN_ERR "%s: internal list is not empty\n", __FILE__);
608}
609
610module_init(sn_pci_hotplug_init);
611module_exit(sn_pci_hotplug_exit);
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index bc01d34e2634..e9e37abe1f76 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -1,9 +1,10 @@
1/* 1/*
2 * File: pci-acpi.c 2 * File: pci-acpi.c
3 * Purpose: Provide PCI supports in ACPI 3 * Purpose: Provide PCI support in ACPI
4 * 4 *
5 * Copyright (C) 2004 Intel 5 * Copyright (C) 2005 David Shaohua Li <shaohua.li@intel.com>
6 * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) 6 * Copyright (C) 2004 Tom Long Nguyen <tom.l.nguyen@intel.com>
7 * Copyright (C) 2004 Intel Corp.
7 */ 8 */
8 9
9#include <linux/delay.h> 10#include <linux/delay.h>
@@ -16,6 +17,7 @@
16#include <acpi/acpi_bus.h> 17#include <acpi/acpi_bus.h>
17 18
18#include <linux/pci-acpi.h> 19#include <linux/pci-acpi.h>
20#include "pci.h"
19 21
20static u32 ctrlset_buf[3] = {0, 0, 0}; 22static u32 ctrlset_buf[3] = {0, 0, 0};
21static u32 global_ctrlsets = 0; 23static u32 global_ctrlsets = 0;
@@ -207,3 +209,105 @@ acpi_status pci_osc_control_set(u32 flags)
207 return status; 209 return status;
208} 210}
209EXPORT_SYMBOL(pci_osc_control_set); 211EXPORT_SYMBOL(pci_osc_control_set);
212
213/*
214 * _SxD returns the D-state with the highest power
215 * (lowest D-state number) supported in the S-state "x".
216 *
217 * If the devices does not have a _PRW
218 * (Power Resources for Wake) supporting system wakeup from "x"
219 * then the OS is free to choose a lower power (higher number
220 * D-state) than the return value from _SxD.
221 *
222 * But if _PRW is enabled at S-state "x", the OS
223 * must not choose a power lower than _SxD --
224 * unless the device has an _SxW method specifying
225 * the lowest power (highest D-state number) the device
226 * may enter while still able to wake the system.
227 *
228 * ie. depending on global OS policy:
229 *
230 * if (_PRW at S-state x)
231 * choose from highest power _SxD to lowest power _SxW
232 * else // no _PRW at S-state x
233 * choose highest power _SxD or any lower power
234 *
235 * currently we simply return _SxD, if present.
236 */
237
238static int acpi_pci_choose_state(struct pci_dev *pdev, pm_message_t state)
239{
240 /* TBD */
241
242 return -ENODEV;
243}
244
245static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
246{
247 acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
248 static int state_conv[] = {
249 [0] = 0,
250 [1] = 1,
251 [2] = 2,
252 [3] = 3,
253 [4] = 3
254 };
255 int acpi_state = state_conv[(int __force) state];
256
257 if (!handle)
258 return -ENODEV;
259 return acpi_bus_set_power(handle, acpi_state);
260}
261
262
263/* ACPI bus type */
264static int pci_acpi_find_device(struct device *dev, acpi_handle *handle)
265{
266 struct pci_dev * pci_dev;
267 acpi_integer addr;
268
269 pci_dev = to_pci_dev(dev);
270 /* Please ref to ACPI spec for the syntax of _ADR */
271 addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
272 *handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
273 if (!*handle)
274 return -ENODEV;
275 return 0;
276}
277
278static int pci_acpi_find_root_bridge(struct device *dev, acpi_handle *handle)
279{
280 int num;
281 unsigned int seg, bus;
282
283 /*
284 * The string should be the same as root bridge's name
285 * Please look at 'pci_scan_bus_parented'
286 */
287 num = sscanf(dev->bus_id, "pci%04x:%02x", &seg, &bus);
288 if (num != 2)
289 return -ENODEV;
290 *handle = acpi_get_pci_rootbridge_handle(seg, bus);
291 if (!*handle)
292 return -ENODEV;
293 return 0;
294}
295
296static struct acpi_bus_type pci_acpi_bus = {
297 .bus = &pci_bus_type,
298 .find_device = pci_acpi_find_device,
299 .find_bridge = pci_acpi_find_root_bridge,
300};
301
302static int __init pci_acpi_init(void)
303{
304 int ret;
305
306 ret = register_acpi_bus_type(&pci_acpi_bus);
307 if (ret)
308 return 0;
309 platform_pci_choose_state = acpi_pci_choose_state;
310 platform_pci_set_power_state = acpi_pci_set_power_state;
311 return 0;
312}
313arch_initcall(pci_acpi_init);
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index e65bf2b395aa..e4115a0d5ba6 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -7,7 +7,6 @@
7#include <linux/module.h> 7#include <linux/module.h>
8#include <linux/init.h> 8#include <linux/init.h>
9#include <linux/device.h> 9#include <linux/device.h>
10#include <linux/pci-dynids.h>
11#include "pci.h" 10#include "pci.h"
12 11
13/* 12/*
@@ -18,36 +17,12 @@
18 * Dynamic device IDs are disabled for !CONFIG_HOTPLUG 17 * Dynamic device IDs are disabled for !CONFIG_HOTPLUG
19 */ 18 */
20 19
21#ifdef CONFIG_HOTPLUG 20struct pci_dynid {
22/** 21 struct list_head node;
23 * pci_device_probe_dynamic() 22 struct pci_device_id id;
24 * 23};
25 * Walk the dynamic ID list looking for a match.
26 * returns 0 and sets pci_dev->driver when drv claims pci_dev, else error.
27 */
28static int
29pci_device_probe_dynamic(struct pci_driver *drv, struct pci_dev *pci_dev)
30{
31 int error = -ENODEV;
32 struct list_head *pos;
33 struct dynid *dynid;
34 24
35 spin_lock(&drv->dynids.lock); 25#ifdef CONFIG_HOTPLUG
36 list_for_each(pos, &drv->dynids.list) {
37 dynid = list_entry(pos, struct dynid, node);
38 if (pci_match_one_device(&dynid->id, pci_dev)) {
39 spin_unlock(&drv->dynids.lock);
40 error = drv->probe(pci_dev, &dynid->id);
41 if (error >= 0) {
42 pci_dev->driver = drv;
43 return 0;
44 }
45 return error;
46 }
47 }
48 spin_unlock(&drv->dynids.lock);
49 return error;
50}
51 26
52/** 27/**
53 * store_new_id 28 * store_new_id
@@ -58,8 +33,7 @@ pci_device_probe_dynamic(struct pci_driver *drv, struct pci_dev *pci_dev)
58static inline ssize_t 33static inline ssize_t
59store_new_id(struct device_driver *driver, const char *buf, size_t count) 34store_new_id(struct device_driver *driver, const char *buf, size_t count)
60{ 35{
61 struct dynid *dynid; 36 struct pci_dynid *dynid;
62 struct bus_type * bus;
63 struct pci_driver *pdrv = to_pci_driver(driver); 37 struct pci_driver *pdrv = to_pci_driver(driver);
64 __u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID, 38 __u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID,
65 subdevice=PCI_ANY_ID, class=0, class_mask=0; 39 subdevice=PCI_ANY_ID, class=0, class_mask=0;
@@ -91,37 +65,22 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
91 list_add_tail(&pdrv->dynids.list, &dynid->node); 65 list_add_tail(&pdrv->dynids.list, &dynid->node);
92 spin_unlock(&pdrv->dynids.lock); 66 spin_unlock(&pdrv->dynids.lock);
93 67
94 bus = get_bus(pdrv->driver.bus); 68 if (get_driver(&pdrv->driver)) {
95 if (bus) { 69 driver_attach(&pdrv->driver);
96 if (get_driver(&pdrv->driver)) { 70 put_driver(&pdrv->driver);
97 down_write(&bus->subsys.rwsem);
98 driver_attach(&pdrv->driver);
99 up_write(&bus->subsys.rwsem);
100 put_driver(&pdrv->driver);
101 }
102 put_bus(bus);
103 } 71 }
104 72
105 return count; 73 return count;
106} 74}
107
108static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); 75static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
109static inline void
110pci_init_dynids(struct pci_dynids *dynids)
111{
112 spin_lock_init(&dynids->lock);
113 INIT_LIST_HEAD(&dynids->list);
114}
115 76
116static void 77static void
117pci_free_dynids(struct pci_driver *drv) 78pci_free_dynids(struct pci_driver *drv)
118{ 79{
119 struct list_head *pos, *n; 80 struct pci_dynid *dynid, *n;
120 struct dynid *dynid;
121 81
122 spin_lock(&drv->dynids.lock); 82 spin_lock(&drv->dynids.lock);
123 list_for_each_safe(pos, n, &drv->dynids.list) { 83 list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
124 dynid = list_entry(pos, struct dynid, node);
125 list_del(&dynid->node); 84 list_del(&dynid->node);
126 kfree(dynid); 85 kfree(dynid);
127 } 86 }
@@ -138,83 +97,70 @@ pci_create_newid_file(struct pci_driver *drv)
138 return error; 97 return error;
139} 98}
140 99
141static int
142pci_bus_match_dynids(const struct pci_dev *pci_dev, struct pci_driver *pci_drv)
143{
144 struct list_head *pos;
145 struct dynid *dynid;
146
147 spin_lock(&pci_drv->dynids.lock);
148 list_for_each(pos, &pci_drv->dynids.list) {
149 dynid = list_entry(pos, struct dynid, node);
150 if (pci_match_one_device(&dynid->id, pci_dev)) {
151 spin_unlock(&pci_drv->dynids.lock);
152 return 1;
153 }
154 }
155 spin_unlock(&pci_drv->dynids.lock);
156 return 0;
157}
158
159#else /* !CONFIG_HOTPLUG */ 100#else /* !CONFIG_HOTPLUG */
160static inline int pci_device_probe_dynamic(struct pci_driver *drv, struct pci_dev *pci_dev)
161{
162 return -ENODEV;
163}
164static inline void pci_init_dynids(struct pci_dynids *dynids) {}
165static inline void pci_free_dynids(struct pci_driver *drv) {} 101static inline void pci_free_dynids(struct pci_driver *drv) {}
166static inline int pci_create_newid_file(struct pci_driver *drv) 102static inline int pci_create_newid_file(struct pci_driver *drv)
167{ 103{
168 return 0; 104 return 0;
169} 105}
170static inline int pci_bus_match_dynids(const struct pci_dev *pci_dev, struct pci_driver *pci_drv)
171{
172 return 0;
173}
174#endif 106#endif
175 107
176/** 108/**
177 * pci_match_device - Tell if a PCI device structure has a matching 109 * pci_match_id - See if a pci device matches a given pci_id table
178 * PCI device id structure
179 * @ids: array of PCI device id structures to search in 110 * @ids: array of PCI device id structures to search in
180 * @dev: the PCI device structure to match against 111 * @dev: the PCI device structure to match against.
181 * 112 *
182 * Used by a driver to check whether a PCI device present in the 113 * Used by a driver to check whether a PCI device present in the
183 * system is in its list of supported devices.Returns the matching 114 * system is in its list of supported devices. Returns the matching
184 * pci_device_id structure or %NULL if there is no match. 115 * pci_device_id structure or %NULL if there is no match.
116 *
117 * Depreciated, don't use this as it will not catch any dynamic ids
118 * that a driver might want to check for.
185 */ 119 */
186const struct pci_device_id * 120const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
187pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) 121 struct pci_dev *dev)
188{ 122{
189 while (ids->vendor || ids->subvendor || ids->class_mask) { 123 if (ids) {
190 if (pci_match_one_device(ids, dev)) 124 while (ids->vendor || ids->subvendor || ids->class_mask) {
191 return ids; 125 if (pci_match_one_device(ids, dev))
192 ids++; 126 return ids;
127 ids++;
128 }
193 } 129 }
194 return NULL; 130 return NULL;
195} 131}
196 132
197/** 133/**
198 * pci_device_probe_static() 134 * pci_match_device - Tell if a PCI device structure has a matching
199 * 135 * PCI device id structure
200 * returns 0 and sets pci_dev->driver when drv claims pci_dev, else error. 136 * @ids: array of PCI device id structures to search in
137 * @dev: the PCI device structure to match against
138 * @drv: the PCI driver to match against
139 *
140 * Used by a driver to check whether a PCI device present in the
141 * system is in its list of supported devices. Returns the matching
142 * pci_device_id structure or %NULL if there is no match.
201 */ 143 */
202static int 144const struct pci_device_id *pci_match_device(struct pci_driver *drv,
203pci_device_probe_static(struct pci_driver *drv, struct pci_dev *pci_dev) 145 struct pci_dev *dev)
204{ 146{
205 int error = -ENODEV;
206 const struct pci_device_id *id; 147 const struct pci_device_id *id;
148 struct pci_dynid *dynid;
207 149
208 if (!drv->id_table) 150 id = pci_match_id(drv->id_table, dev);
209 return error;
210 id = pci_match_device(drv->id_table, pci_dev);
211 if (id) 151 if (id)
212 error = drv->probe(pci_dev, id); 152 return id;
213 if (error >= 0) { 153
214 pci_dev->driver = drv; 154 /* static ids didn't match, lets look at the dynamic ones */
215 error = 0; 155 spin_lock(&drv->dynids.lock);
156 list_for_each_entry(dynid, &drv->dynids.list, node) {
157 if (pci_match_one_device(&dynid->id, dev)) {
158 spin_unlock(&drv->dynids.lock);
159 return &dynid->id;
160 }
216 } 161 }
217 return error; 162 spin_unlock(&drv->dynids.lock);
163 return NULL;
218} 164}
219 165
220/** 166/**
@@ -225,13 +171,20 @@ pci_device_probe_static(struct pci_driver *drv, struct pci_dev *pci_dev)
225 */ 171 */
226static int 172static int
227__pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev) 173__pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
228{ 174{
175 const struct pci_device_id *id;
229 int error = 0; 176 int error = 0;
230 177
231 if (!pci_dev->driver && drv->probe) { 178 if (!pci_dev->driver && drv->probe) {
232 error = pci_device_probe_static(drv, pci_dev); 179 error = -ENODEV;
233 if (error == -ENODEV) 180
234 error = pci_device_probe_dynamic(drv, pci_dev); 181 id = pci_match_device(drv, pci_dev);
182 if (id)
183 error = drv->probe(pci_dev, id);
184 if (error >= 0) {
185 pci_dev->driver = drv;
186 error = 0;
187 }
235 } 188 }
236 return error; 189 return error;
237} 190}
@@ -371,12 +324,6 @@ static struct kobj_type pci_driver_kobj_type = {
371 .sysfs_ops = &pci_driver_sysfs_ops, 324 .sysfs_ops = &pci_driver_sysfs_ops,
372}; 325};
373 326
374static int
375pci_populate_driver_dir(struct pci_driver *drv)
376{
377 return pci_create_newid_file(drv);
378}
379
380/** 327/**
381 * pci_register_driver - register a new pci driver 328 * pci_register_driver - register a new pci driver
382 * @drv: the driver structure to register 329 * @drv: the driver structure to register
@@ -401,13 +348,15 @@ int pci_register_driver(struct pci_driver *drv)
401 drv->driver.shutdown = pci_device_shutdown; 348 drv->driver.shutdown = pci_device_shutdown;
402 drv->driver.owner = drv->owner; 349 drv->driver.owner = drv->owner;
403 drv->driver.kobj.ktype = &pci_driver_kobj_type; 350 drv->driver.kobj.ktype = &pci_driver_kobj_type;
404 pci_init_dynids(&drv->dynids); 351
352 spin_lock_init(&drv->dynids.lock);
353 INIT_LIST_HEAD(&drv->dynids.list);
405 354
406 /* register with core */ 355 /* register with core */
407 error = driver_register(&drv->driver); 356 error = driver_register(&drv->driver);
408 357
409 if (!error) 358 if (!error)
410 pci_populate_driver_dir(drv); 359 error = pci_create_newid_file(drv);
411 360
412 return error; 361 return error;
413} 362}
@@ -463,21 +412,17 @@ pci_dev_driver(const struct pci_dev *dev)
463 * system is in its list of supported devices.Returns the matching 412 * system is in its list of supported devices.Returns the matching
464 * pci_device_id structure or %NULL if there is no match. 413 * pci_device_id structure or %NULL if there is no match.
465 */ 414 */
466static int pci_bus_match(struct device * dev, struct device_driver * drv) 415static int pci_bus_match(struct device *dev, struct device_driver *drv)
467{ 416{
468 const struct pci_dev * pci_dev = to_pci_dev(dev); 417 struct pci_dev *pci_dev = to_pci_dev(dev);
469 struct pci_driver * pci_drv = to_pci_driver(drv); 418 struct pci_driver *pci_drv = to_pci_driver(drv);
470 const struct pci_device_id * ids = pci_drv->id_table;
471 const struct pci_device_id *found_id; 419 const struct pci_device_id *found_id;
472 420
473 if (!ids) 421 found_id = pci_match_device(pci_drv, pci_dev);
474 return 0;
475
476 found_id = pci_match_device(ids, pci_dev);
477 if (found_id) 422 if (found_id)
478 return 1; 423 return 1;
479 424
480 return pci_bus_match_dynids(pci_dev, pci_drv); 425 return 0;
481} 426}
482 427
483/** 428/**
@@ -536,6 +481,7 @@ static int __init pci_driver_init(void)
536 481
537postcore_initcall(pci_driver_init); 482postcore_initcall(pci_driver_init);
538 483
484EXPORT_SYMBOL(pci_match_id);
539EXPORT_SYMBOL(pci_match_device); 485EXPORT_SYMBOL(pci_match_device);
540EXPORT_SYMBOL(pci_register_driver); 486EXPORT_SYMBOL(pci_register_driver);
541EXPORT_SYMBOL(pci_unregister_driver); 487EXPORT_SYMBOL(pci_unregister_driver);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index f04b9ffe4153..1b34fc56067e 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -235,7 +235,7 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
235 * -EIO if device does not support PCI PM. 235 * -EIO if device does not support PCI PM.
236 * 0 if we can successfully change the power state. 236 * 0 if we can successfully change the power state.
237 */ 237 */
238 238int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t);
239int 239int
240pci_set_power_state(struct pci_dev *dev, pci_power_t state) 240pci_set_power_state(struct pci_dev *dev, pci_power_t state)
241{ 241{
@@ -299,11 +299,20 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
299 msleep(10); 299 msleep(10);
300 else if (state == PCI_D2 || dev->current_state == PCI_D2) 300 else if (state == PCI_D2 || dev->current_state == PCI_D2)
301 udelay(200); 301 udelay(200);
302 dev->current_state = state;
303 302
303 /*
304 * Give firmware a chance to be called, such as ACPI _PRx, _PSx
305 * Firmware method after natice method ?
306 */
307 if (platform_pci_set_power_state)
308 platform_pci_set_power_state(dev, state);
309
310 dev->current_state = state;
304 return 0; 311 return 0;
305} 312}
306 313
314int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
315
307/** 316/**
308 * pci_choose_state - Choose the power state of a PCI device 317 * pci_choose_state - Choose the power state of a PCI device
309 * @dev: PCI device to be suspended 318 * @dev: PCI device to be suspended
@@ -316,10 +325,17 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
316 325
317pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) 326pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
318{ 327{
328 int ret;
329
319 if (!pci_find_capability(dev, PCI_CAP_ID_PM)) 330 if (!pci_find_capability(dev, PCI_CAP_ID_PM))
320 return PCI_D0; 331 return PCI_D0;
321 332
322 switch (state) { 333 if (platform_pci_choose_state) {
334 ret = platform_pci_choose_state(dev, state);
335 if (ret >= 0)
336 state = ret;
337 }
338 switch (state) {
323 case 0: return PCI_D0; 339 case 0: return PCI_D0;
324 case 3: return PCI_D3hot; 340 case 3: return PCI_D3hot;
325 default: 341 default:
@@ -334,10 +350,6 @@ EXPORT_SYMBOL(pci_choose_state);
334/** 350/**
335 * pci_save_state - save the PCI configuration space of a device before suspending 351 * pci_save_state - save the PCI configuration space of a device before suspending
336 * @dev: - PCI device that we're dealing with 352 * @dev: - PCI device that we're dealing with
337 * @buffer: - buffer to hold config space context
338 *
339 * @buffer must be large enough to hold the entire PCI 2.2 config space
340 * (>= 64 bytes).
341 */ 353 */
342int 354int
343pci_save_state(struct pci_dev *dev) 355pci_save_state(struct pci_dev *dev)
@@ -352,8 +364,6 @@ pci_save_state(struct pci_dev *dev)
352/** 364/**
353 * pci_restore_state - Restore the saved state of a PCI device 365 * pci_restore_state - Restore the saved state of a PCI device
354 * @dev: - PCI device that we're dealing with 366 * @dev: - PCI device that we're dealing with
355 * @buffer: - saved PCI config space
356 *
357 */ 367 */
358int 368int
359pci_restore_state(struct pci_dev *dev) 369pci_restore_state(struct pci_dev *dev)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 744da0d4ae5f..d94d7af4f7a0 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -11,6 +11,10 @@ extern int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
11 void (*alignf)(void *, struct resource *, 11 void (*alignf)(void *, struct resource *,
12 unsigned long, unsigned long), 12 unsigned long, unsigned long),
13 void *alignf_data); 13 void *alignf_data);
14/* Firmware callbacks */
15extern int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
16extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state);
17
14/* PCI /proc functions */ 18/* PCI /proc functions */
15#ifdef CONFIG_PROC_FS 19#ifdef CONFIG_PROC_FS
16extern int pci_proc_attach_device(struct pci_dev *dev); 20extern int pci_proc_attach_device(struct pci_dev *dev);
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h
index 537b372dc340..a63bd8f72601 100644
--- a/drivers/pci/pcie/portdrv.h
+++ b/drivers/pci/pcie/portdrv.h
@@ -27,6 +27,11 @@
27 27
28#define get_descriptor_id(type, service) (((type - 4) << 4) | service) 28#define get_descriptor_id(type, service) (((type - 4) << 4) | service)
29 29
30struct pcie_port_device_ext {
31 int interrupt_mode; /* [0:INTx | 1:MSI | 2:MSI-X] */
32 unsigned int saved_msi_config_space[5];
33};
34
30extern struct bus_type pcie_port_bus_type; 35extern struct bus_type pcie_port_bus_type;
31extern int pcie_port_device_probe(struct pci_dev *dev); 36extern int pcie_port_device_probe(struct pci_dev *dev);
32extern int pcie_port_device_register(struct pci_dev *dev); 37extern int pcie_port_device_register(struct pci_dev *dev);
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index f5c5f10a3d2f..393e0cee91a9 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -275,10 +275,17 @@ int pcie_port_device_probe(struct pci_dev *dev)
275 275
276int pcie_port_device_register(struct pci_dev *dev) 276int pcie_port_device_register(struct pci_dev *dev)
277{ 277{
278 struct pcie_port_device_ext *p_ext;
278 int status, type, capabilities, irq_mode, i; 279 int status, type, capabilities, irq_mode, i;
279 int vectors[PCIE_PORT_DEVICE_MAXSERVICES]; 280 int vectors[PCIE_PORT_DEVICE_MAXSERVICES];
280 u16 reg16; 281 u16 reg16;
281 282
283 /* Allocate port device extension */
284 if (!(p_ext = kmalloc(sizeof(struct pcie_port_device_ext), GFP_KERNEL)))
285 return -ENOMEM;
286
287 pci_set_drvdata(dev, p_ext);
288
282 /* Get port type */ 289 /* Get port type */
283 pci_read_config_word(dev, 290 pci_read_config_word(dev,
284 pci_find_capability(dev, PCI_CAP_ID_EXP) + 291 pci_find_capability(dev, PCI_CAP_ID_EXP) +
@@ -288,6 +295,7 @@ int pcie_port_device_register(struct pci_dev *dev)
288 /* Now get port services */ 295 /* Now get port services */
289 capabilities = get_port_device_capability(dev); 296 capabilities = get_port_device_capability(dev);
290 irq_mode = assign_interrupt_mode(dev, vectors, capabilities); 297 irq_mode = assign_interrupt_mode(dev, vectors, capabilities);
298 p_ext->interrupt_mode = irq_mode;
291 299
292 /* Allocate child services if any */ 300 /* Allocate child services if any */
293 for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) { 301 for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
@@ -317,7 +325,7 @@ int pcie_port_device_register(struct pci_dev *dev)
317static int suspend_iter(struct device *dev, void *data) 325static int suspend_iter(struct device *dev, void *data)
318{ 326{
319 struct pcie_port_service_driver *service_driver; 327 struct pcie_port_service_driver *service_driver;
320 u32 state = (u32)data; 328 pm_message_t state = * (pm_message_t *) data;
321 329
322 if ((dev->bus == &pcie_port_bus_type) && 330 if ((dev->bus == &pcie_port_bus_type) &&
323 (dev->driver)) { 331 (dev->driver)) {
@@ -328,9 +336,9 @@ static int suspend_iter(struct device *dev, void *data)
328 return 0; 336 return 0;
329} 337}
330 338
331int pcie_port_device_suspend(struct pci_dev *dev, u32 state) 339int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state)
332{ 340{
333 device_for_each_child(&dev->dev, (void *)state, suspend_iter); 341 device_for_each_child(&dev->dev, &state, suspend_iter);
334 return 0; 342 return 0;
335} 343}
336 344
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index e9095ee508e3..30bac7ed7c16 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -29,6 +29,78 @@ MODULE_LICENSE("GPL");
29/* global data */ 29/* global data */
30static const char device_name[] = "pcieport-driver"; 30static const char device_name[] = "pcieport-driver";
31 31
32static void pci_save_msi_state(struct pci_dev *dev)
33{
34 struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev);
35 int i = 0, pos;
36 u16 control;
37
38 if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) <= 0)
39 return;
40
41 pci_read_config_dword(dev, pos, &p_ext->saved_msi_config_space[i++]);
42 control = p_ext->saved_msi_config_space[0] >> 16;
43 pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO,
44 &p_ext->saved_msi_config_space[i++]);
45 if (control & PCI_MSI_FLAGS_64BIT) {
46 pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI,
47 &p_ext->saved_msi_config_space[i++]);
48 pci_read_config_dword(dev, pos + PCI_MSI_DATA_64,
49 &p_ext->saved_msi_config_space[i++]);
50 } else
51 pci_read_config_dword(dev, pos + PCI_MSI_DATA_32,
52 &p_ext->saved_msi_config_space[i++]);
53 if (control & PCI_MSI_FLAGS_MASKBIT)
54 pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT,
55 &p_ext->saved_msi_config_space[i++]);
56}
57
58static void pci_restore_msi_state(struct pci_dev *dev)
59{
60 struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev);
61 int i = 0, pos;
62 u16 control;
63
64 if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) <= 0)
65 return;
66
67 control = p_ext->saved_msi_config_space[i++] >> 16;
68 pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
69 pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO,
70 p_ext->saved_msi_config_space[i++]);
71 if (control & PCI_MSI_FLAGS_64BIT) {
72 pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI,
73 p_ext->saved_msi_config_space[i++]);
74 pci_write_config_dword(dev, pos + PCI_MSI_DATA_64,
75 p_ext->saved_msi_config_space[i++]);
76 } else
77 pci_write_config_dword(dev, pos + PCI_MSI_DATA_32,
78 p_ext->saved_msi_config_space[i++]);
79 if (control & PCI_MSI_FLAGS_MASKBIT)
80 pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT,
81 p_ext->saved_msi_config_space[i++]);
82}
83
84static void pcie_portdrv_save_config(struct pci_dev *dev)
85{
86 struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev);
87
88 pci_save_state(dev);
89 if (p_ext->interrupt_mode == PCIE_PORT_MSI_MODE)
90 pci_save_msi_state(dev);
91}
92
93static void pcie_portdrv_restore_config(struct pci_dev *dev)
94{
95 struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev);
96
97 pci_restore_state(dev);
98 if (p_ext->interrupt_mode == PCIE_PORT_MSI_MODE)
99 pci_restore_msi_state(dev);
100 pci_enable_device(dev);
101 pci_set_master(dev);
102}
103
32/* 104/*
33 * pcie_portdrv_probe - Probe PCI-Express port devices 105 * pcie_portdrv_probe - Probe PCI-Express port devices
34 * @dev: PCI-Express port device being probed 106 * @dev: PCI-Express port device being probed
@@ -64,16 +136,21 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev,
64static void pcie_portdrv_remove (struct pci_dev *dev) 136static void pcie_portdrv_remove (struct pci_dev *dev)
65{ 137{
66 pcie_port_device_remove(dev); 138 pcie_port_device_remove(dev);
139 kfree(pci_get_drvdata(dev));
67} 140}
68 141
69#ifdef CONFIG_PM 142#ifdef CONFIG_PM
70static int pcie_portdrv_suspend (struct pci_dev *dev, pm_message_t state) 143static int pcie_portdrv_suspend (struct pci_dev *dev, pm_message_t state)
71{ 144{
72 return pcie_port_device_suspend(dev, state); 145 int ret = pcie_port_device_suspend(dev, state);
146
147 pcie_portdrv_save_config(dev);
148 return ret;
73} 149}
74 150
75static int pcie_portdrv_resume (struct pci_dev *dev) 151static int pcie_portdrv_resume (struct pci_dev *dev)
76{ 152{
153 pcie_portdrv_restore_config(dev);
77 return pcie_port_device_resume(dev); 154 return pcie_port_device_resume(dev);
78} 155}
79#endif 156#endif
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 6a0a82f0508b..df3bdae2040f 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -239,9 +239,8 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
239 239
240 if (dev->transparent) { 240 if (dev->transparent) {
241 printk(KERN_INFO "PCI: Transparent bridge - %s\n", pci_name(dev)); 241 printk(KERN_INFO "PCI: Transparent bridge - %s\n", pci_name(dev));
242 for(i = 0; i < PCI_BUS_NUM_RESOURCES; i++) 242 for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++)
243 child->resource[i] = child->parent->resource[i]; 243 child->resource[i] = child->parent->resource[i - 3];
244 return;
245 } 244 }
246 245
247 for(i=0; i<3; i++) 246 for(i=0; i<3; i++)
@@ -398,6 +397,16 @@ static void pci_enable_crs(struct pci_dev *dev)
398 pci_write_config_word(dev, rpcap + PCI_EXP_RTCTL, rpctl); 397 pci_write_config_word(dev, rpcap + PCI_EXP_RTCTL, rpctl);
399} 398}
400 399
400static void __devinit pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
401{
402 struct pci_bus *parent = child->parent;
403 while (parent->parent && parent->subordinate < max) {
404 parent->subordinate = max;
405 pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max);
406 parent = parent->parent;
407 }
408}
409
401unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus); 410unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus);
402 411
403/* 412/*
@@ -499,7 +508,13 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
499 508
500 if (!is_cardbus) { 509 if (!is_cardbus) {
501 child->bridge_ctl = PCI_BRIDGE_CTL_NO_ISA; 510 child->bridge_ctl = PCI_BRIDGE_CTL_NO_ISA;
502 511 /*
512 * Adjust subordinate busnr in parent buses.
513 * We do this before scanning for children because
514 * some devices may not be detected if the bios
515 * was lazy.
516 */
517 pci_fixup_parent_subordinate_busnr(child, max);
503 /* Now we can scan all subordinate buses... */ 518 /* Now we can scan all subordinate buses... */
504 max = pci_scan_child_bus(child); 519 max = pci_scan_child_bus(child);
505 } else { 520 } else {
@@ -513,6 +528,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
513 max+i+1)) 528 max+i+1))
514 break; 529 break;
515 max += i; 530 max += i;
531 pci_fixup_parent_subordinate_busnr(child, max);
516 } 532 }
517 /* 533 /*
518 * Set the subordinate bus number to its real value. 534 * Set the subordinate bus number to its real value.
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 968033fd29f0..1521fd5d95cc 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -767,6 +767,7 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
767 if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK)) { 767 if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK)) {
768 if (dev->device == PCI_DEVICE_ID_INTEL_82845_HB) 768 if (dev->device == PCI_DEVICE_ID_INTEL_82845_HB)
769 switch(dev->subsystem_device) { 769 switch(dev->subsystem_device) {
770 case 0x8025: /* P4B-LX */
770 case 0x8070: /* P4B */ 771 case 0x8070: /* P4B */
771 case 0x8088: /* P4B533 */ 772 case 0x8088: /* P4B533 */
772 case 0x1626: /* L3C notebook */ 773 case 0x1626: /* L3C notebook */
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index a90a533eba0f..05fa91a31c62 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -379,6 +379,7 @@ exit:
379EXPORT_SYMBOL(pci_dev_present); 379EXPORT_SYMBOL(pci_dev_present);
380 380
381EXPORT_SYMBOL(pci_find_bus); 381EXPORT_SYMBOL(pci_find_bus);
382EXPORT_SYMBOL(pci_find_next_bus);
382EXPORT_SYMBOL(pci_find_device); 383EXPORT_SYMBOL(pci_find_device);
383EXPORT_SYMBOL(pci_find_device_reverse); 384EXPORT_SYMBOL(pci_find_device_reverse);
384EXPORT_SYMBOL(pci_find_slot); 385EXPORT_SYMBOL(pci_find_slot);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 6b628de948af..9fe48f712be9 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -74,6 +74,7 @@ pbus_assign_resources_sorted(struct pci_bus *bus)
74 idx = res - &list->dev->resource[0]; 74 idx = res - &list->dev->resource[0];
75 if (pci_assign_resource(list->dev, idx)) { 75 if (pci_assign_resource(list->dev, idx)) {
76 res->start = 0; 76 res->start = 0;
77 res->end = 0;
77 res->flags = 0; 78 res->flags = 0;
78 } 79 }
79 tmp = list; 80 tmp = list;
@@ -273,6 +274,8 @@ find_free_bus_resource(struct pci_bus *bus, unsigned long type)
273 274
274 for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { 275 for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
275 r = bus->resource[i]; 276 r = bus->resource[i];
277 if (r == &ioport_resource || r == &iomem_resource)
278 continue;
276 if (r && (r->flags & type_mask) == type && !r->parent) 279 if (r && (r->flags & type_mask) == type && !r->parent)
277 return r; 280 return r;
278 } 281 }