diff options
-rw-r--r-- | drivers/pci/hotplug/pciehp_pci.c | 52 |
1 files changed, 28 insertions, 24 deletions
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 647673a7d22..4017fb03a0b 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c | |||
@@ -34,6 +34,31 @@ | |||
34 | #include "../pci.h" | 34 | #include "../pci.h" |
35 | #include "pciehp.h" | 35 | #include "pciehp.h" |
36 | 36 | ||
37 | static int pciehp_add_bridge(struct pci_dev *dev) | ||
38 | { | ||
39 | struct pci_bus *parent = dev->bus; | ||
40 | int pass, busnr, start = parent->secondary; | ||
41 | int end = parent->subordinate; | ||
42 | |||
43 | for (busnr = start; busnr <= end; busnr++) { | ||
44 | if (!pci_find_bus(pci_domain_nr(parent), busnr)) | ||
45 | break; | ||
46 | } | ||
47 | if (busnr-- > end) { | ||
48 | err("No bus number available for hot-added bridge %s\n", | ||
49 | pci_name(dev)); | ||
50 | return -1; | ||
51 | } | ||
52 | for (pass = 0; pass < 2; pass++) | ||
53 | busnr = pci_scan_bridge(parent, dev, busnr, pass); | ||
54 | if (!dev->subordinate) | ||
55 | return -1; | ||
56 | pci_bus_size_bridges(dev->subordinate); | ||
57 | pci_bus_assign_resources(parent); | ||
58 | pci_enable_bridges(parent); | ||
59 | pci_bus_add_devices(parent); | ||
60 | return 0; | ||
61 | } | ||
37 | 62 | ||
38 | int pciehp_configure_device(struct slot *p_slot) | 63 | int pciehp_configure_device(struct slot *p_slot) |
39 | { | 64 | { |
@@ -55,8 +80,8 @@ int pciehp_configure_device(struct slot *p_slot) | |||
55 | } | 80 | } |
56 | 81 | ||
57 | for (fn = 0; fn < 8; fn++) { | 82 | for (fn = 0; fn < 8; fn++) { |
58 | if (!(dev = pci_find_slot(p_slot->bus, | 83 | dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn)); |
59 | PCI_DEVFN(p_slot->device, fn)))) | 84 | if (!dev) |
60 | continue; | 85 | continue; |
61 | if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | 86 | if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { |
62 | err("Cannot hot-add display device %s\n", | 87 | err("Cannot hot-add display device %s\n", |
@@ -65,27 +90,7 @@ int pciehp_configure_device(struct slot *p_slot) | |||
65 | } | 90 | } |
66 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || | 91 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || |
67 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { | 92 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { |
68 | /* Find an unused bus number for the new bridge */ | 93 | pciehp_add_bridge(dev); |
69 | struct pci_bus *child; | ||
70 | unsigned char busnr, start = parent->secondary; | ||
71 | unsigned char end = parent->subordinate; | ||
72 | for (busnr = start; busnr <= end; busnr++) { | ||
73 | if (!pci_find_bus(pci_domain_nr(parent), | ||
74 | busnr)) | ||
75 | break; | ||
76 | } | ||
77 | if (busnr >= end) { | ||
78 | err("No free bus for hot-added bridge\n"); | ||
79 | continue; | ||
80 | } | ||
81 | child = pci_add_new_bus(parent, dev, busnr); | ||
82 | if (!child) { | ||
83 | err("Cannot add new bus for %s\n", | ||
84 | pci_name(dev)); | ||
85 | continue; | ||
86 | } | ||
87 | child->subordinate = pci_do_scan_bus(child); | ||
88 | pci_bus_size_bridges(child); | ||
89 | } | 94 | } |
90 | /* TBD: program firmware provided _HPP values */ | 95 | /* TBD: program firmware provided _HPP values */ |
91 | /* program_fw_provided_values(dev); */ | 96 | /* program_fw_provided_values(dev); */ |
@@ -93,7 +98,6 @@ int pciehp_configure_device(struct slot *p_slot) | |||
93 | 98 | ||
94 | pci_bus_assign_resources(parent); | 99 | pci_bus_assign_resources(parent); |
95 | pci_bus_add_devices(parent); | 100 | pci_bus_add_devices(parent); |
96 | pci_enable_bridges(parent); | ||
97 | return 0; | 101 | return 0; |
98 | } | 102 | } |
99 | 103 | ||