2 * Common ACPI functions for hot plug platforms
4 * Copyright (C) 2006 Intel Corporation
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
16 * NON INFRINGEMENT. See the GNU General Public License for more
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Send feedback to <kristen.c.accardi@intel.com>
27 #include <linux/module.h>
28 #include <linux/moduleparam.h>
29 #include <linux/kernel.h>
30 #include <linux/types.h>
31 #include <linux/pci.h>
32 #include <linux/pci_hotplug.h>
33 #include <acpi/acpi.h>
34 #include <acpi/acpi_bus.h>
35 #include <acpi/actypes.h>
37 #define MY_NAME "acpi_pcihp"
39 #define dbg(fmt, arg...) do { if (debug_acpi) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __func__ , ## arg); } while (0)
40 #define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
41 #define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
42 #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
44 #define METHOD_NAME__SUN "_SUN"
45 #define METHOD_NAME__HPP "_HPP"
46 #define METHOD_NAME_OSHP "OSHP"
48 static int debug_acpi
;
51 decode_type0_hpx_record(union acpi_object
*record
, struct hotplug_params
*hpx
)
54 union acpi_object
*fields
= record
->package
.elements
;
55 u32 revision
= fields
[1].integer
.value
;
59 if (record
->package
.count
!= 6)
61 for (i
= 2; i
< 6; i
++)
62 if (fields
[i
].type
!= ACPI_TYPE_INTEGER
)
64 hpx
->t0
= &hpx
->type0_data
;
65 hpx
->t0
->revision
= revision
;
66 hpx
->t0
->cache_line_size
= fields
[2].integer
.value
;
67 hpx
->t0
->latency_timer
= fields
[3].integer
.value
;
68 hpx
->t0
->enable_serr
= fields
[4].integer
.value
;
69 hpx
->t0
->enable_perr
= fields
[5].integer
.value
;
73 "%s: Type 0 Revision %d record not supported\n",
81 decode_type1_hpx_record(union acpi_object
*record
, struct hotplug_params
*hpx
)
84 union acpi_object
*fields
= record
->package
.elements
;
85 u32 revision
= fields
[1].integer
.value
;
89 if (record
->package
.count
!= 5)
91 for (i
= 2; i
< 5; i
++)
92 if (fields
[i
].type
!= ACPI_TYPE_INTEGER
)
94 hpx
->t1
= &hpx
->type1_data
;
95 hpx
->t1
->revision
= revision
;
96 hpx
->t1
->max_mem_read
= fields
[2].integer
.value
;
97 hpx
->t1
->avg_max_split
= fields
[3].integer
.value
;
98 hpx
->t1
->tot_max_split
= fields
[4].integer
.value
;
102 "%s: Type 1 Revision %d record not supported\n",
110 decode_type2_hpx_record(union acpi_object
*record
, struct hotplug_params
*hpx
)
113 union acpi_object
*fields
= record
->package
.elements
;
114 u32 revision
= fields
[1].integer
.value
;
118 if (record
->package
.count
!= 18)
120 for (i
= 2; i
< 18; i
++)
121 if (fields
[i
].type
!= ACPI_TYPE_INTEGER
)
123 hpx
->t2
= &hpx
->type2_data
;
124 hpx
->t2
->revision
= revision
;
125 hpx
->t2
->unc_err_mask_and
= fields
[2].integer
.value
;
126 hpx
->t2
->unc_err_mask_or
= fields
[3].integer
.value
;
127 hpx
->t2
->unc_err_sever_and
= fields
[4].integer
.value
;
128 hpx
->t2
->unc_err_sever_or
= fields
[5].integer
.value
;
129 hpx
->t2
->cor_err_mask_and
= fields
[6].integer
.value
;
130 hpx
->t2
->cor_err_mask_or
= fields
[7].integer
.value
;
131 hpx
->t2
->adv_err_cap_and
= fields
[8].integer
.value
;
132 hpx
->t2
->adv_err_cap_or
= fields
[9].integer
.value
;
133 hpx
->t2
->pci_exp_devctl_and
= fields
[10].integer
.value
;
134 hpx
->t2
->pci_exp_devctl_or
= fields
[11].integer
.value
;
135 hpx
->t2
->pci_exp_lnkctl_and
= fields
[12].integer
.value
;
136 hpx
->t2
->pci_exp_lnkctl_or
= fields
[13].integer
.value
;
137 hpx
->t2
->sec_unc_err_sever_and
= fields
[14].integer
.value
;
138 hpx
->t2
->sec_unc_err_sever_or
= fields
[15].integer
.value
;
139 hpx
->t2
->sec_unc_err_mask_and
= fields
[16].integer
.value
;
140 hpx
->t2
->sec_unc_err_mask_or
= fields
[17].integer
.value
;
144 "%s: Type 2 Revision %d record not supported\n",
152 acpi_run_hpx(acpi_handle handle
, struct hotplug_params
*hpx
)
155 struct acpi_buffer buffer
= {ACPI_ALLOCATE_BUFFER
, NULL
};
156 union acpi_object
*package
, *record
, *fields
;
160 /* Clear the return buffer with zeros */
161 memset(hpx
, 0, sizeof(struct hotplug_params
));
163 status
= acpi_evaluate_object(handle
, "_HPX", NULL
, &buffer
);
164 if (ACPI_FAILURE(status
))
167 package
= (union acpi_object
*)buffer
.pointer
;
168 if (package
->type
!= ACPI_TYPE_PACKAGE
) {
173 for (i
= 0; i
< package
->package
.count
; i
++) {
174 record
= &package
->package
.elements
[i
];
175 if (record
->type
!= ACPI_TYPE_PACKAGE
) {
180 fields
= record
->package
.elements
;
181 if (fields
[0].type
!= ACPI_TYPE_INTEGER
||
182 fields
[1].type
!= ACPI_TYPE_INTEGER
) {
187 type
= fields
[0].integer
.value
;
190 status
= decode_type0_hpx_record(record
, hpx
);
191 if (ACPI_FAILURE(status
))
195 status
= decode_type1_hpx_record(record
, hpx
);
196 if (ACPI_FAILURE(status
))
200 status
= decode_type2_hpx_record(record
, hpx
);
201 if (ACPI_FAILURE(status
))
205 printk(KERN_ERR
"%s: Type %d record not supported\n",
212 kfree(buffer
.pointer
);
217 acpi_run_hpp(acpi_handle handle
, struct hotplug_params
*hpp
)
221 struct acpi_buffer ret_buf
= { 0, NULL
};
222 struct acpi_buffer string
= { ACPI_ALLOCATE_BUFFER
, NULL
};
223 union acpi_object
*ext_obj
, *package
;
226 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &string
);
228 /* Clear the return buffer with zeros */
229 memset(hpp
, 0, sizeof(struct hotplug_params
));
232 status
= acpi_evaluate_object(handle
, METHOD_NAME__HPP
, NULL
, &ret_buf
);
234 case AE_BUFFER_OVERFLOW
:
235 ret_buf
.pointer
= kmalloc (ret_buf
.length
, GFP_KERNEL
);
236 if (!ret_buf
.pointer
) {
237 printk(KERN_ERR
"%s:%s alloc for _HPP fail\n",
238 __func__
, (char *)string
.pointer
);
239 kfree(string
.pointer
);
242 status
= acpi_evaluate_object(handle
, METHOD_NAME__HPP
,
244 if (ACPI_SUCCESS(status
))
247 if (ACPI_FAILURE(status
)) {
248 pr_debug("%s:%s _HPP fail=0x%x\n", __func__
,
249 (char *)string
.pointer
, status
);
250 kfree(string
.pointer
);
255 ext_obj
= (union acpi_object
*) ret_buf
.pointer
;
256 if (ext_obj
->type
!= ACPI_TYPE_PACKAGE
) {
257 printk(KERN_ERR
"%s:%s _HPP obj not a package\n", __func__
,
258 (char *)string
.pointer
);
260 goto free_and_return
;
263 len
= ext_obj
->package
.count
;
264 package
= (union acpi_object
*) ret_buf
.pointer
;
265 for ( i
= 0; (i
< len
) || (i
< 4); i
++) {
266 ext_obj
= (union acpi_object
*) &package
->package
.elements
[i
];
267 switch (ext_obj
->type
) {
268 case ACPI_TYPE_INTEGER
:
269 nui
[i
] = (u8
)ext_obj
->integer
.value
;
272 printk(KERN_ERR
"%s:%s _HPP obj type incorrect\n",
273 __func__
, (char *)string
.pointer
);
275 goto free_and_return
;
279 hpp
->t0
= &hpp
->type0_data
;
280 hpp
->t0
->cache_line_size
= nui
[0];
281 hpp
->t0
->latency_timer
= nui
[1];
282 hpp
->t0
->enable_serr
= nui
[2];
283 hpp
->t0
->enable_perr
= nui
[3];
285 pr_debug(" _HPP: cache_line_size=0x%x\n", hpp
->t0
->cache_line_size
);
286 pr_debug(" _HPP: latency timer =0x%x\n", hpp
->t0
->latency_timer
);
287 pr_debug(" _HPP: enable SERR =0x%x\n", hpp
->t0
->enable_serr
);
288 pr_debug(" _HPP: enable PERR =0x%x\n", hpp
->t0
->enable_perr
);
291 kfree(string
.pointer
);
292 kfree(ret_buf
.pointer
);
298 /* acpi_run_oshp - get control of hotplug from the firmware
300 * @handle - the handle of the hotplug controller.
302 acpi_status
acpi_run_oshp(acpi_handle handle
)
305 struct acpi_buffer string
= { ACPI_ALLOCATE_BUFFER
, NULL
};
307 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &string
);
310 status
= acpi_evaluate_object(handle
, METHOD_NAME_OSHP
, NULL
, NULL
);
311 if (ACPI_FAILURE(status
))
312 if (status
!= AE_NOT_FOUND
)
313 printk(KERN_ERR
"%s:%s OSHP fails=0x%x\n",
314 __func__
, (char *)string
.pointer
, status
);
316 dbg("%s:%s OSHP not found\n",
317 __func__
, (char *)string
.pointer
);
319 pr_debug("%s:%s OSHP passes\n", __func__
,
320 (char *)string
.pointer
);
322 kfree(string
.pointer
);
325 EXPORT_SYMBOL_GPL(acpi_run_oshp
);
329 /* acpi_get_hp_params_from_firmware
331 * @bus - the pci_bus of the bus on which the device is newly added
332 * @hpp - allocated by the caller
334 acpi_status
acpi_get_hp_params_from_firmware(struct pci_bus
*bus
,
335 struct hotplug_params
*hpp
)
337 acpi_status status
= AE_NOT_FOUND
;
338 acpi_handle handle
, phandle
;
339 struct pci_bus
*pbus
= bus
;
340 struct pci_dev
*pdev
;
345 handle
= acpi_get_pci_rootbridge_handle(
346 pci_domain_nr(pbus
), pbus
->number
);
349 handle
= DEVICE_ACPI_HANDLE(&(pdev
->dev
));
354 * _HPP settings apply to all child buses, until another _HPP is
355 * encountered. If we don't find an _HPP for the input pci dev,
356 * look for it in the parent device scope since that would apply to
357 * this pci dev. If we don't find any _HPP, use hardcoded defaults
360 status
= acpi_run_hpx(handle
, hpp
);
361 if (ACPI_SUCCESS(status
))
363 status
= acpi_run_hpp(handle
, hpp
);
364 if (ACPI_SUCCESS(status
))
366 if (acpi_root_bridge(handle
))
368 status
= acpi_get_parent(handle
, &phandle
);
369 if (ACPI_FAILURE(status
))
375 EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware
);
378 /* acpi_root_bridge - check to see if this acpi object is a root bridge
380 * @handle - the acpi object in question.
382 int acpi_root_bridge(acpi_handle handle
)
385 struct acpi_device_info
*info
;
386 struct acpi_buffer buffer
= {ACPI_ALLOCATE_BUFFER
, NULL
};
389 status
= acpi_get_object_info(handle
, &buffer
);
390 if (ACPI_SUCCESS(status
)) {
391 info
= buffer
.pointer
;
392 if ((info
->valid
& ACPI_VALID_HID
) &&
393 !strcmp(PCI_ROOT_HID_STRING
,
394 info
->hardware_id
.value
)) {
395 kfree(buffer
.pointer
);
398 if (info
->valid
& ACPI_VALID_CID
) {
399 for (i
=0; i
< info
->compatibility_id
.count
; i
++) {
400 if (!strcmp(PCI_ROOT_HID_STRING
,
401 info
->compatibility_id
.id
[i
].value
)) {
402 kfree(buffer
.pointer
);
407 kfree(buffer
.pointer
);
411 EXPORT_SYMBOL_GPL(acpi_root_bridge
);
413 module_param(debug_acpi
, bool, 0644);
414 MODULE_PARM_DESC(debug_acpi
, "Debugging mode for ACPI enabled or not");