aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/shpchprm_acpi.c
diff options
context:
space:
mode:
authorrajesh.shah@intel.com <rajesh.shah@intel.com>2005-10-13 15:05:38 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-10-28 18:37:00 -0400
commit424600f9706b20a8a33ad928d3d0326bd88679bc (patch)
tree364509b512ff4f522b38329df582553a9c8fb6ff /drivers/pci/hotplug/shpchprm_acpi.c
parent7e88ed199689f333668b62348051202706b6a74a (diff)
[PATCH] shpchp: reduce dependence on ACPI
Reduce the SHPC hotplug driver's dependence on ACPI. We don't walk the acpi namespace anymore to build a list of bridges and devices. The remaining interaction with ACPI is to run the _OSHP method to transition control of hotplug hardware from system BIOS to the shpc hotplug driver, and to run the _HPP method to get hotplug device parameters like cache line size, latency timer and SERR/PERR enable from BIOS. Note that one of the side effects of this patch is that shpchp does not enable the hot-added device or its DMA bus mastering automatically now. It expects the device driver to do that. This may break some drivers and we will have to fix them as they are reported. Signed-off-by: Rajesh Shah <rajesh.shah@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/hotplug/shpchprm_acpi.c')
-rw-r--r--drivers/pci/hotplug/shpchprm_acpi.c794
1 files changed, 62 insertions, 732 deletions
diff --git a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/shpchprm_acpi.c
index 3d2f9c5269c7..3be518c7d47a 100644
--- a/drivers/pci/hotplug/shpchprm_acpi.c
+++ b/drivers/pci/hotplug/shpchprm_acpi.c
@@ -38,62 +38,11 @@
38#include <acpi/acpi_bus.h> 38#include <acpi/acpi_bus.h>
39#include <acpi/actypes.h> 39#include <acpi/actypes.h>
40#include "shpchp.h" 40#include "shpchp.h"
41#include "shpchprm.h"
42
43#define PCI_MAX_BUS 0x100
44#define ACPI_STA_DEVICE_PRESENT 0x01
45 41
46#define METHOD_NAME__SUN "_SUN" 42#define METHOD_NAME__SUN "_SUN"
47#define METHOD_NAME__HPP "_HPP" 43#define METHOD_NAME__HPP "_HPP"
48#define METHOD_NAME_OSHP "OSHP" 44#define METHOD_NAME_OSHP "OSHP"
49 45
50#define PHP_RES_BUS 0xA0
51#define PHP_RES_IO 0xA1
52#define PHP_RES_MEM 0xA2
53#define PHP_RES_PMEM 0xA3
54
55#define BRIDGE_TYPE_P2P 0x00
56#define BRIDGE_TYPE_HOST 0x01
57
58/* this should go to drivers/acpi/include/ */
59struct acpi__hpp {
60 u8 cache_line_size;
61 u8 latency_timer;
62 u8 enable_serr;
63 u8 enable_perr;
64};
65
66struct acpi_php_slot {
67 struct acpi_php_slot *next;
68 struct acpi_bridge *bridge;
69 acpi_handle handle;
70 int seg;
71 int bus;
72 int dev;
73 int fun;
74 u32 sun;
75 void *slot_ops; /* _STA, _EJx, etc */
76 struct slot *slot;
77}; /* per func */
78
79struct acpi_bridge {
80 struct acpi_bridge *parent;
81 struct acpi_bridge *next;
82 struct acpi_bridge *child;
83 acpi_handle handle;
84 int seg;
85 int pbus; /* pdev->bus->number */
86 int pdevice; /* PCI_SLOT(pdev->devfn) */
87 int pfunction; /* PCI_DEVFN(pdev->devfn) */
88 int bus; /* pdev->subordinate->number */
89 struct acpi__hpp *_hpp;
90 struct acpi_php_slot *slots;
91 int scanned;
92 int type;
93};
94
95static struct acpi_bridge *acpi_bridges_head;
96
97static u8 * acpi_path_name( acpi_handle handle) 46static u8 * acpi_path_name( acpi_handle handle)
98{ 47{
99 acpi_status status; 48 acpi_status status;
@@ -109,82 +58,43 @@ static u8 * acpi_path_name( acpi_handle handle)
109 return path_name; 58 return path_name;
110} 59}
111 60
112static void acpi_get__hpp ( struct acpi_bridge *ab); 61static acpi_status
113static void acpi_run_oshp ( struct acpi_bridge *ab); 62acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
114
115static int acpi_add_slot_to_php_slots(
116 struct acpi_bridge *ab,
117 int bus_num,
118 acpi_handle handle,
119 u32 adr,
120 u32 sun
121 )
122{
123 struct acpi_php_slot *aps;
124 static long samesun = -1;
125
126 aps = (struct acpi_php_slot *) kmalloc (sizeof(struct acpi_php_slot), GFP_KERNEL);
127 if (!aps) {
128 err ("acpi_shpchprm: alloc for aps fail\n");
129 return -1;
130 }
131 memset(aps, 0, sizeof(struct acpi_php_slot));
132
133 aps->handle = handle;
134 aps->bus = bus_num;
135 aps->dev = (adr >> 16) & 0xffff;
136 aps->fun = adr & 0xffff;
137 aps->sun = sun;
138
139 aps->next = ab->slots; /* cling to the bridge */
140 aps->bridge = ab;
141 ab->slots = aps;
142
143 ab->scanned += 1;
144 if (!ab->_hpp)
145 acpi_get__hpp(ab);
146
147 acpi_run_oshp(ab);
148
149 if (sun != samesun) {
150 info("acpi_shpchprm: Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n", aps->sun, ab->seg,
151 aps->bus, aps->dev, aps->fun);
152 samesun = sun;
153 }
154 return 0;
155}
156
157static void acpi_get__hpp ( struct acpi_bridge *ab)
158{ 63{
159 acpi_status status; 64 acpi_status status;
160 u8 nui[4]; 65 u8 nui[4];
161 struct acpi_buffer ret_buf = { 0, NULL}; 66 struct acpi_buffer ret_buf = { 0, NULL};
162 union acpi_object *ext_obj, *package; 67 union acpi_object *ext_obj, *package;
163 u8 *path_name = acpi_path_name(ab->handle); 68 u8 *path_name = acpi_path_name(handle);
164 int i, len = 0; 69 int i, len = 0;
165 70
166 /* get _hpp */ 71 /* get _hpp */
167 status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf); 72 status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
168 switch (status) { 73 switch (status) {
169 case AE_BUFFER_OVERFLOW: 74 case AE_BUFFER_OVERFLOW:
170 ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); 75 ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
171 if (!ret_buf.pointer) { 76 if (!ret_buf.pointer) {
172 err ("acpi_shpchprm:%s alloc for _HPP fail\n", path_name); 77 err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
173 return; 78 path_name);
79 return AE_NO_MEMORY;
174 } 80 }
175 status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf); 81 status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
82 NULL, &ret_buf);
176 if (ACPI_SUCCESS(status)) 83 if (ACPI_SUCCESS(status))
177 break; 84 break;
178 default: 85 default:
179 if (ACPI_FAILURE(status)) { 86 if (ACPI_FAILURE(status)) {
180 err("acpi_shpchprm:%s _HPP fail=0x%x\n", path_name, status); 87 dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
181 return; 88 path_name, status);
89 return status;
182 } 90 }
183 } 91 }
184 92
185 ext_obj = (union acpi_object *) ret_buf.pointer; 93 ext_obj = (union acpi_object *) ret_buf.pointer;
186 if (ext_obj->type != ACPI_TYPE_PACKAGE) { 94 if (ext_obj->type != ACPI_TYPE_PACKAGE) {
187 err ("acpi_shpchprm:%s _HPP obj not a package\n", path_name); 95 err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
96 path_name);
97 status = AE_ERROR;
188 goto free_and_return; 98 goto free_and_return;
189 } 99 }
190 100
@@ -197,553 +107,41 @@ static void acpi_get__hpp ( struct acpi_bridge *ab)
197 nui[i] = (u8)ext_obj->integer.value; 107 nui[i] = (u8)ext_obj->integer.value;
198 break; 108 break;
199 default: 109 default:
200 err ("acpi_shpchprm:%s _HPP obj type incorrect\n", path_name); 110 err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
111 path_name);
112 status = AE_ERROR;
201 goto free_and_return; 113 goto free_and_return;
202 } 114 }
203 } 115 }
204 116
205 ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL); 117 hpp->cache_line_size = nui[0];
206 if (!ab->_hpp) { 118 hpp->latency_timer = nui[1];
207 err ("acpi_shpchprm:%s alloc for _HPP failed\n", path_name); 119 hpp->enable_serr = nui[2];
208 goto free_and_return; 120 hpp->enable_perr = nui[3];
209 }
210 memset(ab->_hpp, 0, sizeof(struct acpi__hpp));
211
212 ab->_hpp->cache_line_size = nui[0];
213 ab->_hpp->latency_timer = nui[1];
214 ab->_hpp->enable_serr = nui[2];
215 ab->_hpp->enable_perr = nui[3];
216 121
217 dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size); 122 dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
218 dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer); 123 dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
219 dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr); 124 dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
220 dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr); 125 dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
221 126
222free_and_return: 127free_and_return:
223 kfree(ret_buf.pointer); 128 kfree(ret_buf.pointer);
129 return status;
224} 130}
225 131
226static void acpi_run_oshp ( struct acpi_bridge *ab) 132static void acpi_run_oshp(acpi_handle handle)
227{
228 acpi_status status;
229 u8 *path_name = acpi_path_name(ab->handle);
230
231 /* run OSHP */
232 status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, NULL);
233 if (ACPI_FAILURE(status)) {
234 err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status);
235 } else
236 dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status);
237 return;
238}
239
240/* find acpi_bridge downword from ab. */
241static struct acpi_bridge *
242find_acpi_bridge_by_bus(
243 struct acpi_bridge *ab,
244 int seg,
245 int bus /* pdev->subordinate->number */
246 )
247{
248 struct acpi_bridge *lab = NULL;
249
250 if (!ab)
251 return NULL;
252
253 if ((ab->bus == bus) && (ab->seg == seg))
254 return ab;
255
256 if (ab->child)
257 lab = find_acpi_bridge_by_bus(ab->child, seg, bus);
258
259 if (!lab)
260 if (ab->next)
261 lab = find_acpi_bridge_by_bus(ab->next, seg, bus);
262
263 return lab;
264}
265
266/*
267 * Build a device tree of ACPI PCI Bridges
268 */
269static void shpchprm_acpi_register_a_bridge (
270 struct acpi_bridge **head,
271 struct acpi_bridge *pab, /* parent bridge to which child bridge is added */
272 struct acpi_bridge *cab /* child bridge to add */
273 )
274{
275 struct acpi_bridge *lpab;
276 struct acpi_bridge *lcab;
277
278 lpab = find_acpi_bridge_by_bus(*head, pab->seg, pab->bus);
279 if (!lpab) {
280 if (!(pab->type & BRIDGE_TYPE_HOST))
281 warn("PCI parent bridge s:b(%x:%x) not in list.\n", pab->seg, pab->bus);
282 pab->next = *head;
283 *head = pab;
284 lpab = pab;
285 }
286
287 if ((cab->type & BRIDGE_TYPE_HOST) && (pab == cab))
288 return;
289
290 lcab = find_acpi_bridge_by_bus(*head, cab->seg, cab->bus);
291 if (lcab) {
292 if ((pab->bus != lcab->parent->bus) || (lcab->bus != cab->bus))
293 err("PCI child bridge s:b(%x:%x) in list with diff parent.\n", cab->seg, cab->bus);
294 return;
295 } else
296 lcab = cab;
297
298 lcab->parent = lpab;
299 lcab->next = lpab->child;
300 lpab->child = lcab;
301}
302
303static acpi_status shpchprm_acpi_build_php_slots_callback(
304 acpi_handle handle,
305 u32 Level,
306 void *context,
307 void **retval
308 )
309{ 133{
310 ulong bus_num;
311 ulong seg_num;
312 ulong sun, adr;
313 ulong padr = 0;
314 acpi_handle phandle = NULL;
315 struct acpi_bridge *pab = (struct acpi_bridge *)context;
316 struct acpi_bridge *lab;
317 acpi_status status; 134 acpi_status status;
318 u8 *path_name = acpi_path_name(handle); 135 u8 *path_name = acpi_path_name(handle);
319 136
320 /* get _SUN */ 137 /* run OSHP */
321 status = acpi_evaluate_integer(handle, METHOD_NAME__SUN, NULL, &sun); 138 status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
322 switch(status) {
323 case AE_NOT_FOUND:
324 return AE_OK;
325 default:
326 if (ACPI_FAILURE(status)) {
327 err("acpi_shpchprm:%s _SUN fail=0x%x\n", path_name, status);
328 return status;
329 }
330 }
331
332 /* get _ADR. _ADR must exist if _SUN exists */
333 status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
334 if (ACPI_FAILURE(status)) {
335 err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
336 return status;
337 }
338
339 dbg("acpi_shpchprm:%s sun=0x%08x adr=0x%08x\n", path_name, (u32)sun, (u32)adr);
340
341 status = acpi_get_parent(handle, &phandle);
342 if (ACPI_FAILURE(status)) { 139 if (ACPI_FAILURE(status)) {
343 err("acpi_shpchprm:%s get_parent fail=0x%x\n", path_name, status); 140 err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
344 return (status); 141 status);
345 }
346
347 bus_num = pab->bus;
348 seg_num = pab->seg;
349
350 if (pab->bus == bus_num) {
351 lab = pab;
352 } else { 142 } else {
353 dbg("WARN: pab is not parent\n"); 143 dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
354 lab = find_acpi_bridge_by_bus(pab, seg_num, bus_num);
355 if (!lab) {
356 dbg("acpi_shpchprm: alloc new P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
357 lab = (struct acpi_bridge *)kmalloc(sizeof(struct acpi_bridge), GFP_KERNEL);
358 if (!lab) {
359 err("acpi_shpchprm: alloc for ab fail\n");
360 return AE_NO_MEMORY;
361 }
362 memset(lab, 0, sizeof(struct acpi_bridge));
363
364 lab->handle = phandle;
365 lab->pbus = pab->bus;
366 lab->pdevice = (int)(padr >> 16) & 0xffff;
367 lab->pfunction = (int)(padr & 0xffff);
368 lab->bus = (int)bus_num;
369 lab->scanned = 0;
370 lab->type = BRIDGE_TYPE_P2P;
371
372 shpchprm_acpi_register_a_bridge (&acpi_bridges_head, pab, lab);
373 } else
374 dbg("acpi_shpchprm: found P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
375 }
376
377 acpi_add_slot_to_php_slots(lab, (int)bus_num, handle, (u32)adr, (u32)sun);
378 return (status);
379}
380
381static int shpchprm_acpi_build_php_slots(
382 struct acpi_bridge *ab,
383 u32 depth
384 )
385{
386 acpi_status status;
387 u8 *path_name = acpi_path_name(ab->handle);
388
389 /* Walk down this pci bridge to get _SUNs if any behind P2P */
390 status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
391 ab->handle,
392 depth,
393 shpchprm_acpi_build_php_slots_callback,
394 ab,
395 NULL );
396 if (ACPI_FAILURE(status)) {
397 dbg("acpi_shpchprm:%s walk for _SUN on pci bridge seg:bus(%x:%x) fail=0x%x\n", path_name, ab->seg, ab->bus, status);
398 return -1;
399 }
400
401 return 0;
402}
403
404static void build_a_bridge(
405 struct acpi_bridge *pab,
406 struct acpi_bridge *ab
407 )
408{
409 u8 *path_name = acpi_path_name(ab->handle);
410
411 shpchprm_acpi_register_a_bridge (&acpi_bridges_head, pab, ab);
412
413 switch (ab->type) {
414 case BRIDGE_TYPE_HOST:
415 dbg("acpi_shpchprm: Registered PCI HOST Bridge(%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
416 ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
417 break;
418 case BRIDGE_TYPE_P2P:
419 dbg("acpi_shpchprm: Registered PCI P2P Bridge(%02x-%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
420 ab->pbus, ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
421 break;
422 };
423
424 /* build any immediate PHP slots under this pci bridge */
425 shpchprm_acpi_build_php_slots(ab, 1);
426}
427
428static struct acpi_bridge * add_p2p_bridge(
429 acpi_handle handle,
430 struct acpi_bridge *pab, /* parent */
431 ulong adr
432 )
433{
434 struct acpi_bridge *ab;
435 struct pci_dev *pdev;
436 ulong devnum, funcnum;
437 u8 *path_name = acpi_path_name(handle);
438
439 ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
440 if (!ab) {
441 err("acpi_shpchprm: alloc for ab fail\n");
442 return NULL;
443 }
444 memset(ab, 0, sizeof(struct acpi_bridge));
445
446 devnum = (adr >> 16) & 0xffff;
447 funcnum = adr & 0xffff;
448
449 pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
450 if (!pdev || !pdev->subordinate) {
451 err("acpi_shpchprm:%s is not a P2P Bridge\n", path_name);
452 kfree(ab);
453 return NULL;
454 }
455
456 ab->handle = handle;
457 ab->seg = pab->seg;
458 ab->pbus = pab->bus; /* or pdev->bus->number */
459 ab->pdevice = devnum; /* or PCI_SLOT(pdev->devfn) */
460 ab->pfunction = funcnum; /* or PCI_FUNC(pdev->devfn) */
461 ab->bus = pdev->subordinate->number;
462 ab->scanned = 0;
463 ab->type = BRIDGE_TYPE_P2P;
464
465 dbg("acpi_shpchprm: P2P(%x-%x) on pci=b:d:f(%x:%x:%x) acpi=b:d:f(%x:%x:%x) [%s]\n",
466 pab->bus, ab->bus, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
467 pab->bus, (u32)devnum, (u32)funcnum, path_name);
468
469 build_a_bridge(pab, ab);
470
471 return ab;
472}
473
474static acpi_status scan_p2p_bridge(
475 acpi_handle handle,
476 u32 Level,
477 void *context,
478 void **retval
479 )
480{
481 struct acpi_bridge *pab = (struct acpi_bridge *)context;
482 struct acpi_bridge *ab;
483 acpi_status status;
484 ulong adr = 0;
485 u8 *path_name = acpi_path_name(handle);
486 ulong devnum, funcnum;
487 struct pci_dev *pdev;
488
489 /* get device, function */
490 status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
491 if (ACPI_FAILURE(status)) {
492 if (status != AE_NOT_FOUND)
493 err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
494 return AE_OK;
495 } 144 }
496
497 devnum = (adr >> 16) & 0xffff;
498 funcnum = adr & 0xffff;
499
500 pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
501 if (!pdev)
502 return AE_OK;
503 if (!pdev->subordinate)
504 return AE_OK;
505
506 ab = add_p2p_bridge(handle, pab, adr);
507 if (ab) {
508 status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
509 handle,
510 (u32)1,
511 scan_p2p_bridge,
512 ab,
513 NULL);
514 if (ACPI_FAILURE(status))
515 dbg("acpi_shpchprm:%s find_p2p fail=0x%x\n", path_name, status);
516 }
517
518 return AE_OK;
519}
520
521static struct acpi_bridge * add_host_bridge(
522 acpi_handle handle,
523 ulong segnum,
524 ulong busnum
525 )
526{
527 ulong adr = 0;
528 acpi_status status;
529 struct acpi_bridge *ab;
530 u8 *path_name = acpi_path_name(handle);
531
532 /* get device, function: host br adr is always 0000 though. */
533 status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
534 if (ACPI_FAILURE(status)) {
535 err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
536 return NULL;
537 }
538 dbg("acpi_shpchprm: ROOT PCI seg(0x%x)bus(0x%x)dev(0x%x)func(0x%x) [%s]\n", (u32)segnum, (u32)busnum,
539 (u32)(adr >> 16) & 0xffff, (u32)adr & 0xffff, path_name);
540
541 ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
542 if (!ab) {
543 err("acpi_shpchprm: alloc for ab fail\n");
544 return NULL;
545 }
546 memset(ab, 0, sizeof(struct acpi_bridge));
547
548 ab->handle = handle;
549 ab->seg = (int)segnum;
550 ab->bus = ab->pbus = (int)busnum;
551 ab->pdevice = (int)(adr >> 16) & 0xffff;
552 ab->pfunction = (int)(adr & 0xffff);
553 ab->scanned = 0;
554 ab->type = BRIDGE_TYPE_HOST;
555
556 build_a_bridge(ab, ab);
557
558 return ab;
559}
560
561static acpi_status acpi_scan_from_root_pci_callback (
562 acpi_handle handle,
563 u32 Level,
564 void *context,
565 void **retval
566 )
567{
568 ulong segnum = 0;
569 ulong busnum = 0;
570 acpi_status status;
571 struct acpi_bridge *ab;
572 u8 *path_name = acpi_path_name(handle);
573
574 /* get bus number of this pci root bridge */
575 status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &segnum);
576 if (ACPI_FAILURE(status)) {
577 if (status != AE_NOT_FOUND) {
578 err("acpi_shpchprm:%s evaluate _SEG fail=0x%x\n", path_name, status);
579 return status;
580 }
581 segnum = 0;
582 }
583
584 /* get bus number of this pci root bridge */
585 status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, &busnum);
586 if (ACPI_FAILURE(status)) {
587 err("acpi_shpchprm:%s evaluate _BBN fail=0x%x\n", path_name, status);
588 return (status);
589 }
590
591 ab = add_host_bridge(handle, segnum, busnum);
592 if (ab) {
593 status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
594 handle,
595 1,
596 scan_p2p_bridge,
597 ab,
598 NULL);
599 if (ACPI_FAILURE(status))
600 dbg("acpi_shpchprm:%s find_p2p fail=0x%x\n", path_name, status);
601 }
602
603 return AE_OK;
604}
605
606static int shpchprm_acpi_scan_pci (void)
607{
608 acpi_status status;
609
610 /*
611 * TBD: traverse LDM device tree with the help of
612 * unified ACPI augmented for php device population.
613 */
614 status = acpi_get_devices ( PCI_ROOT_HID_STRING,
615 acpi_scan_from_root_pci_callback,
616 NULL,
617 NULL );
618 if (ACPI_FAILURE(status)) {
619 err("acpi_shpchprm:get_device PCI ROOT HID fail=0x%x\n", status);
620 return -1;
621 }
622
623 return 0;
624}
625
626int shpchprm_init(enum php_ctlr_type ctlr_type)
627{
628 int rc;
629
630 if (ctlr_type != PCI)
631 return -ENODEV;
632
633 dbg("shpchprm ACPI init <enter>\n");
634 acpi_bridges_head = NULL;
635
636 /* construct PCI bus:device tree of acpi_handles */
637 rc = shpchprm_acpi_scan_pci();
638 if (rc)
639 return rc;
640
641 dbg("shpchprm ACPI init %s\n", (rc)?"fail":"success");
642 return rc;
643}
644
645static void free_a_slot(struct acpi_php_slot *aps)
646{
647 dbg(" free a php func of slot(0x%02x) on PCI b:d:f=0x%02x:%02x:%02x\n", aps->sun, aps->bus, aps->dev, aps->fun);
648
649 kfree(aps);
650}
651
652static void free_a_bridge( struct acpi_bridge *ab)
653{
654 struct acpi_php_slot *aps, *next;
655
656 switch (ab->type) {
657 case BRIDGE_TYPE_HOST:
658 dbg("Free ACPI PCI HOST Bridge(%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
659 ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
660 break;
661 case BRIDGE_TYPE_P2P:
662 dbg("Free ACPI PCI P2P Bridge(%x-%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
663 ab->pbus, ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
664 break;
665 };
666
667 /* free slots first */
668 for (aps = ab->slots; aps; aps = next) {
669 next = aps->next;
670 free_a_slot(aps);
671 }
672
673 kfree(ab);
674}
675
676static void shpchprm_free_bridges ( struct acpi_bridge *ab)
677{
678 if (!ab)
679 return;
680
681 if (ab->child)
682 shpchprm_free_bridges (ab->child);
683
684 if (ab->next)
685 shpchprm_free_bridges (ab->next);
686
687 free_a_bridge(ab);
688}
689
690void shpchprm_cleanup(void)
691{
692 shpchprm_free_bridges (acpi_bridges_head);
693}
694
695static int get_number_of_slots (
696 struct acpi_bridge *ab,
697 int selfonly
698 )
699{
700 struct acpi_php_slot *aps;
701 int prev_slot = -1;
702 int slot_num = 0;
703
704 for ( aps = ab->slots; aps; aps = aps->next)
705 if (aps->dev != prev_slot) {
706 prev_slot = aps->dev;
707 slot_num++;
708 }
709
710 if (ab->child)
711 slot_num += get_number_of_slots (ab->child, 0);
712
713 if (selfonly)
714 return slot_num;
715
716 if (ab->next)
717 slot_num += get_number_of_slots (ab->next, 0);
718
719 return slot_num;
720}
721
722static struct acpi_php_slot * get_acpi_slot (
723 struct acpi_bridge *ab,
724 u32 sun
725 )
726{
727 struct acpi_php_slot *aps = NULL;
728
729 for ( aps = ab->slots; aps; aps = aps->next)
730 if (aps->sun == sun)
731 return aps;
732
733 if (!aps && ab->child) {
734 aps = (struct acpi_php_slot *)get_acpi_slot (ab->child, sun);
735 if (aps)
736 return aps;
737 }
738
739 if (!aps && ab->next) {
740 aps = (struct acpi_php_slot *)get_acpi_slot (ab->next, sun);
741 if (aps)
742 return aps;
743 }
744
745 return aps;
746
747} 145}
748 146
749int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) 147int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
@@ -755,108 +153,40 @@ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busn
755 return 0; 153 return 0;
756} 154}
757 155
758int shpchprm_set_hpp( 156void get_hp_hw_control_from_firmware(struct pci_dev *dev)
759 struct controller *ctrl,
760 struct pci_func *func,
761 u8 card_type
762 )
763{ 157{
764 struct acpi_bridge *ab; 158 /*
765 struct pci_bus lpci_bus, *pci_bus; 159 * OSHP is an optional ACPI firmware control method. If present,
766 int rc = 0; 160 * we need to run it to inform BIOS that we will control SHPC
767 unsigned int devfn; 161 * hardware from now on.
768 u8 cls= 0x08; /* default cache line size */ 162 */
769 u8 lt = 0x40; /* default latency timer */ 163 acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev));
770 u8 ep = 0; 164 if (!handle)
771 u8 es = 0; 165 return;
772 166 acpi_run_oshp(handle);
773 memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
774 pci_bus = &lpci_bus;
775 pci_bus->number = func->bus;
776 devfn = PCI_DEVFN(func->device, func->function);
777
778 ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus);
779
780 if (ab) {
781 if (ab->_hpp) {
782 lt = (u8)ab->_hpp->latency_timer;
783 cls = (u8)ab->_hpp->cache_line_size;
784 ep = (u8)ab->_hpp->enable_perr;
785 es = (u8)ab->_hpp->enable_serr;
786 } else
787 dbg("_hpp: no _hpp for B/D/F=%#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
788 } else
789 dbg("_hpp: no acpi bridge for B/D/F = %#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
790
791
792 if (card_type == PCI_HEADER_TYPE_BRIDGE) {
793 /* set subordinate Latency Timer */
794 rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, lt);
795 }
796
797 /* set base Latency Timer */
798 rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, lt);
799 dbg(" set latency timer =0x%02x: %x\n", lt, rc);
800
801 rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, cls);
802 dbg(" set cache_line_size=0x%02x: %x\n", cls, rc);
803
804 return rc;
805} 167}
806 168
807void shpchprm_enable_card( 169void get_hp_params_from_firmware(struct pci_dev *dev,
808 struct controller *ctrl, 170 struct hotplug_params *hpp)
809 struct pci_func *func,
810 u8 card_type)
811{ 171{
812 u16 command, cmd, bcommand, bcmd; 172 acpi_status status = AE_NOT_FOUND;
813 struct pci_bus lpci_bus, *pci_bus; 173 struct pci_dev *pdev = dev;
814 struct acpi_bridge *ab;
815 unsigned int devfn;
816 int rc;
817
818 memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
819 pci_bus = &lpci_bus;
820 pci_bus->number = func->bus;
821 devfn = PCI_DEVFN(func->device, func->function);
822
823 rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
824
825 if (card_type == PCI_HEADER_TYPE_BRIDGE) {
826 rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
827 }
828
829 cmd = command = command | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
830 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
831 bcmd = bcommand = bcommand | PCI_BRIDGE_CTL_NO_ISA;
832 174
833 ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus); 175 /*
834 if (ab) { 176 * _HPP settings apply to all child buses, until another _HPP is
835 if (ab->_hpp) { 177 * encountered. If we don't find an _HPP for the input pci dev,
836 if (ab->_hpp->enable_perr) { 178 * look for it in the parent device scope since that would apply to
837 command |= PCI_COMMAND_PARITY; 179 * this pci dev. If we don't find any _HPP, use hardcoded defaults
838 bcommand |= PCI_BRIDGE_CTL_PARITY; 180 */
839 } else { 181 while (pdev && (ACPI_FAILURE(status))) {
840 command &= ~PCI_COMMAND_PARITY; 182 acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
841 bcommand &= ~PCI_BRIDGE_CTL_PARITY; 183 if (!handle)
842 } 184 break;
843 if (ab->_hpp->enable_serr) { 185 status = acpi_run_hpp(handle, hpp);
844 command |= PCI_COMMAND_SERR; 186 if (!(pdev->bus->parent))
845 bcommand |= PCI_BRIDGE_CTL_SERR; 187 break;
846 } else { 188 /* Check if a parent object supports _HPP */
847 command &= ~PCI_COMMAND_SERR; 189 pdev = pdev->bus->parent->self;
848 bcommand &= ~PCI_BRIDGE_CTL_SERR;
849 }
850 } else
851 dbg("no _hpp for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
852 } else
853 dbg("no acpi bridge for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
854
855 if (command != cmd) {
856 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
857 }
858 if ((card_type == PCI_HEADER_TYPE_BRIDGE) && (bcommand != bcmd)) {
859 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
860 } 190 }
861} 191}
862 192