aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrajesh.shah@intel.com <rajesh.shah@intel.com>2005-10-31 19:20:07 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2005-11-10 19:09:14 -0500
commita8a2be949267cb0d1d933a92d9fb43eda4f4fe88 (patch)
tree08c0fd1ec2ee5236d201005021021491194f4153
parent71b720c0f96145f5868c87591c286b290bc1a6af (diff)
[PATCH] pciehp: reduce dependence on ACPI
Reduce the PCI Express hotplug driver's dependence on ACPI. We don't walk the acpi namespace anymore to build a list of bridges and devices. We go to ACPI only to run the _OSC or _OSHP methods to transition control of hotplug hardware from system BIOS to the 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 pciehp does not automatically enable the hot-added device or its DMA bus mastering capability 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>
-rw-r--r--drivers/pci/hotplug/pciehp.h11
-rw-r--r--drivers/pci/hotplug/pciehp_core.c20
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c1
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c4
-rw-r--r--drivers/pci/hotplug/pciehprm.h52
-rw-r--r--drivers/pci/hotplug/pciehprm_acpi.c838
-rw-r--r--drivers/pci/hotplug/pciehprm_nonacpi.c107
-rw-r--r--drivers/pci/hotplug/pciehprm_nonacpi.h56
8 files changed, 96 insertions, 993 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index e9480ddd5abf..e9c09566f851 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -49,6 +49,13 @@ extern int pciehp_debug;
49#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) 49#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
50#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) 50#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
51 51
52struct hotplug_params {
53 u8 cache_line_size;
54 u8 latency_timer;
55 u8 enable_serr;
56 u8 enable_perr;
57};
58
52struct pci_func { 59struct pci_func {
53 struct pci_func *next; 60 struct pci_func *next;
54 u8 bus; 61 u8 bus;
@@ -199,6 +206,10 @@ extern int pciehp_save_config (struct controller *ctrl, int busnumber, int num
199extern int pciehp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot); 206extern int pciehp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot);
200extern int pciehp_configure_device (struct slot *ctrl); 207extern int pciehp_configure_device (struct slot *ctrl);
201extern int pciehp_unconfigure_device (struct pci_func* func); 208extern int pciehp_unconfigure_device (struct pci_func* func);
209extern int get_hp_hw_control_from_firmware(struct pci_dev *dev);
210extern void get_hp_params_from_firmware(struct pci_dev *dev,
211 struct hotplug_params *hpp);
212
202 213
203 214
204/* Global variables */ 215/* Global variables */
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 190664e5adf4..e20cf8e42bd9 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -39,7 +39,6 @@
39#include <linux/init.h> 39#include <linux/init.h>
40#include <asm/uaccess.h> 40#include <asm/uaccess.h>
41#include "pciehp.h" 41#include "pciehp.h"
42#include "pciehprm.h"
43#include <linux/interrupt.h> 42#include <linux/interrupt.h>
44 43
45/* Global variables */ 44/* Global variables */
@@ -381,6 +380,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
381 dbg("%s: DRV_thread pid = %d\n", __FUNCTION__, current->pid); 380 dbg("%s: DRV_thread pid = %d\n", __FUNCTION__, current->pid);
382 381
383 pdev = dev->port; 382 pdev = dev->port;
383 ctrl->pci_dev = pdev;
384 384
385 rc = pcie_init(ctrl, dev, 385 rc = pcie_init(ctrl, dev,
386 (php_intr_callback_t) pciehp_handle_attention_button, 386 (php_intr_callback_t) pciehp_handle_attention_button,
@@ -392,8 +392,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
392 goto err_out_free_ctrl; 392 goto err_out_free_ctrl;
393 } 393 }
394 394
395 ctrl->pci_dev = pdev;
396
397 pci_set_drvdata(pdev, ctrl); 395 pci_set_drvdata(pdev, ctrl);
398 396
399 ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL); 397 ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL);
@@ -609,18 +607,14 @@ static int __init pcied_init(void)
609 if (retval) 607 if (retval)
610 goto error_hpc_init; 608 goto error_hpc_init;
611 609
612 retval = pciehprm_init(PCI); 610 retval = pcie_port_service_register(&hpdriver_portdrv);
613 if (!retval) { 611 dbg("pcie_port_service_register = %d\n", retval);
614 retval = pcie_port_service_register(&hpdriver_portdrv); 612 info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
615 dbg("pcie_port_service_register = %d\n", retval); 613 if (retval)
616 info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); 614 dbg("%s: Failure to register service\n", __FUNCTION__);
617 if (retval)
618 dbg("%s: Failure to register service\n", __FUNCTION__);
619 }
620 615
621error_hpc_init: 616error_hpc_init:
622 if (retval) { 617 if (retval) {
623 pciehprm_cleanup();
624 pciehp_event_stop_thread(); 618 pciehp_event_stop_thread();
625 }; 619 };
626 620
@@ -632,8 +626,6 @@ static void __exit pcied_cleanup(void)
632 dbg("unload_pciehpd()\n"); 626 dbg("unload_pciehpd()\n");
633 unload_pciehpd(); 627 unload_pciehpd();
634 628
635 pciehprm_cleanup();
636
637 dbg("pcie_port_service_unregister\n"); 629 dbg("pcie_port_service_unregister\n");
638 pcie_port_service_unregister(&hpdriver_portdrv); 630 pcie_port_service_unregister(&hpdriver_portdrv);
639 631
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 412783e0ef40..d07d4194bc29 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -40,7 +40,6 @@
40#include <linux/pci.h> 40#include <linux/pci.h>
41#include "../pci.h" 41#include "../pci.h"
42#include "pciehp.h" 42#include "pciehp.h"
43#include "pciehprm.h"
44 43
45static void interrupt_event_handler(struct controller *ctrl); 44static void interrupt_event_handler(struct controller *ctrl);
46 45
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 7a0e27f0e063..ef79ca1f38da 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -1470,6 +1470,10 @@ int pcie_init(struct controller * ctrl,
1470 } 1470 }
1471 dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word); 1471 dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word);
1472 1472
1473 rc = get_hp_hw_control_from_firmware(ctrl->pci_dev);
1474 if (rc)
1475 goto abort_free_ctlr;
1476
1473 /* Add this HPC instance into the HPC list */ 1477 /* Add this HPC instance into the HPC list */
1474 spin_lock(&list_lock); 1478 spin_lock(&list_lock);
1475 if (php_ctlr_list_head == 0) { 1479 if (php_ctlr_list_head == 0) {
diff --git a/drivers/pci/hotplug/pciehprm.h b/drivers/pci/hotplug/pciehprm.h
deleted file mode 100644
index 05f20fbc5f50..000000000000
--- a/drivers/pci/hotplug/pciehprm.h
+++ /dev/null
@@ -1,52 +0,0 @@
1/*
2 * PCIEHPRM : PCIEHP Resource Manager for ACPI/non-ACPI platform
3 *
4 * Copyright (C) 1995,2001 Compaq Computer Corporation
5 * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
6 * Copyright (C) 2001 IBM Corp.
7 * Copyright (C) 2003-2004 Intel Corporation
8 *
9 * All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or (at
14 * your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
19 * NON INFRINGEMENT. See the GNU General Public License for more
20 * details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *
26 * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
27 *
28 */
29
30#ifndef _PCIEHPRM_H_
31#define _PCIEHPRM_H_
32
33#ifdef CONFIG_HOTPLUG_PCI_PCIE_PHPRM_NONACPI
34#include "pciehprm_nonacpi.h"
35#endif
36
37int pciehprm_init(enum php_ctlr_type ct);
38void pciehprm_cleanup(void);
39int pciehprm_print_pirt(void);
40int pciehprm_find_available_resources(struct controller *ctrl);
41int pciehprm_set_hpp(struct controller *ctrl, struct pci_func *func, u8 card_type);
42void pciehprm_enable_card(struct controller *ctrl, struct pci_func *func, u8 card_type);
43
44#ifdef DEBUG
45#define RES_CHECK(this, bits) \
46 { if (((this) & (bits - 1))) \
47 printk("%s:%d ERR: potential res loss!\n", __FUNCTION__, __LINE__); }
48#else
49#define RES_CHECK(this, bits)
50#endif
51
52#endif /* _PCIEHPRM_H_ */
diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c
index 078550ba2708..c823cfa42eec 100644
--- a/drivers/pci/hotplug/pciehprm_acpi.c
+++ b/drivers/pci/hotplug/pciehprm_acpi.c
@@ -39,70 +39,11 @@
39#include <acpi/acpi_bus.h> 39#include <acpi/acpi_bus.h>
40#include <acpi/actypes.h> 40#include <acpi/actypes.h>
41#include "pciehp.h" 41#include "pciehp.h"
42#include "pciehprm.h"
43
44#define PCI_MAX_BUS 0x100
45#define ACPI_STA_DEVICE_PRESENT 0x01
46 42
47#define METHOD_NAME__SUN "_SUN" 43#define METHOD_NAME__SUN "_SUN"
48#define METHOD_NAME__HPP "_HPP" 44#define METHOD_NAME__HPP "_HPP"
49#define METHOD_NAME_OSHP "OSHP" 45#define METHOD_NAME_OSHP "OSHP"
50 46
51/* Status code for running acpi method to gain native control */
52#define NC_NOT_RUN 0
53#define OSC_NOT_EXIST 1
54#define OSC_RUN_FAILED 2
55#define OSHP_NOT_EXIST 3
56#define OSHP_RUN_FAILED 4
57#define NC_RUN_SUCCESS 5
58
59#define PHP_RES_BUS 0xA0
60#define PHP_RES_IO 0xA1
61#define PHP_RES_MEM 0xA2
62#define PHP_RES_PMEM 0xA3
63
64#define BRIDGE_TYPE_P2P 0x00
65#define BRIDGE_TYPE_HOST 0x01
66
67/* this should go to drivers/acpi/include/ */
68struct acpi__hpp {
69 u8 cache_line_size;
70 u8 latency_timer;
71 u8 enable_serr;
72 u8 enable_perr;
73};
74
75struct acpi_php_slot {
76 struct acpi_php_slot *next;
77 struct acpi_bridge *bridge;
78 acpi_handle handle;
79 int seg;
80 int bus;
81 int dev;
82 int fun;
83 u32 sun;
84 void *slot_ops; /* _STA, _EJx, etc */
85 struct slot *slot;
86}; /* per func */
87
88struct acpi_bridge {
89 struct acpi_bridge *parent;
90 struct acpi_bridge *next;
91 struct acpi_bridge *child;
92 acpi_handle handle;
93 int seg;
94 int pbus; /* pdev->bus->number */
95 int pdevice; /* PCI_SLOT(pdev->devfn) */
96 int pfunction; /* PCI_DEVFN(pdev->devfn) */
97 int bus; /* pdev->subordinate->number */
98 struct acpi__hpp *_hpp;
99 struct acpi_php_slot *slots;
100 int scanned;
101 int type;
102};
103
104static struct acpi_bridge *acpi_bridges_head;
105
106static u8 * acpi_path_name( acpi_handle handle) 47static u8 * acpi_path_name( acpi_handle handle)
107{ 48{
108 acpi_status status; 49 acpi_status status;
@@ -118,85 +59,43 @@ static u8 * acpi_path_name( acpi_handle handle)
118 return path_name; 59 return path_name;
119} 60}
120 61
121static void acpi_get__hpp ( struct acpi_bridge *ab); 62static acpi_status
122static int acpi_run_oshp ( struct acpi_bridge *ab); 63acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
123static int osc_run_status = NC_NOT_RUN;
124static int oshp_run_status = NC_NOT_RUN;
125
126static int acpi_add_slot_to_php_slots(
127 struct acpi_bridge *ab,
128 int bus_num,
129 acpi_handle handle,
130 u32 adr,
131 u32 sun
132 )
133{
134 struct acpi_php_slot *aps;
135 static long samesun = -1;
136
137 aps = (struct acpi_php_slot *) kmalloc (sizeof(struct acpi_php_slot), GFP_KERNEL);
138 if (!aps) {
139 err ("acpi_pciehprm: alloc for aps fail\n");
140 return -1;
141 }
142 memset(aps, 0, sizeof(struct acpi_php_slot));
143
144 aps->handle = handle;
145 aps->bus = bus_num;
146 aps->dev = (adr >> 16) & 0xffff;
147 aps->fun = adr & 0xffff;
148 aps->sun = sun;
149
150 aps->next = ab->slots; /* cling to the bridge */
151 aps->bridge = ab;
152 ab->slots = aps;
153
154 ab->scanned += 1;
155 if (!ab->_hpp)
156 acpi_get__hpp(ab);
157
158 if (osc_run_status == OSC_NOT_EXIST)
159 oshp_run_status = acpi_run_oshp(ab);
160
161 if (sun != samesun) {
162 info("acpi_pciehprm: Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n",
163 aps->sun, ab->seg, aps->bus, aps->dev, aps->fun);
164 samesun = sun;
165 }
166 return 0;
167}
168
169static void acpi_get__hpp ( struct acpi_bridge *ab)
170{ 64{
171 acpi_status status; 65 acpi_status status;
172 u8 nui[4]; 66 u8 nui[4];
173 struct acpi_buffer ret_buf = { 0, NULL}; 67 struct acpi_buffer ret_buf = { 0, NULL};
174 union acpi_object *ext_obj, *package; 68 union acpi_object *ext_obj, *package;
175 u8 *path_name = acpi_path_name(ab->handle); 69 u8 *path_name = acpi_path_name(handle);
176 int i, len = 0; 70 int i, len = 0;
177 71
178 /* get _hpp */ 72 /* get _hpp */
179 status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf); 73 status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
180 switch (status) { 74 switch (status) {
181 case AE_BUFFER_OVERFLOW: 75 case AE_BUFFER_OVERFLOW:
182 ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); 76 ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
183 if (!ret_buf.pointer) { 77 if (!ret_buf.pointer) {
184 err ("acpi_pciehprm:%s alloc for _HPP fail\n", path_name); 78 err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
185 return; 79 path_name);
80 return AE_NO_MEMORY;
186 } 81 }
187 status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf); 82 status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
83 NULL, &ret_buf);
188 if (ACPI_SUCCESS(status)) 84 if (ACPI_SUCCESS(status))
189 break; 85 break;
190 default: 86 default:
191 if (ACPI_FAILURE(status)) { 87 if (ACPI_FAILURE(status)) {
192 err("acpi_pciehprm:%s _HPP fail=0x%x\n", path_name, status); 88 dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
193 return; 89 path_name, status);
90 return status;
194 } 91 }
195 } 92 }
196 93
197 ext_obj = (union acpi_object *) ret_buf.pointer; 94 ext_obj = (union acpi_object *) ret_buf.pointer;
198 if (ext_obj->type != ACPI_TYPE_PACKAGE) { 95 if (ext_obj->type != ACPI_TYPE_PACKAGE) {
199 err ("acpi_pciehprm:%s _HPP obj not a package\n", path_name); 96 err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
97 path_name);
98 status = AE_ERROR;
200 goto free_and_return; 99 goto free_and_return;
201 } 100 }
202 101
@@ -209,689 +108,94 @@ static void acpi_get__hpp ( struct acpi_bridge *ab)
209 nui[i] = (u8)ext_obj->integer.value; 108 nui[i] = (u8)ext_obj->integer.value;
210 break; 109 break;
211 default: 110 default:
212 err ("acpi_pciehprm:%s _HPP obj type incorrect\n", path_name); 111 err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
112 path_name);
113 status = AE_ERROR;
213 goto free_and_return; 114 goto free_and_return;
214 } 115 }
215 } 116 }
216 117
217 ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL); 118 hpp->cache_line_size = nui[0];
218 if (!ab->_hpp) { 119 hpp->latency_timer = nui[1];
219 err ("acpi_pciehprm:%s alloc for _HPP failed\n", path_name); 120 hpp->enable_serr = nui[2];
220 goto free_and_return; 121 hpp->enable_perr = nui[3];
221 }
222 memset(ab->_hpp, 0, sizeof(struct acpi__hpp));
223 122
224 ab->_hpp->cache_line_size = nui[0]; 123 dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
225 ab->_hpp->latency_timer = nui[1]; 124 dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
226 ab->_hpp->enable_serr = nui[2]; 125 dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
227 ab->_hpp->enable_perr = nui[3]; 126 dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
228
229 dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size);
230 dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer);
231 dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr);
232 dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr);
233 127
234free_and_return: 128free_and_return:
235 kfree(ret_buf.pointer); 129 kfree(ret_buf.pointer);
130 return status;
236} 131}
237 132
238static int acpi_run_oshp ( struct acpi_bridge *ab) 133static acpi_status acpi_run_oshp(acpi_handle handle)
239{ 134{
240 acpi_status status; 135 acpi_status status;
241 u8 *path_name = acpi_path_name(ab->handle); 136 u8 *path_name = acpi_path_name(handle);
242 137
243 /* run OSHP */ 138 /* run OSHP */
244 status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, NULL); 139 status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
245 if (ACPI_FAILURE(status)) { 140 if (ACPI_FAILURE(status)) {
246 err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status); 141 err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
247 oshp_run_status = (status == AE_NOT_FOUND) ? OSHP_NOT_EXIST : OSHP_RUN_FAILED; 142 status);
248 } else { 143 } else {
249 oshp_run_status = NC_RUN_SUCCESS; 144 dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
250 dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status);
251 dbg("acpi_pciehprm:%s oshp_run_status =0x%x\n", path_name, oshp_run_status);
252 }
253 return oshp_run_status;
254}
255
256/* find acpi_bridge downword from ab. */
257static struct acpi_bridge *
258find_acpi_bridge_by_bus(
259 struct acpi_bridge *ab,
260 int seg,
261 int bus /* pdev->subordinate->number */
262 )
263{
264 struct acpi_bridge *lab = NULL;
265
266 if (!ab)
267 return NULL;
268
269 if ((ab->bus == bus) && (ab->seg == seg))
270 return ab;
271
272 if (ab->child)
273 lab = find_acpi_bridge_by_bus(ab->child, seg, bus);
274
275 if (!lab)
276 if (ab->next)
277 lab = find_acpi_bridge_by_bus(ab->next, seg, bus);
278
279 return lab;
280}
281
282/*
283 * Build a device tree of ACPI PCI Bridges
284 */
285static void pciehprm_acpi_register_a_bridge (
286 struct acpi_bridge **head,
287 struct acpi_bridge *pab, /* parent bridge to which child bridge is added */
288 struct acpi_bridge *cab /* child bridge to add */
289 )
290{
291 struct acpi_bridge *lpab;
292 struct acpi_bridge *lcab;
293
294 lpab = find_acpi_bridge_by_bus(*head, pab->seg, pab->bus);
295 if (!lpab) {
296 if (!(pab->type & BRIDGE_TYPE_HOST))
297 warn("PCI parent bridge s:b(%x:%x) not in list.\n", pab->seg, pab->bus);
298 pab->next = *head;
299 *head = pab;
300 lpab = pab;
301 } 145 }
302 146 return status;
303 if ((cab->type & BRIDGE_TYPE_HOST) && (pab == cab))
304 return;
305
306 lcab = find_acpi_bridge_by_bus(*head, cab->seg, cab->bus);
307 if (lcab) {
308 if ((pab->bus != lcab->parent->bus) || (lcab->bus != cab->bus))
309 err("PCI child bridge s:b(%x:%x) in list with diff parent.\n", cab->seg, cab->bus);
310 return;
311 } else
312 lcab = cab;
313
314 lcab->parent = lpab;
315 lcab->next = lpab->child;
316 lpab->child = lcab;
317} 147}
318 148
319static acpi_status pciehprm_acpi_build_php_slots_callback( 149int get_hp_hw_control_from_firmware(struct pci_dev *dev)
320 acpi_handle handle,
321 u32 Level,
322 void *context,
323 void **retval
324 )
325{ 150{
326 ulong bus_num; 151 acpi_status status;
327 ulong seg_num; 152 /*
328 ulong sun, adr; 153 * Per PCI firmware specification, we should run the ACPI _OSC
329 ulong padr = 0; 154 * method to get control of hotplug hardware before using it
330 acpi_handle phandle = NULL; 155 */
331 struct acpi_bridge *pab = (struct acpi_bridge *)context; 156 /* Fixme: run _OSC for a specific host bridge, not all of them */
332 struct acpi_bridge *lab; 157 status = pci_osc_control_set(OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
333 acpi_status status; 158
334 u8 *path_name = acpi_path_name(handle); 159 /* Fixme: fail native hotplug if _OSC does not exist for root ports */
335 160 if (status == AE_NOT_FOUND) {
336 /* get _SUN */ 161 /*
337 status = acpi_evaluate_integer(handle, METHOD_NAME__SUN, NULL, &sun); 162 * Some older BIOS's don't support _OSC but support
338 switch(status) { 163 * OSHP to do the same thing
339 case AE_NOT_FOUND: 164 */
340 return AE_OK; 165 acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev));
341 default: 166 if (handle)
342 if (ACPI_FAILURE(status)) { 167 status = acpi_run_oshp(handle);
343 err("acpi_pciehprm:%s _SUN fail=0x%x\n", path_name, status);
344 return status;
345 }
346 }
347
348 /* get _ADR. _ADR must exist if _SUN exists */
349 status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
350 if (ACPI_FAILURE(status)) {
351 err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status);
352 return status;
353 }
354
355 dbg("acpi_pciehprm:%s sun=0x%08x adr=0x%08x\n", path_name, (u32)sun, (u32)adr);
356
357 status = acpi_get_parent(handle, &phandle);
358 if (ACPI_FAILURE(status)) {
359 err("acpi_pciehprm:%s get_parent fail=0x%x\n", path_name, status);
360 return (status);
361 }
362
363 bus_num = pab->bus;
364 seg_num = pab->seg;
365
366 if (pab->bus == bus_num) {
367 lab = pab;
368 } else {
369 dbg("WARN: pab is not parent\n");
370 lab = find_acpi_bridge_by_bus(pab, seg_num, bus_num);
371 if (!lab) {
372 dbg("acpi_pciehprm: alloc new P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
373 lab = (struct acpi_bridge *)kmalloc(sizeof(struct acpi_bridge), GFP_KERNEL);
374 if (!lab) {
375 err("acpi_pciehprm: alloc for ab fail\n");
376 return AE_NO_MEMORY;
377 }
378 memset(lab, 0, sizeof(struct acpi_bridge));
379
380 lab->handle = phandle;
381 lab->pbus = pab->bus;
382 lab->pdevice = (int)(padr >> 16) & 0xffff;
383 lab->pfunction = (int)(padr & 0xffff);
384 lab->bus = (int)bus_num;
385 lab->scanned = 0;
386 lab->type = BRIDGE_TYPE_P2P;
387
388 pciehprm_acpi_register_a_bridge (&acpi_bridges_head, pab, lab);
389 } else
390 dbg("acpi_pciehprm: found P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
391 } 168 }
392
393 acpi_add_slot_to_php_slots(lab, (int)bus_num, handle, (u32)adr, (u32)sun);
394
395 return (status);
396}
397
398static int pciehprm_acpi_build_php_slots(
399 struct acpi_bridge *ab,
400 u32 depth
401 )
402{
403 acpi_status status;
404 u8 *path_name = acpi_path_name(ab->handle);
405
406 /* Walk down this pci bridge to get _SUNs if any behind P2P */
407 status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
408 ab->handle,
409 depth,
410 pciehprm_acpi_build_php_slots_callback,
411 ab,
412 NULL );
413 if (ACPI_FAILURE(status)) { 169 if (ACPI_FAILURE(status)) {
414 dbg("acpi_pciehprm:%s walk for _SUN on pci bridge seg:bus(%x:%x) fail=0x%x\n", path_name, ab->seg, ab->bus, status); 170 err("Cannot get control of hotplug hardware\n");
415 return -1; 171 return -1;
416 } 172 }
417 173
174 dbg("Sucess getting control of hotplug hardware\n");
418 return 0; 175 return 0;
419} 176}
420 177
421static void build_a_bridge( 178void get_hp_params_from_firmware(struct pci_dev *dev,
422 struct acpi_bridge *pab, 179 struct hotplug_params *hpp)
423 struct acpi_bridge *ab
424 )
425{
426 u8 *path_name = acpi_path_name(ab->handle);
427
428 pciehprm_acpi_register_a_bridge (&acpi_bridges_head, pab, ab);
429
430 switch (ab->type) {
431 case BRIDGE_TYPE_HOST:
432 dbg("acpi_pciehprm: Registered PCI HOST Bridge(%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
433 ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
434 break;
435 case BRIDGE_TYPE_P2P:
436 dbg("acpi_pciehprm: Registered PCI P2P Bridge(%02x-%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
437 ab->pbus, ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
438 break;
439 };
440
441 /* build any immediate PHP slots under this pci bridge */
442 pciehprm_acpi_build_php_slots(ab, 1);
443}
444
445static struct acpi_bridge * add_p2p_bridge(
446 acpi_handle handle,
447 struct acpi_bridge *pab, /* parent */
448 ulong adr
449 )
450{
451 struct acpi_bridge *ab;
452 struct pci_dev *pdev;
453 ulong devnum, funcnum;
454 u8 *path_name = acpi_path_name(handle);
455
456 ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
457 if (!ab) {
458 err("acpi_pciehprm: alloc for ab fail\n");
459 return NULL;
460 }
461 memset(ab, 0, sizeof(struct acpi_bridge));
462
463 devnum = (adr >> 16) & 0xffff;
464 funcnum = adr & 0xffff;
465
466 pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
467 if (!pdev || !pdev->subordinate) {
468 err("acpi_pciehprm:%s is not a P2P Bridge\n", path_name);
469 kfree(ab);
470 return NULL;
471 }
472
473 ab->handle = handle;
474 ab->seg = pab->seg;
475 ab->pbus = pab->bus; /* or pdev->bus->number */
476 ab->pdevice = devnum; /* or PCI_SLOT(pdev->devfn) */
477 ab->pfunction = funcnum; /* or PCI_FUNC(pdev->devfn) */
478 ab->bus = pdev->subordinate->number;
479 ab->scanned = 0;
480 ab->type = BRIDGE_TYPE_P2P;
481
482 dbg("acpi_pciehprm: P2P(%x-%x) on pci=b:d:f(%x:%x:%x) acpi=b:d:f(%x:%x:%x) [%s]\n",
483 pab->bus, ab->bus, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
484 pab->bus, (u32)devnum, (u32)funcnum, path_name);
485
486 build_a_bridge(pab, ab);
487
488 return ab;
489}
490
491static acpi_status scan_p2p_bridge(
492 acpi_handle handle,
493 u32 Level,
494 void *context,
495 void **retval
496 )
497{
498 struct acpi_bridge *pab = (struct acpi_bridge *)context;
499 struct acpi_bridge *ab;
500 acpi_status status;
501 ulong adr = 0;
502 u8 *path_name = acpi_path_name(handle);
503 ulong devnum, funcnum;
504 struct pci_dev *pdev;
505
506 /* get device, function */
507 status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
508 if (ACPI_FAILURE(status)) {
509 if (status != AE_NOT_FOUND)
510 err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status);
511 return AE_OK;
512 }
513
514 devnum = (adr >> 16) & 0xffff;
515 funcnum = adr & 0xffff;
516
517 pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
518 if (!pdev)
519 return AE_OK;
520 if (!pdev->subordinate)
521 return AE_OK;
522
523 ab = add_p2p_bridge(handle, pab, adr);
524 if (ab) {
525 status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
526 handle,
527 (u32)1,
528 scan_p2p_bridge,
529 ab,
530 NULL);
531 if (ACPI_FAILURE(status))
532 dbg("acpi_pciehprm:%s find_p2p fail=0x%x\n", path_name, status);
533 }
534
535 return AE_OK;
536}
537
538static struct acpi_bridge * add_host_bridge(
539 acpi_handle handle,
540 ulong segnum,
541 ulong busnum
542 )
543{
544 ulong adr = 0;
545 acpi_status status;
546 struct acpi_bridge *ab;
547 u8 *path_name = acpi_path_name(handle);
548
549 /* get device, function: host br adr is always 0000 though. */
550 status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
551 if (ACPI_FAILURE(status)) {
552 err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status);
553 return NULL;
554 }
555 dbg("acpi_pciehprm: ROOT PCI seg(0x%x)bus(0x%x)dev(0x%x)func(0x%x) [%s]\n", (u32)segnum,
556 (u32)busnum, (u32)(adr >> 16) & 0xffff, (u32)adr & 0xffff, path_name);
557
558 ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
559 if (!ab) {
560 err("acpi_pciehprm: alloc for ab fail\n");
561 return NULL;
562 }
563 memset(ab, 0, sizeof(struct acpi_bridge));
564
565 ab->handle = handle;
566 ab->seg = (int)segnum;
567 ab->bus = ab->pbus = (int)busnum;
568 ab->pdevice = (int)(adr >> 16) & 0xffff;
569 ab->pfunction = (int)(adr & 0xffff);
570 ab->scanned = 0;
571 ab->type = BRIDGE_TYPE_HOST;
572
573 status = pci_osc_control_set (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
574 if (ACPI_FAILURE(status)) {
575 err("%s: status %x\n", __FUNCTION__, status);
576 osc_run_status = (status == AE_NOT_FOUND) ? OSC_NOT_EXIST : OSC_RUN_FAILED;
577 } else {
578 osc_run_status = NC_RUN_SUCCESS;
579 }
580 dbg("%s: osc_run_status %x\n", __FUNCTION__, osc_run_status);
581
582 build_a_bridge(ab, ab);
583
584 return ab;
585}
586
587static acpi_status acpi_scan_from_root_pci_callback (
588 acpi_handle handle,
589 u32 Level,
590 void *context,
591 void **retval
592 )
593{
594 ulong segnum = 0;
595 ulong busnum = 0;
596 acpi_status status;
597 struct acpi_bridge *ab;
598 u8 *path_name = acpi_path_name(handle);
599
600 /* get bus number of this pci root bridge */
601 status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &segnum);
602 if (ACPI_FAILURE(status)) {
603 if (status != AE_NOT_FOUND) {
604 err("acpi_pciehprm:%s evaluate _SEG fail=0x%x\n", path_name, status);
605 return status;
606 }
607 segnum = 0;
608 }
609
610 /* get bus number of this pci root bridge */
611 status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, &busnum);
612 if (ACPI_FAILURE(status)) {
613 err("acpi_pciehprm:%s evaluate _BBN fail=0x%x\n", path_name, status);
614 return (status);
615 }
616
617 ab = add_host_bridge(handle, segnum, busnum);
618 if (ab) {
619 status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
620 handle,
621 1,
622 scan_p2p_bridge,
623 ab,
624 NULL);
625 if (ACPI_FAILURE(status))
626 dbg("acpi_pciehprm:%s find_p2p fail=0x%x\n", path_name, status);
627 }
628
629 return AE_OK;
630}
631
632static int pciehprm_acpi_scan_pci (void)
633{ 180{
634 acpi_status status; 181 acpi_status status = AE_NOT_FOUND;
182 struct pci_dev *pdev = dev;
635 183
636 /* 184 /*
637 * TBD: traverse LDM device tree with the help of 185 * _HPP settings apply to all child buses, until another _HPP is
638 * unified ACPI augmented for php device population. 186 * encountered. If we don't find an _HPP for the input pci dev,
187 * look for it in the parent device scope since that would apply to
188 * this pci dev. If we don't find any _HPP, use hardcoded defaults
639 */ 189 */
640 status = acpi_get_devices ( PCI_ROOT_HID_STRING, 190 while (pdev && (ACPI_FAILURE(status))) {
641 acpi_scan_from_root_pci_callback, 191 acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
642 NULL, 192 if (!handle)
643 NULL ); 193 break;
644 if (ACPI_FAILURE(status)) { 194 status = acpi_run_hpp(handle, hpp);
645 err("acpi_pciehprm:get_device PCI ROOT HID fail=0x%x\n", status); 195 if (!(pdev->bus->parent))
646 return -1; 196 break;
647 } 197 /* Check if a parent object supports _HPP */
648 198 pdev = pdev->bus->parent->self;
649 return 0;
650}
651
652int pciehprm_init(enum php_ctlr_type ctlr_type)
653{
654 int rc;
655
656 if (ctlr_type != PCI)
657 return -ENODEV;
658
659 dbg("pciehprm ACPI init <enter>\n");
660 acpi_bridges_head = NULL;
661
662 /* construct PCI bus:device tree of acpi_handles */
663 rc = pciehprm_acpi_scan_pci();
664 if (rc)
665 return rc;
666
667 if ((oshp_run_status != NC_RUN_SUCCESS) && (osc_run_status != NC_RUN_SUCCESS)) {
668 err("Fails to gain control of native hot-plug\n");
669 rc = -ENODEV;
670 }
671
672 dbg("pciehprm ACPI init %s\n", (rc)?"fail":"success");
673 return rc;
674}
675
676static void free_a_slot(struct acpi_php_slot *aps)
677{
678 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);
679
680 kfree(aps);
681}
682
683static void free_a_bridge( struct acpi_bridge *ab)
684{
685 struct acpi_php_slot *aps, *next;
686
687 switch (ab->type) {
688 case BRIDGE_TYPE_HOST:
689 dbg("Free ACPI PCI HOST Bridge(%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
690 ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
691 break;
692 case BRIDGE_TYPE_P2P:
693 dbg("Free ACPI PCI P2P Bridge(%x-%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
694 ab->pbus, ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
695 break;
696 };
697
698 /* free slots first */
699 for (aps = ab->slots; aps; aps = next) {
700 next = aps->next;
701 free_a_slot(aps);
702 }
703
704 kfree(ab);
705}
706
707static void pciehprm_free_bridges ( struct acpi_bridge *ab)
708{
709 if (!ab)
710 return;
711
712 if (ab->child)
713 pciehprm_free_bridges (ab->child);
714
715 if (ab->next)
716 pciehprm_free_bridges (ab->next);
717
718 free_a_bridge(ab);
719}
720
721void pciehprm_cleanup(void)
722{
723 pciehprm_free_bridges (acpi_bridges_head);
724}
725
726static int get_number_of_slots (
727 struct acpi_bridge *ab,
728 int selfonly
729 )
730{
731 struct acpi_php_slot *aps;
732 int prev_slot = -1;
733 int slot_num = 0;
734
735 for ( aps = ab->slots; aps; aps = aps->next)
736 if (aps->dev != prev_slot) {
737 prev_slot = aps->dev;
738 slot_num++;
739 }
740
741 if (ab->child)
742 slot_num += get_number_of_slots (ab->child, 0);
743
744 if (selfonly)
745 return slot_num;
746
747 if (ab->next)
748 slot_num += get_number_of_slots (ab->next, 0);
749
750 return slot_num;
751}
752
753static struct acpi_php_slot * get_acpi_slot (
754 struct acpi_bridge *ab,
755 u32 sun
756 )
757{
758 struct acpi_php_slot *aps = NULL;
759
760 for ( aps = ab->slots; aps; aps = aps->next)
761 if (aps->sun == sun)
762 return aps;
763
764 if (!aps && ab->child) {
765 aps = (struct acpi_php_slot *)get_acpi_slot (ab->child, sun);
766 if (aps)
767 return aps;
768 }
769
770 if (!aps && ab->next) {
771 aps = (struct acpi_php_slot *)get_acpi_slot (ab->next, sun);
772 if (aps)
773 return aps;
774 }
775
776 return aps;
777
778}
779
780#if 0
781void * pciehprm_get_slot(struct slot *slot)
782{
783 struct acpi_bridge *ab = acpi_bridges_head;
784 struct acpi_php_slot *aps = get_acpi_slot (ab, slot->number);
785
786 aps->slot = slot;
787
788 dbg("Got acpi slot sun(%x): s:b:d:f(%x:%x:%x:%x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);
789
790 return (void *)aps;
791}
792#endif
793
794int pciehprm_set_hpp(
795 struct controller *ctrl,
796 struct pci_func *func,
797 u8 card_type
798 )
799{
800 struct acpi_bridge *ab;
801 struct pci_bus lpci_bus, *pci_bus;
802 int rc = 0;
803 unsigned int devfn;
804 u8 cls= 0x08; /* default cache line size */
805 u8 lt = 0x40; /* default latency timer */
806 u8 ep = 0;
807 u8 es = 0;
808
809 memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
810 pci_bus = &lpci_bus;
811 pci_bus->number = func->bus;
812 devfn = PCI_DEVFN(func->device, func->function);
813
814 ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);
815
816 if (ab) {
817 if (ab->_hpp) {
818 lt = (u8)ab->_hpp->latency_timer;
819 cls = (u8)ab->_hpp->cache_line_size;
820 ep = (u8)ab->_hpp->enable_perr;
821 es = (u8)ab->_hpp->enable_serr;
822 } else
823 dbg("_hpp: no _hpp for B/D/F=%#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
824 } else
825 dbg("_hpp: no acpi bridge for B/D/F = %#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
826
827
828 if (card_type == PCI_HEADER_TYPE_BRIDGE) {
829 /* set subordinate Latency Timer */
830 rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, lt);
831 } 199 }
832
833 /* set base Latency Timer */
834 rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, lt);
835 dbg(" set latency timer =0x%02x: %x\n", lt, rc);
836
837 rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, cls);
838 dbg(" set cache_line_size=0x%02x: %x\n", cls, rc);
839
840 return rc;
841} 200}
842 201
843void pciehprm_enable_card(
844 struct controller *ctrl,
845 struct pci_func *func,
846 u8 card_type)
847{
848 u16 command, cmd, bcommand, bcmd;
849 struct pci_bus lpci_bus, *pci_bus;
850 struct acpi_bridge *ab;
851 unsigned int devfn;
852 int rc;
853
854 memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
855 pci_bus = &lpci_bus;
856 pci_bus->number = func->bus;
857 devfn = PCI_DEVFN(func->device, func->function);
858
859 rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &cmd);
860
861 if (card_type == PCI_HEADER_TYPE_BRIDGE) {
862 rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcmd);
863 }
864
865 command = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
866 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
867 bcommand = bcmd | PCI_BRIDGE_CTL_NO_ISA;
868
869 ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);
870 if (ab) {
871 if (ab->_hpp) {
872 if (ab->_hpp->enable_perr) {
873 command |= PCI_COMMAND_PARITY;
874 bcommand |= PCI_BRIDGE_CTL_PARITY;
875 } else {
876 command &= ~PCI_COMMAND_PARITY;
877 bcommand &= ~PCI_BRIDGE_CTL_PARITY;
878 }
879 if (ab->_hpp->enable_serr) {
880 command |= PCI_COMMAND_SERR;
881 bcommand |= PCI_BRIDGE_CTL_SERR;
882 } else {
883 command &= ~PCI_COMMAND_SERR;
884 bcommand &= ~PCI_BRIDGE_CTL_SERR;
885 }
886 } else
887 dbg("no _hpp for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
888 } else
889 dbg("no acpi bridge for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
890
891 if (command != cmd) {
892 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
893 }
894 if ((card_type == PCI_HEADER_TYPE_BRIDGE) && (bcommand != bcmd)) {
895 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
896 }
897}
diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c
index ed68c3dd0f08..32371cd19e34 100644
--- a/drivers/pci/hotplug/pciehprm_nonacpi.c
+++ b/drivers/pci/hotplug/pciehprm_nonacpi.c
@@ -37,15 +37,9 @@
37#include <linux/slab.h> 37#include <linux/slab.h>
38#include <asm/uaccess.h> 38#include <asm/uaccess.h>
39#include "pciehp.h" 39#include "pciehp.h"
40#include "pciehprm.h"
41#include "pciehprm_nonacpi.h" 40#include "pciehprm_nonacpi.h"
42 41
43 42
44void pciehprm_cleanup(void)
45{
46 return;
47}
48
49int pciehprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) 43int pciehprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
50{ 44{
51 45
@@ -53,106 +47,13 @@ int pciehprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busn
53 return 0; 47 return 0;
54} 48}
55 49
56int pciehprm_set_hpp( 50void get_hp_params_from_firmware(struct pci_dev *dev,
57 struct controller *ctrl, 51 struct hotplug_params *hpp)
58 struct pci_func *func,
59 u8 card_type)
60{
61 u32 rc;
62 u8 temp_byte;
63 struct pci_bus lpci_bus, *pci_bus;
64 unsigned int devfn;
65 memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
66 pci_bus = &lpci_bus;
67 pci_bus->number = func->bus;
68 devfn = PCI_DEVFN(func->device, func->function);
69
70 temp_byte = 0x40; /* hard coded value for LT */
71 if (card_type == PCI_HEADER_TYPE_BRIDGE) {
72 /* set subordinate Latency Timer */
73 rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);
74
75 if (rc) {
76 dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__,
77 func->bus, func->device, func->function);
78 return rc;
79 }
80 }
81
82 /* set base Latency Timer */
83 rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
84
85 if (rc) {
86 dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
87 return rc;
88 }
89
90 /* set Cache Line size */
91 temp_byte = 0x08; /* hard coded value for CLS */
92
93 rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
94
95 if (rc) {
96 dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
97 }
98
99 /* set enable_perr */
100 /* set enable_serr */
101
102 return rc;
103}
104
105void pciehprm_enable_card(
106 struct controller *ctrl,
107 struct pci_func *func,
108 u8 card_type)
109{ 52{
110 u16 command, bcommand; 53 return;
111 struct pci_bus lpci_bus, *pci_bus;
112 unsigned int devfn;
113 int rc;
114
115 memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
116 pci_bus = &lpci_bus;
117 pci_bus->number = func->bus;
118 devfn = PCI_DEVFN(func->device, func->function);
119
120 rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
121
122 command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR
123 | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
124 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
125
126 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
127
128 if (card_type == PCI_HEADER_TYPE_BRIDGE) {
129
130 rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
131
132 bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR
133 | PCI_BRIDGE_CTL_NO_ISA;
134
135 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
136 }
137} 54}
138 55
139static int legacy_pciehprm_init_pci(void) 56int get_hp_hw_control_from_firmware(struct pci_dev *dev)
140{ 57{
141 return 0; 58 return 0;
142} 59}
143
144int pciehprm_init(enum php_ctlr_type ctrl_type)
145{
146 int retval;
147
148 switch (ctrl_type) {
149 case PCI:
150 retval = legacy_pciehprm_init_pci();
151 break;
152 default:
153 retval = -ENODEV;
154 break;
155 }
156
157 return retval;
158}
diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.h b/drivers/pci/hotplug/pciehprm_nonacpi.h
deleted file mode 100644
index b10603b0e958..000000000000
--- a/drivers/pci/hotplug/pciehprm_nonacpi.h
+++ /dev/null
@@ -1,56 +0,0 @@
1/*
2 * PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
3 *
4 * Copyright (C) 1995,2001 Compaq Computer Corporation
5 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
6 * Copyright (C) 2001 IBM Corp.
7 * Copyright (C) 2003-2004 Intel Corporation
8 *
9 * All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or (at
14 * your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
19 * NON INFRINGEMENT. See the GNU General Public License for more
20 * details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *
26 * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
27 *
28 */
29
30#ifndef _PCIEHPRM_NONACPI_H_
31#define _PCIEHPRM_NONACPI_H_
32
33struct irq_info {
34 u8 bus, devfn; /* bus, device and function */
35 struct {
36 u8 link; /* IRQ line ID, chipset dependent, 0=not routed */
37 u16 bitmap; /* Available IRQs */
38 } __attribute__ ((packed)) irq[4];
39 u8 slot; /* slot number, 0=onboard */
40 u8 rfu;
41} __attribute__ ((packed));
42
43struct irq_routing_table {
44 u32 signature; /* PIRQ_SIGNATURE should be here */
45 u16 version; /* PIRQ_VERSION */
46 u16 size; /* Table size in bytes */
47 u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */
48 u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */
49 u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */
50 u32 miniport_data; /* Crap */
51 u8 rfu[11];
52 u8 checksum; /* Modulo 256 checksum must give zero */
53 struct irq_info slots[0];
54} __attribute__ ((packed));
55
56#endif /* _PCIEHPRM_NONACPI_H_ */