diff options
author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2009-09-14 18:35:40 -0400 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-09-14 20:39:14 -0400 |
commit | 5e3573db2bd5db6925159279d99576a4635bdb66 (patch) | |
tree | a90efab044203abfda470f464cd056fe97497121 /drivers/pci/hotplug | |
parent | e81995bb1c0077a312cb621abc406a36f65a986a (diff) |
PCI hotplug: clean up acpi_run_hpp()
This patch cleans up acpi_run_hpp() and follows the style of acpi_run_hpx():
- remove unnecessary METHOD_NAME__HPP #define
- use ACPI_ALLOCATE_BUFFER rather than evaluating _HPP twice
- validate _HPP package length (defined as 4 by the spec)
- avoid ref to undefined data if FW provides < 4 elements
- remove temporary nui[] array
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Reviewed-by: Alex Chiang <achiang@hp.com>
Reviewed-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Acked-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r-- | drivers/pci/hotplug/acpi_pcihp.c | 84 |
1 files changed, 22 insertions, 62 deletions
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index ee24de1c5fae..a73028ec52e5 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg) | 41 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg) |
42 | 42 | ||
43 | #define METHOD_NAME__SUN "_SUN" | 43 | #define METHOD_NAME__SUN "_SUN" |
44 | #define METHOD_NAME__HPP "_HPP" | ||
45 | #define METHOD_NAME_OSHP "OSHP" | 44 | #define METHOD_NAME_OSHP "OSHP" |
46 | 45 | ||
47 | static int debug_acpi; | 46 | static int debug_acpi; |
@@ -215,80 +214,41 @@ acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx) | |||
215 | static acpi_status | 214 | static acpi_status |
216 | acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) | 215 | acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) |
217 | { | 216 | { |
218 | acpi_status status; | 217 | acpi_status status; |
219 | u8 nui[4]; | 218 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
220 | struct acpi_buffer ret_buf = { 0, NULL}; | 219 | union acpi_object *package, *fields; |
221 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; | 220 | int i; |
222 | union acpi_object *ext_obj, *package; | ||
223 | int i, len = 0; | ||
224 | |||
225 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); | ||
226 | 221 | ||
227 | /* Clear the return buffer with zeros */ | ||
228 | memset(hpp, 0, sizeof(struct hotplug_params)); | 222 | memset(hpp, 0, sizeof(struct hotplug_params)); |
229 | 223 | ||
230 | /* get _hpp */ | 224 | status = acpi_evaluate_object(handle, "_HPP", NULL, &buffer); |
231 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); | 225 | if (ACPI_FAILURE(status)) |
232 | switch (status) { | 226 | return status; |
233 | case AE_BUFFER_OVERFLOW: | ||
234 | ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); | ||
235 | if (!ret_buf.pointer) { | ||
236 | printk(KERN_ERR "%s:%s alloc for _HPP fail\n", | ||
237 | __func__, (char *)string.pointer); | ||
238 | kfree(string.pointer); | ||
239 | return AE_NO_MEMORY; | ||
240 | } | ||
241 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, | ||
242 | NULL, &ret_buf); | ||
243 | if (ACPI_SUCCESS(status)) | ||
244 | break; | ||
245 | default: | ||
246 | if (ACPI_FAILURE(status)) { | ||
247 | pr_debug("%s:%s _HPP fail=0x%x\n", __func__, | ||
248 | (char *)string.pointer, status); | ||
249 | kfree(string.pointer); | ||
250 | return status; | ||
251 | } | ||
252 | } | ||
253 | 227 | ||
254 | ext_obj = (union acpi_object *) ret_buf.pointer; | 228 | package = (union acpi_object *) buffer.pointer; |
255 | if (ext_obj->type != ACPI_TYPE_PACKAGE) { | 229 | if (package->type != ACPI_TYPE_PACKAGE || |
256 | printk(KERN_ERR "%s:%s _HPP obj not a package\n", __func__, | 230 | package->package.count != 4) { |
257 | (char *)string.pointer); | ||
258 | status = AE_ERROR; | 231 | status = AE_ERROR; |
259 | goto free_and_return; | 232 | goto exit; |
260 | } | 233 | } |
261 | 234 | ||
262 | len = ext_obj->package.count; | 235 | fields = package->package.elements; |
263 | package = (union acpi_object *) ret_buf.pointer; | 236 | for (i = 0; i < 4; i++) { |
264 | for ( i = 0; (i < len) || (i < 4); i++) { | 237 | if (fields[i].type != ACPI_TYPE_INTEGER) { |
265 | ext_obj = (union acpi_object *) &package->package.elements[i]; | ||
266 | switch (ext_obj->type) { | ||
267 | case ACPI_TYPE_INTEGER: | ||
268 | nui[i] = (u8)ext_obj->integer.value; | ||
269 | break; | ||
270 | default: | ||
271 | printk(KERN_ERR "%s:%s _HPP obj type incorrect\n", | ||
272 | __func__, (char *)string.pointer); | ||
273 | status = AE_ERROR; | 238 | status = AE_ERROR; |
274 | goto free_and_return; | 239 | goto exit; |
275 | } | 240 | } |
276 | } | 241 | } |
277 | 242 | ||
278 | hpp->t0 = &hpp->type0_data; | 243 | hpp->t0 = &hpp->type0_data; |
279 | hpp->t0->cache_line_size = nui[0]; | 244 | hpp->t0->revision = 1; |
280 | hpp->t0->latency_timer = nui[1]; | 245 | hpp->t0->cache_line_size = fields[0].integer.value; |
281 | hpp->t0->enable_serr = nui[2]; | 246 | hpp->t0->latency_timer = fields[1].integer.value; |
282 | hpp->t0->enable_perr = nui[3]; | 247 | hpp->t0->enable_serr = fields[2].integer.value; |
283 | 248 | hpp->t0->enable_perr = fields[3].integer.value; | |
284 | pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->t0->cache_line_size); | ||
285 | pr_debug(" _HPP: latency timer =0x%x\n", hpp->t0->latency_timer); | ||
286 | pr_debug(" _HPP: enable SERR =0x%x\n", hpp->t0->enable_serr); | ||
287 | pr_debug(" _HPP: enable PERR =0x%x\n", hpp->t0->enable_perr); | ||
288 | 249 | ||
289 | free_and_return: | 250 | exit: |
290 | kfree(string.pointer); | 251 | kfree(buffer.pointer); |
291 | kfree(ret_buf.pointer); | ||
292 | return status; | 252 | return status; |
293 | } | 253 | } |
294 | 254 | ||