diff options
author | Andrew Patterson <andrew.patterson@hp.com> | 2008-11-10 17:30:45 -0500 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-01-07 14:12:27 -0500 |
commit | 990a7ac5645883a833a11b900bb6f25b65dea65b (patch) | |
tree | 8644b7da9b41069d873d2b4dbe600bc5a828347d /drivers | |
parent | 8b62091e20215730be1b94b7cd135a78a3e692ca (diff) |
ACPI/PCI: call _OSC support during root bridge discovery
Add pci_acpi_osc_support() and call it when a PCI bridge is added. This
allows us to avoid having every individual PCI root bridge driver call
_OSC support for every root bridge in their probe functions, a
significant savings in boot time.
Signed-off-by: Matthew Wilcox <willy@linux.intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/pci_root.c | 9 | ||||
-rw-r--r-- | drivers/pci/pci-acpi.c | 24 |
2 files changed, 28 insertions, 5 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 642554b1b60c..de4d57114fe4 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/spinlock.h> | 31 | #include <linux/spinlock.h> |
32 | #include <linux/pm.h> | 32 | #include <linux/pm.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/pci-acpi.h> | ||
34 | #include <linux/acpi.h> | 35 | #include <linux/acpi.h> |
35 | #include <acpi/acpi_bus.h> | 36 | #include <acpi/acpi_bus.h> |
36 | #include <acpi/acpi_drivers.h> | 37 | #include <acpi/acpi_drivers.h> |
@@ -193,6 +194,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
193 | unsigned long long value = 0; | 194 | unsigned long long value = 0; |
194 | acpi_handle handle = NULL; | 195 | acpi_handle handle = NULL; |
195 | struct acpi_device *child; | 196 | struct acpi_device *child; |
197 | u32 flags; | ||
196 | 198 | ||
197 | 199 | ||
198 | if (!device) | 200 | if (!device) |
@@ -210,6 +212,13 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
210 | 212 | ||
211 | device->ops.bind = acpi_pci_bind; | 213 | device->ops.bind = acpi_pci_bind; |
212 | 214 | ||
215 | /* | ||
216 | * All supported architectures that use ACPI have support for | ||
217 | * PCI domains, so we indicate this in _OSC support capabilities. | ||
218 | */ | ||
219 | flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; | ||
220 | pci_acpi_osc_support(device->handle, flags); | ||
221 | |||
213 | /* | 222 | /* |
214 | * Segment | 223 | * Segment |
215 | * ------- | 224 | * ------- |
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 2ed3f10d0860..8a1f02c3c915 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -143,28 +143,42 @@ static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data, | |||
143 | return status; | 143 | return status; |
144 | } | 144 | } |
145 | 145 | ||
146 | static acpi_status acpi_query_osc(acpi_handle handle, | 146 | /* |
147 | u32 level, void *context, void **retval) | 147 | * pci_acpi_osc_support: Invoke _OSC indicating support for the given feature |
148 | * @flags: Bitmask of flags to support | ||
149 | * | ||
150 | * See the ACPI spec for the definition of the flags | ||
151 | */ | ||
152 | int pci_acpi_osc_support(acpi_handle handle, u32 flags) | ||
148 | { | 153 | { |
154 | u32 dummy; | ||
149 | acpi_status status; | 155 | acpi_status status; |
150 | struct acpi_osc_data *osc_data; | ||
151 | u32 flags = (unsigned long)context, dummy; | ||
152 | acpi_handle tmp; | 156 | acpi_handle tmp; |
157 | struct acpi_osc_data *osc_data; | ||
158 | int rc = 0; | ||
153 | 159 | ||
154 | status = acpi_get_handle(handle, "_OSC", &tmp); | 160 | status = acpi_get_handle(handle, "_OSC", &tmp); |
155 | if (ACPI_FAILURE(status)) | 161 | if (ACPI_FAILURE(status)) |
156 | return AE_OK; | 162 | return -ENOTTY; |
157 | 163 | ||
158 | mutex_lock(&pci_acpi_lock); | 164 | mutex_lock(&pci_acpi_lock); |
159 | osc_data = acpi_get_osc_data(handle); | 165 | osc_data = acpi_get_osc_data(handle); |
160 | if (!osc_data) { | 166 | if (!osc_data) { |
161 | printk(KERN_ERR "acpi osc data array is full\n"); | 167 | printk(KERN_ERR "acpi osc data array is full\n"); |
168 | rc = -ENOMEM; | ||
162 | goto out; | 169 | goto out; |
163 | } | 170 | } |
164 | 171 | ||
165 | __acpi_query_osc(flags, osc_data, &dummy); | 172 | __acpi_query_osc(flags, osc_data, &dummy); |
166 | out: | 173 | out: |
167 | mutex_unlock(&pci_acpi_lock); | 174 | mutex_unlock(&pci_acpi_lock); |
175 | return rc; | ||
176 | } | ||
177 | |||
178 | static acpi_status acpi_query_osc(acpi_handle handle, u32 level, | ||
179 | void *context, void **retval) | ||
180 | { | ||
181 | pci_acpi_osc_support(handle, (unsigned long)context); | ||
168 | return AE_OK; | 182 | return AE_OK; |
169 | } | 183 | } |
170 | 184 | ||