diff options
author | Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> | 2006-05-01 21:54:50 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-06-19 17:13:22 -0400 |
commit | 7430e34c70106a9576fc61d77604d164b187a1b7 (patch) | |
tree | 4b9eeaaa3702c9be216f820e8eeaf11f93610d2c /drivers/pci | |
parent | 2433ee2654f0ac86f7886e5a8d01bee7f3c7c6db (diff) |
[PATCH] acpi_pcihp: Fix programming _HPP values
This patch fixes the problem that hotplug parameters are not programed
when PCI cards are hot-added by ACPIPHP, SHPCHP and PCIEHP driver. The
pci_dev structure being hot-added is not bound to ACPI handle, so we
need to trace PCI bus tree to find ACPI handle.
Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Cc: Kristen Accardi <kristen.c.accardi@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/hotplug/acpi_pcihp.c | 34 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 3 | ||||
-rw-r--r-- | drivers/pci/hotplug/pci_hotplug.h | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp.h | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp.h | 2 |
5 files changed, 29 insertions, 14 deletions
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 64cb30d7fc9a..9395fec73423 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c | |||
@@ -145,14 +145,27 @@ EXPORT_SYMBOL_GPL(acpi_run_oshp); | |||
145 | 145 | ||
146 | /* acpi_get_hp_params_from_firmware | 146 | /* acpi_get_hp_params_from_firmware |
147 | * | 147 | * |
148 | * @dev - the pci_dev of the newly added device | 148 | * @bus - the pci_bus of the bus on which the device is newly added |
149 | * @hpp - allocated by the caller | 149 | * @hpp - allocated by the caller |
150 | */ | 150 | */ |
151 | acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, | 151 | acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, |
152 | struct hotplug_params *hpp) | 152 | struct hotplug_params *hpp) |
153 | { | 153 | { |
154 | acpi_status status = AE_NOT_FOUND; | 154 | acpi_status status = AE_NOT_FOUND; |
155 | struct pci_dev *pdev = dev; | 155 | acpi_handle handle, phandle; |
156 | struct pci_bus *pbus = bus; | ||
157 | struct pci_dev *pdev; | ||
158 | |||
159 | do { | ||
160 | pdev = pbus->self; | ||
161 | if (!pdev) { | ||
162 | handle = acpi_get_pci_rootbridge_handle( | ||
163 | pci_domain_nr(pbus), pbus->number); | ||
164 | break; | ||
165 | } | ||
166 | handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); | ||
167 | pbus = pbus->parent; | ||
168 | } while (!handle); | ||
156 | 169 | ||
157 | /* | 170 | /* |
158 | * _HPP settings apply to all child buses, until another _HPP is | 171 | * _HPP settings apply to all child buses, until another _HPP is |
@@ -160,15 +173,16 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, | |||
160 | * look for it in the parent device scope since that would apply to | 173 | * look for it in the parent device scope since that would apply to |
161 | * this pci dev. If we don't find any _HPP, use hardcoded defaults | 174 | * this pci dev. If we don't find any _HPP, use hardcoded defaults |
162 | */ | 175 | */ |
163 | while (pdev && (ACPI_FAILURE(status))) { | 176 | while (handle) { |
164 | acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); | ||
165 | if (!handle) | ||
166 | break; | ||
167 | status = acpi_run_hpp(handle, hpp); | 177 | status = acpi_run_hpp(handle, hpp); |
168 | if (!(pdev->bus->parent)) | 178 | if (ACPI_SUCCESS(status)) |
179 | break; | ||
180 | if (acpi_root_bridge(handle)) | ||
181 | break; | ||
182 | status = acpi_get_parent(handle, &phandle); | ||
183 | if (ACPI_FAILURE(status)) | ||
169 | break; | 184 | break; |
170 | /* Check if a parent object supports _HPP */ | 185 | handle = phandle; |
171 | pdev = pdev->bus->parent->self; | ||
172 | } | 186 | } |
173 | return status; | 187 | return status; |
174 | } | 188 | } |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 2a83e6bdab6a..4b0988e93806 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -286,7 +286,7 @@ static void decode_hpp(struct acpiphp_bridge *bridge) | |||
286 | { | 286 | { |
287 | acpi_status status; | 287 | acpi_status status; |
288 | 288 | ||
289 | status = acpi_get_hp_params_from_firmware(bridge->pci_dev, &bridge->hpp); | 289 | status = acpi_get_hp_params_from_firmware(bridge->pci_bus, &bridge->hpp); |
290 | if (ACPI_FAILURE(status)) { | 290 | if (ACPI_FAILURE(status)) { |
291 | /* use default numbers */ | 291 | /* use default numbers */ |
292 | bridge->hpp.cache_line_size = 0x10; | 292 | bridge->hpp.cache_line_size = 0x10; |
@@ -1250,6 +1250,7 @@ static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus) | |||
1250 | 1250 | ||
1251 | memset(&bridge, 0, sizeof(bridge)); | 1251 | memset(&bridge, 0, sizeof(bridge)); |
1252 | bridge.handle = handle; | 1252 | bridge.handle = handle; |
1253 | bridge.pci_bus = bus; | ||
1253 | bridge.pci_dev = bus->self; | 1254 | bridge.pci_dev = bus->self; |
1254 | decode_hpp(&bridge); | 1255 | decode_hpp(&bridge); |
1255 | list_for_each_entry(dev, &bus->devices, bus_list) | 1256 | list_for_each_entry(dev, &bus->devices, bus_list) |
diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h index eb0d01d47236..6913ace70e9b 100644 --- a/drivers/pci/hotplug/pci_hotplug.h +++ b/drivers/pci/hotplug/pci_hotplug.h | |||
@@ -188,7 +188,7 @@ struct hotplug_params { | |||
188 | #include <acpi/acpi_bus.h> | 188 | #include <acpi/acpi_bus.h> |
189 | #include <acpi/actypes.h> | 189 | #include <acpi/actypes.h> |
190 | extern acpi_status acpi_run_oshp(acpi_handle handle); | 190 | extern acpi_status acpi_run_oshp(acpi_handle handle); |
191 | extern acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, | 191 | extern acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, |
192 | struct hotplug_params *hpp); | 192 | struct hotplug_params *hpp); |
193 | int acpi_root_bridge(acpi_handle handle); | 193 | int acpi_root_bridge(acpi_handle handle); |
194 | #endif | 194 | #endif |
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 92c1f0f1e1ad..ce89f5815861 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -284,7 +284,7 @@ struct hpc_ops { | |||
284 | static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, | 284 | static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, |
285 | struct hotplug_params *hpp) | 285 | struct hotplug_params *hpp) |
286 | { | 286 | { |
287 | if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp))) | 287 | if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp))) |
288 | return -ENODEV; | 288 | return -ENODEV; |
289 | return 0; | 289 | return 0; |
290 | } | 290 | } |
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 5c70f43908c4..b70fddbce934 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
@@ -196,7 +196,7 @@ extern void queue_pushbutton_work(void *data); | |||
196 | static inline int get_hp_params_from_firmware(struct pci_dev *dev, | 196 | static inline int get_hp_params_from_firmware(struct pci_dev *dev, |
197 | struct hotplug_params *hpp) | 197 | struct hotplug_params *hpp) |
198 | { | 198 | { |
199 | if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp))) | 199 | if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp))) |
200 | return -ENODEV; | 200 | return -ENODEV; |
201 | return 0; | 201 | return 0; |
202 | } | 202 | } |