aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorrajesh.shah@intel.com <rajesh.shah@intel.com>2005-10-31 19:20:08 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2005-11-10 19:09:14 -0500
commitca22a5e4d70620b7f3d809e424daa5214b0aa00d (patch)
tree13f69e742475642f382bcb0350e399d14315b534 /drivers/pci
parenta8a2be949267cb0d1d933a92d9fb43eda4f4fe88 (diff)
[PATCH] pciehp: remove redundant data structures
State information is currently stored in per-slot as well as per-pci-function data structures in pciehp. There's a lot of overlap in the information kept, and some of it is never used. This patch consolidates the state information to per-slot and eliminates unused data structures. The biggest change is to eliminate the pci_func structure and the code around managing its lists. Signed-off-by: Rajesh Shah <rajesh.shah@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/hotplug/pciehp.h30
-rw-r--r--drivers/pci/hotplug/pciehp_core.c29
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c391
-rw-r--r--drivers/pci/hotplug/pciehp_pci.c349
4 files changed, 65 insertions, 734 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index e9c09566f851..3e17e3d4dd65 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -56,25 +56,11 @@ struct hotplug_params {
56 u8 enable_perr; 56 u8 enable_perr;
57}; 57};
58 58
59struct pci_func {
60 struct pci_func *next;
61 u8 bus;
62 u8 device;
63 u8 function;
64 u8 is_a_board;
65 u16 status;
66 u8 configured;
67 u8 switch_save;
68 u8 presence_save;
69 u16 reserved2;
70 u32 config_space[0x20];
71 struct pci_dev* pci_dev;
72};
73
74struct slot { 59struct slot {
75 struct slot *next; 60 struct slot *next;
76 u8 bus; 61 u8 bus;
77 u8 device; 62 u8 device;
63 u16 status;
78 u32 number; 64 u32 number;
79 u8 is_a_board; 65 u8 is_a_board;
80 u8 configured; 66 u8 configured;
@@ -177,9 +163,6 @@ struct controller {
177 * error Messages 163 * error Messages
178 */ 164 */
179#define msg_initialization_err "Initialization failure, error=%d\n" 165#define msg_initialization_err "Initialization failure, error=%d\n"
180#define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n"
181#define msg_HPC_non_pcie "The PCI hot plug controller is not supported by this driver.\n"
182#define msg_HPC_not_supported "This system is not supported by this version of pciephd module. Upgrade to a newer version of pciehpd\n"
183#define msg_button_on "PCI slot #%d - powering on due to button press.\n" 166#define msg_button_on "PCI slot #%d - powering on due to button press.\n"
184#define msg_button_off "PCI slot #%d - powering off due to button press.\n" 167#define msg_button_off "PCI slot #%d - powering off due to button press.\n"
185#define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n" 168#define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n"
@@ -188,8 +171,6 @@ struct controller {
188/* controller functions */ 171/* controller functions */
189extern int pciehp_event_start_thread (void); 172extern int pciehp_event_start_thread (void);
190extern void pciehp_event_stop_thread (void); 173extern void pciehp_event_stop_thread (void);
191extern struct pci_func *pciehp_slot_create (unsigned char busnumber);
192extern struct pci_func *pciehp_slot_find (unsigned char bus, unsigned char device, unsigned char index);
193extern int pciehp_enable_slot (struct slot *slot); 174extern int pciehp_enable_slot (struct slot *slot);
194extern int pciehp_disable_slot (struct slot *slot); 175extern int pciehp_disable_slot (struct slot *slot);
195 176
@@ -200,12 +181,8 @@ extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id);
200/* extern void long_delay (int delay); */ 181/* extern void long_delay (int delay); */
201 182
202/* pci functions */ 183/* pci functions */
203extern int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num); 184extern int pciehp_configure_device (struct slot *p_slot);
204/*extern int pciehp_get_bus_dev (struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/ 185extern int pciehp_unconfigure_device (struct slot *p_slot);
205extern int pciehp_save_config (struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
206extern int pciehp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot);
207extern int pciehp_configure_device (struct slot *ctrl);
208extern int pciehp_unconfigure_device (struct pci_func* func);
209extern int get_hp_hw_control_from_firmware(struct pci_dev *dev); 186extern int get_hp_hw_control_from_firmware(struct pci_dev *dev);
210extern void get_hp_params_from_firmware(struct pci_dev *dev, 187extern void get_hp_params_from_firmware(struct pci_dev *dev,
211 struct hotplug_params *hpp); 188 struct hotplug_params *hpp);
@@ -214,7 +191,6 @@ extern void get_hp_params_from_firmware(struct pci_dev *dev,
214 191
215/* Global variables */ 192/* Global variables */
216extern struct controller *pciehp_ctrl_list; 193extern struct controller *pciehp_ctrl_list;
217extern struct pci_func *pciehp_slot_list[256];
218 194
219/* Inline functions */ 195/* Inline functions */
220 196
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index e20cf8e42bd9..be608563e8b6 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -46,7 +46,6 @@ int pciehp_debug;
46int pciehp_poll_mode; 46int pciehp_poll_mode;
47int pciehp_poll_time; 47int pciehp_poll_time;
48struct controller *pciehp_ctrl_list; 48struct controller *pciehp_ctrl_list;
49struct pci_func *pciehp_slot_list[256];
50 49
51#define DRIVER_VERSION "0.4" 50#define DRIVER_VERSION "0.4"
52#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" 51#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -422,15 +421,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
422 first_device_num = ctrl->slot_device_offset; 421 first_device_num = ctrl->slot_device_offset;
423 num_ctlr_slots = ctrl->num_slots; 422 num_ctlr_slots = ctrl->num_slots;
424 423
425 /* Store PCI Config Space for all devices on this bus */
426 dbg("%s: Before calling pciehp_save_config, ctrl->bus %x,ctrl->slot_bus %x\n",
427 __FUNCTION__,ctrl->bus, ctrl->slot_bus);
428 rc = pciehp_save_config(ctrl, ctrl->slot_bus, num_ctlr_slots, first_device_num);
429 if (rc) {
430 err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc);
431 goto err_out_free_ctrl_bus;
432 }
433
434 ctrl->add_support = 1; 424 ctrl->add_support = 1;
435 425
436 /* Setup the slot information structures */ 426 /* Setup the slot information structures */
@@ -491,7 +481,6 @@ err_out_none:
491 481
492static int pcie_start_thread(void) 482static int pcie_start_thread(void)
493{ 483{
494 int loop;
495 int retval = 0; 484 int retval = 0;
496 485
497 dbg("Initialize + Start the notification/polling mechanism \n"); 486 dbg("Initialize + Start the notification/polling mechanism \n");
@@ -502,20 +491,11 @@ static int pcie_start_thread(void)
502 return retval; 491 return retval;
503 } 492 }
504 493
505 dbg("Initialize slot lists\n");
506 /* One slot list for each bus in the system */
507 for (loop = 0; loop < 256; loop++) {
508 pciehp_slot_list[loop] = NULL;
509 }
510
511 return retval; 494 return retval;
512} 495}
513 496
514static void __exit unload_pciehpd(void) 497static void __exit unload_pciehpd(void)
515{ 498{
516 struct pci_func *next;
517 struct pci_func *TempSlot;
518 int loop;
519 struct controller *ctrl; 499 struct controller *ctrl;
520 struct controller *tctrl; 500 struct controller *tctrl;
521 501
@@ -534,15 +514,6 @@ static void __exit unload_pciehpd(void)
534 kfree(tctrl); 514 kfree(tctrl);
535 } 515 }
536 516
537 for (loop = 0; loop < 256; loop++) {
538 next = pciehp_slot_list[loop];
539 while (next != NULL) {
540 TempSlot = next;
541 next = next->next;
542 kfree(TempSlot);
543 }
544 }
545
546 /* Stop the notification mechanism */ 517 /* Stop the notification mechanism */
547 pciehp_event_stop_thread(); 518 pciehp_event_stop_thread();
548 519
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index d07d4194bc29..b60e4973289c 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -55,19 +55,16 @@ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id)
55 struct slot *p_slot; 55 struct slot *p_slot;
56 u8 rc = 0; 56 u8 rc = 0;
57 u8 getstatus; 57 u8 getstatus;
58 struct pci_func *func;
59 struct event_info *taskInfo; 58 struct event_info *taskInfo;
60 59
61 /* Attention Button Change */ 60 /* Attention Button Change */
62 dbg("pciehp: Attention button interrupt received.\n"); 61 dbg("pciehp: Attention button interrupt received.\n");
63 62
64 func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
65
66 /* This is the structure that tells the worker thread what to do */ 63 /* This is the structure that tells the worker thread what to do */
67 taskInfo = &(ctrl->event_queue[ctrl->next_event]); 64 taskInfo = &(ctrl->event_queue[ctrl->next_event]);
68 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 65 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
69 66
70 p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); 67 p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
71 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 68 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
72 69
73 ctrl->next_event = (ctrl->next_event + 1) % 10; 70 ctrl->next_event = (ctrl->next_event + 1) % 10;
@@ -112,14 +109,11 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id)
112 struct slot *p_slot; 109 struct slot *p_slot;
113 u8 rc = 0; 110 u8 rc = 0;
114 u8 getstatus; 111 u8 getstatus;
115 struct pci_func *func;
116 struct event_info *taskInfo; 112 struct event_info *taskInfo;
117 113
118 /* Switch Change */ 114 /* Switch Change */
119 dbg("pciehp: Switch interrupt received.\n"); 115 dbg("pciehp: Switch interrupt received.\n");
120 116
121 func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
122
123 /* This is the structure that tells the worker thread 117 /* This is the structure that tells the worker thread
124 * what to do 118 * what to do
125 */ 119 */
@@ -129,7 +123,7 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id)
129 123
130 rc++; 124 rc++;
131 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 125 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
132 p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); 126 p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
133 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 127 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
134 128
135 if (getstatus) { 129 if (getstatus) {
@@ -137,14 +131,14 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id)
137 * Switch opened 131 * Switch opened
138 */ 132 */
139 info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); 133 info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
140 func->switch_save = 0; 134 p_slot->switch_save = 0;
141 taskInfo->event_type = INT_SWITCH_OPEN; 135 taskInfo->event_type = INT_SWITCH_OPEN;
142 } else { 136 } else {
143 /* 137 /*
144 * Switch closed 138 * Switch closed
145 */ 139 */
146 info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); 140 info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
147 func->switch_save = 0x10; 141 p_slot->switch_save = 0x10;
148 taskInfo->event_type = INT_SWITCH_CLOSE; 142 taskInfo->event_type = INT_SWITCH_CLOSE;
149 } 143 }
150 144
@@ -159,14 +153,11 @@ u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id)
159 struct controller *ctrl = (struct controller *) inst_id; 153 struct controller *ctrl = (struct controller *) inst_id;
160 struct slot *p_slot; 154 struct slot *p_slot;
161 u8 rc = 0; 155 u8 rc = 0;
162 struct pci_func *func;
163 struct event_info *taskInfo; 156 struct event_info *taskInfo;
164 157
165 /* Presence Change */ 158 /* Presence Change */
166 dbg("pciehp: Presence/Notify input change.\n"); 159 dbg("pciehp: Presence/Notify input change.\n");
167 160
168 func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
169
170 /* This is the structure that tells the worker thread 161 /* This is the structure that tells the worker thread
171 * what to do 162 * what to do
172 */ 163 */
@@ -180,8 +171,8 @@ u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id)
180 /* Switch is open, assume a presence change 171 /* Switch is open, assume a presence change
181 * Save the presence state 172 * Save the presence state
182 */ 173 */
183 p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); 174 p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
184 if (func->presence_save) { 175 if (p_slot->presence_save) {
185 /* 176 /*
186 * Card Present 177 * Card Present
187 */ 178 */
@@ -206,14 +197,11 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
206 struct controller *ctrl = (struct controller *) inst_id; 197 struct controller *ctrl = (struct controller *) inst_id;
207 struct slot *p_slot; 198 struct slot *p_slot;
208 u8 rc = 0; 199 u8 rc = 0;
209 struct pci_func *func;
210 struct event_info *taskInfo; 200 struct event_info *taskInfo;
211 201
212 /* power fault */ 202 /* power fault */
213 dbg("pciehp: Power fault interrupt received.\n"); 203 dbg("pciehp: Power fault interrupt received.\n");
214 204
215 func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
216
217 /* this is the structure that tells the worker thread 205 /* this is the structure that tells the worker thread
218 * what to do 206 * what to do
219 */ 207 */
@@ -229,7 +217,7 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
229 * power fault Cleared 217 * power fault Cleared
230 */ 218 */
231 info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); 219 info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
232 func->status = 0x00; 220 p_slot->status = 0x00;
233 taskInfo->event_type = INT_POWER_FAULT_CLEAR; 221 taskInfo->event_type = INT_POWER_FAULT_CLEAR;
234 } else { 222 } else {
235 /* 223 /*
@@ -238,7 +226,7 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
238 info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); 226 info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
239 taskInfo->event_type = INT_POWER_FAULT; 227 taskInfo->event_type = INT_POWER_FAULT;
240 /* set power fault status for this board */ 228 /* set power fault status for this board */
241 func->status = 0xFF; 229 p_slot->status = 0xFF;
242 info("power fault bit %x set\n", hp_slot); 230 info("power fault bit %x set\n", hp_slot);
243 } 231 }
244 if (rc) 232 if (rc)
@@ -247,187 +235,6 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
247 return rc; 235 return rc;
248} 236}
249 237
250/**
251 * pciehp_slot_create - Creates a node and adds it to the proper bus.
252 * @busnumber - bus where new node is to be located
253 *
254 * Returns pointer to the new node or NULL if unsuccessful
255 */
256struct pci_func *pciehp_slot_create(u8 busnumber)
257{
258 struct pci_func *new_slot;
259 struct pci_func *next;
260 dbg("%s: busnumber %x\n", __FUNCTION__, busnumber);
261 new_slot = kmalloc(sizeof(struct pci_func), GFP_KERNEL);
262
263 if (new_slot == NULL)
264 return new_slot;
265
266 memset(new_slot, 0, sizeof(struct pci_func));
267
268 new_slot->next = NULL;
269 new_slot->configured = 1;
270
271 if (pciehp_slot_list[busnumber] == NULL) {
272 pciehp_slot_list[busnumber] = new_slot;
273 } else {
274 next = pciehp_slot_list[busnumber];
275 while (next->next != NULL)
276 next = next->next;
277 next->next = new_slot;
278 }
279 return new_slot;
280}
281
282
283/**
284 * slot_remove - Removes a node from the linked list of slots.
285 * @old_slot: slot to remove
286 *
287 * Returns 0 if successful, !0 otherwise.
288 */
289static int slot_remove(struct pci_func * old_slot)
290{
291 struct pci_func *next;
292
293 if (old_slot == NULL)
294 return 1;
295
296 next = pciehp_slot_list[old_slot->bus];
297
298 if (next == NULL)
299 return 1;
300
301 if (next == old_slot) {
302 pciehp_slot_list[old_slot->bus] = old_slot->next;
303 kfree(old_slot);
304 return 0;
305 }
306
307 while ((next->next != old_slot) && (next->next != NULL)) {
308 next = next->next;
309 }
310
311 if (next->next == old_slot) {
312 next->next = old_slot->next;
313 kfree(old_slot);
314 return 0;
315 } else
316 return 2;
317}
318
319
320/**
321 * bridge_slot_remove - Removes a node from the linked list of slots.
322 * @bridge: bridge to remove
323 *
324 * Returns 0 if successful, !0 otherwise.
325 */
326static int bridge_slot_remove(struct pci_func *bridge)
327{
328 u8 subordinateBus, secondaryBus;
329 u8 tempBus;
330 struct pci_func *next;
331
332 if (bridge == NULL)
333 return 1;
334
335 secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF;
336 subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF;
337
338 for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {
339 next = pciehp_slot_list[tempBus];
340
341 while (!slot_remove(next)) {
342 next = pciehp_slot_list[tempBus];
343 }
344 }
345
346 next = pciehp_slot_list[bridge->bus];
347
348 if (next == NULL) {
349 return 1;
350 }
351
352 if (next == bridge) {
353 pciehp_slot_list[bridge->bus] = bridge->next;
354 kfree(bridge);
355 return 0;
356 }
357
358 while ((next->next != bridge) && (next->next != NULL)) {
359 next = next->next;
360 }
361
362 if (next->next == bridge) {
363 next->next = bridge->next;
364 kfree(bridge);
365 return 0;
366 } else
367 return 2;
368}
369
370
371/**
372 * pciehp_slot_find - Looks for a node by bus, and device, multiple functions accessed
373 * @bus: bus to find
374 * @device: device to find
375 * @index: is 0 for first function found, 1 for the second...
376 *
377 * Returns pointer to the node if successful, %NULL otherwise.
378 */
379struct pci_func *pciehp_slot_find(u8 bus, u8 device, u8 index)
380{
381 int found = -1;
382 struct pci_func *func;
383
384 func = pciehp_slot_list[bus];
385 dbg("%s: bus %x device %x index %x\n",
386 __FUNCTION__, bus, device, index);
387 if (func != NULL) {
388 dbg("%s: func-> bus %x device %x function %x pci_dev %p\n",
389 __FUNCTION__, func->bus, func->device, func->function,
390 func->pci_dev);
391 } else
392 dbg("%s: func == NULL\n", __FUNCTION__);
393
394 if ((func == NULL) || ((func->device == device) && (index == 0)))
395 return func;
396
397 if (func->device == device)
398 found++;
399
400 while (func->next != NULL) {
401 func = func->next;
402
403 dbg("%s: In while loop, func-> bus %x device %x function %x pci_dev %p\n",
404 __FUNCTION__, func->bus, func->device, func->function,
405 func->pci_dev);
406 if (func->device == device)
407 found++;
408 dbg("%s: while loop, found %d, index %d\n", __FUNCTION__,
409 found, index);
410
411 if ((found == index) || (func->function == index)) {
412 dbg("%s: Found bus %x dev %x func %x\n", __FUNCTION__,
413 func->bus, func->device, func->function);
414 return func;
415 }
416 }
417
418 return NULL;
419}
420
421static int is_bridge(struct pci_func * func)
422{
423 /* Check the header type */
424 if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01)
425 return 1;
426 else
427 return 0;
428}
429
430
431/* The following routines constitute the bulk of the 238/* The following routines constitute the bulk of the
432 hotplug controller logic 239 hotplug controller logic
433 */ 240 */
@@ -472,17 +279,16 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
472 * Configures board 279 * Configures board
473 * 280 *
474 */ 281 */
475static u32 board_added(struct pci_func * func, struct controller * ctrl) 282static u32 board_added(struct slot *p_slot)
476{ 283{
477 u8 hp_slot; 284 u8 hp_slot;
478 u32 temp_register = 0xFFFFFFFF; 285 u32 temp_register = 0xFFFFFFFF;
479 u32 rc = 0; 286 u32 rc = 0;
480 struct slot *p_slot; 287 struct controller *ctrl = p_slot->ctrl;
481 288
482 p_slot = pciehp_find_slot(ctrl, func->device); 289 hp_slot = p_slot->device - ctrl->slot_device_offset;
483 hp_slot = func->device - ctrl->slot_device_offset;
484 290
485 dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); 291 dbg("%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, p_slot->device, ctrl->slot_device_offset, hp_slot);
486 292
487 /* Wait for exclusive access to hardware */ 293 /* Wait for exclusive access to hardware */
488 down(&ctrl->crit_sect); 294 down(&ctrl->crit_sect);
@@ -522,15 +328,15 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
522 return rc; 328 return rc;
523 } 329 }
524 330
525 dbg("%s: func status = %x\n", __FUNCTION__, func->status); 331 dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status);
526 332
527 /* Check for a power fault */ 333 /* Check for a power fault */
528 if (func->status == 0xFF) { 334 if (p_slot->status == 0xFF) {
529 /* power fault occurred, but it was benign */ 335 /* power fault occurred, but it was benign */
530 temp_register = 0xFFFFFFFF; 336 temp_register = 0xFFFFFFFF;
531 dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register); 337 dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register);
532 rc = POWER_FAILURE; 338 rc = POWER_FAILURE;
533 func->status = 0; 339 p_slot->status = 0;
534 goto err_exit; 340 goto err_exit;
535 } 341 }
536 342
@@ -541,10 +347,9 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
541 goto err_exit; 347 goto err_exit;
542 } 348 }
543 349
544 pciehp_save_slot_config(ctrl, func); 350 p_slot->status = 0;
545 func->status = 0; 351 p_slot->switch_save = 0x10;
546 func->switch_save = 0x10; 352 p_slot->is_a_board = 0x01;
547 func->is_a_board = 0x01;
548 353
549 /* 354 /*
550 * Some PCI Express root ports require fixup after hot-plug operation. 355 * Some PCI Express root ports require fixup after hot-plug operation.
@@ -575,30 +380,27 @@ err_exit:
575 * remove_board - Turns off slot and LED's 380 * remove_board - Turns off slot and LED's
576 * 381 *
577 */ 382 */
578static u32 remove_board(struct pci_func *func, struct controller *ctrl) 383static u32 remove_board(struct slot *p_slot)
579{ 384{
580 u8 device; 385 u8 device;
581 u8 hp_slot; 386 u8 hp_slot;
582 u32 rc; 387 u32 rc;
583 struct slot *p_slot; 388 struct controller *ctrl = p_slot->ctrl;
584
585 if (func == NULL)
586 return 1;
587 389
588 if (pciehp_unconfigure_device(func)) 390 if (pciehp_unconfigure_device(p_slot))
589 return 1; 391 return 1;
590 392
591 device = func->device; 393 device = p_slot->device;
592 394
593 hp_slot = func->device - ctrl->slot_device_offset; 395 hp_slot = p_slot->device - ctrl->slot_device_offset;
594 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 396 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
595 397
596 dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); 398 dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
597 399
598 /* Change status to shutdown */ 400 /* Change status to shutdown */
599 if (func->is_a_board) 401 if (p_slot->is_a_board)
600 func->status = 0x01; 402 p_slot->status = 0x01;
601 func->configured = 0; 403 p_slot->configured = 0;
602 404
603 /* Wait for exclusive access to hardware */ 405 /* Wait for exclusive access to hardware */
604 down(&ctrl->crit_sect); 406 down(&ctrl->crit_sect);
@@ -626,35 +428,8 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl)
626 /* Done with exclusive hardware access */ 428 /* Done with exclusive hardware access */
627 up(&ctrl->crit_sect); 429 up(&ctrl->crit_sect);
628 430
629 if (ctrl->add_support) { 431 p_slot->switch_save = 0x10;
630 while (func) { 432 p_slot->is_a_board = 0;
631 if (is_bridge(func)) {
632 dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n",
633 ctrl->seg, func->bus, func->device, func->function);
634 bridge_slot_remove(func);
635 } else {
636 dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n",
637 ctrl->seg, func->bus, func->device, func->function);
638 slot_remove(func);
639 }
640
641 func = pciehp_slot_find(ctrl->slot_bus, device, 0);
642 }
643
644 /* Setup slot structure with entry for empty slot */
645 func = pciehp_slot_create(ctrl->slot_bus);
646
647 if (func == NULL) {
648 return 1;
649 }
650
651 func->bus = ctrl->slot_bus;
652 func->device = device;
653 func->function = 0;
654 func->configured = 0;
655 func->switch_save = 0x10;
656 func->is_a_board = 0;
657 }
658 433
659 return 0; 434 return 0;
660} 435}
@@ -851,7 +626,6 @@ static void interrupt_event_handler(struct controller *ctrl)
851{ 626{
852 int loop = 0; 627 int loop = 0;
853 int change = 1; 628 int change = 1;
854 struct pci_func *func;
855 u8 hp_slot; 629 u8 hp_slot;
856 u8 getstatus; 630 u8 getstatus;
857 struct slot *p_slot; 631 struct slot *p_slot;
@@ -863,11 +637,9 @@ static void interrupt_event_handler(struct controller *ctrl)
863 if (ctrl->event_queue[loop].event_type != 0) { 637 if (ctrl->event_queue[loop].event_type != 0) {
864 hp_slot = ctrl->event_queue[loop].hp_slot; 638 hp_slot = ctrl->event_queue[loop].hp_slot;
865 639
866 func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
867
868 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 640 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
869 641
870 dbg("hp_slot %d, func %p, p_slot %p\n", hp_slot, func, p_slot); 642 dbg("hp_slot %d, p_slot %p\n", hp_slot, p_slot);
871 643
872 if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { 644 if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) {
873 dbg("button cancel\n"); 645 dbg("button cancel\n");
@@ -1015,13 +787,6 @@ int pciehp_enable_slot(struct slot *p_slot)
1015{ 787{
1016 u8 getstatus = 0; 788 u8 getstatus = 0;
1017 int rc; 789 int rc;
1018 struct pci_func *func;
1019
1020 func = pciehp_slot_find(p_slot->bus, p_slot->device, 0);
1021 if (!func) {
1022 dbg("%s: Error! slot NULL\n", __FUNCTION__);
1023 return 1;
1024 }
1025 790
1026 /* Check to see if (latch closed, card present, power off) */ 791 /* Check to see if (latch closed, card present, power off) */
1027 down(&p_slot->ctrl->crit_sect); 792 down(&p_slot->ctrl->crit_sect);
@@ -1051,45 +816,21 @@ int pciehp_enable_slot(struct slot *p_slot)
1051 } 816 }
1052 up(&p_slot->ctrl->crit_sect); 817 up(&p_slot->ctrl->crit_sect);
1053 818
1054 slot_remove(func); 819 p_slot->configured = 0;
1055 820 p_slot->is_a_board = 1;
1056 func = pciehp_slot_create(p_slot->bus);
1057 if (func == NULL)
1058 return 1;
1059
1060 func->bus = p_slot->bus;
1061 func->device = p_slot->device;
1062 func->function = 0;
1063 func->configured = 0;
1064 func->is_a_board = 1;
1065 821
1066 /* We have to save the presence info for these slots */ 822 /* We have to save the presence info for these slots */
1067 p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); 823 p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
1068 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 824 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
1069 func->switch_save = !getstatus? 0x10:0; 825 p_slot->switch_save = !getstatus? 0x10:0;
1070 826
1071 rc = board_added(func, p_slot->ctrl); 827 rc = board_added(p_slot);
1072 if (rc) { 828 if (rc) {
1073 if (is_bridge(func))
1074 bridge_slot_remove(func);
1075 else
1076 slot_remove(func);
1077
1078 /* Setup slot structure with entry for empty slot */
1079 func = pciehp_slot_create(p_slot->bus);
1080 if (func == NULL)
1081 return 1; /* Out of memory */
1082
1083 func->bus = p_slot->bus;
1084 func->device = p_slot->device;
1085 func->function = 0;
1086 func->configured = 0;
1087 func->is_a_board = 1;
1088
1089 /* We have to save the presence info for these slots */ 829 /* We have to save the presence info for these slots */
1090 p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); 830 p_slot->hpc_ops->get_adapter_status(p_slot,
831 &(p_slot->presence_save));
1091 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 832 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
1092 func->switch_save = !getstatus? 0x10:0; 833 p_slot->switch_save = !getstatus? 0x10:0;
1093 } 834 }
1094 835
1095 if (p_slot) 836 if (p_slot)
@@ -1101,14 +842,8 @@ int pciehp_enable_slot(struct slot *p_slot)
1101 842
1102int pciehp_disable_slot(struct slot *p_slot) 843int pciehp_disable_slot(struct slot *p_slot)
1103{ 844{
1104 u8 class_code, header_type, BCR;
1105 u8 index = 0;
1106 u8 getstatus = 0; 845 u8 getstatus = 0;
1107 u32 rc = 0;
1108 int ret = 0; 846 int ret = 0;
1109 unsigned int devfn;
1110 struct pci_bus *pci_bus = p_slot->ctrl->pci_dev->subordinate;
1111 struct pci_func *func;
1112 847
1113 if (!p_slot->ctrl) 848 if (!p_slot->ctrl)
1114 return 1; 849 return 1;
@@ -1145,54 +880,8 @@ int pciehp_disable_slot(struct slot *p_slot)
1145 880
1146 up(&p_slot->ctrl->crit_sect); 881 up(&p_slot->ctrl->crit_sect);
1147 882
1148 func = pciehp_slot_find(p_slot->bus, p_slot->device, index++); 883 ret = remove_board(p_slot);
1149 884 update_slot_info(p_slot);
1150 /* Make sure there are no video controllers here 885 return ret;
1151 * for all func of p_slot
1152 */
1153 while (func && !rc) {
1154 pci_bus->number = func->bus;
1155 devfn = PCI_DEVFN(func->device, func->function);
1156
1157 /* Check the Class Code */
1158 rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
1159 if (rc)
1160 return rc;
1161
1162 if (class_code == PCI_BASE_CLASS_DISPLAY) {
1163 /* Display/Video adapter (not supported) */
1164 rc = REMOVE_NOT_SUPPORTED;
1165 } else {
1166 /* See if it's a bridge */
1167 rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
1168 if (rc)
1169 return rc;
1170
1171 /* If it's a bridge, check the VGA Enable bit */
1172 if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
1173 rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR);
1174 if (rc)
1175 return rc;
1176
1177 /* If the VGA Enable bit is set, remove isn't supported */
1178 if (BCR & PCI_BRIDGE_CTL_VGA) {
1179 rc = REMOVE_NOT_SUPPORTED;
1180 }
1181 }
1182 }
1183
1184 func = pciehp_slot_find(p_slot->bus, p_slot->device, index++);
1185 }
1186
1187 func = pciehp_slot_find(p_slot->bus, p_slot->device, 0);
1188 if ((func != NULL) && !rc) {
1189 rc = remove_board(func, p_slot->ctrl);
1190 } else if (!rc)
1191 rc = 1;
1192
1193 if (p_slot)
1194 update_slot_info(p_slot);
1195
1196 return rc;
1197} 886}
1198 887
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index db59a06ab0b4..1d185c1bc77a 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -101,346 +101,41 @@ int pciehp_configure_device(struct slot *p_slot)
101 return 0; 101 return 0;
102} 102}
103 103
104int pciehp_unconfigure_device(struct pci_func* func) 104int pciehp_unconfigure_device(struct slot *p_slot)
105{ 105{
106 int rc = 0; 106 int rc = 0;
107 int j; 107 int j;
108 struct pci_bus *pbus; 108 u8 bctl = 0;
109 109
110 dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, 110 dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus,
111 func->device, func->function); 111 p_slot->device);
112 pbus = func->pci_dev->bus;
113 112
114 for (j=0; j<8 ; j++) { 113 for (j=0; j<8 ; j++) {
115 struct pci_dev* temp = pci_find_slot(func->bus, 114 struct pci_dev* temp = pci_find_slot(p_slot->bus,
116 (func->device << 3) | j); 115 (p_slot->device << 3) | j);
117 if (temp) { 116 if (!temp)
118 pci_remove_bus_device(temp); 117 continue;
118 if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
119 err("Cannot remove display device %s\n",
120 pci_name(temp));
121 continue;
122 }
123 if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
124 pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
125 if (bctl & PCI_BRIDGE_CTL_VGA) {
126 err("Cannot remove display device %s\n",
127 pci_name(temp));
128 continue;
129 }
119 } 130 }
131 pci_remove_bus_device(temp);
120 } 132 }
121 /* 133 /*
122 * Some PCI Express root ports require fixup after hot-plug operation. 134 * Some PCI Express root ports require fixup after hot-plug operation.
123 */ 135 */
124 if (pcie_mch_quirk) 136 if (pcie_mch_quirk)
125 pci_fixup_device(pci_fixup_final, pbus->self); 137 pci_fixup_device(pci_fixup_final, p_slot->ctrl->pci_dev);
126 138
127 return rc; 139 return rc;
128} 140}
129 141
130/*
131 * pciehp_save_config
132 *
133 * Reads configuration for all slots in a PCI bus and saves info.
134 *
135 * Note: For non-hot plug busses, the slot # saved is the device #
136 *
137 * returns 0 if success
138 */
139int pciehp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num)
140{
141 int rc;
142 u8 class_code;
143 u8 header_type;
144 u32 ID;
145 u8 secondary_bus;
146 struct pci_func *new_slot;
147 int sub_bus;
148 int max_functions;
149 int function;
150 u8 DevError;
151 int device = 0;
152 int cloop = 0;
153 int stop_it;
154 int index;
155 int is_hot_plug = num_ctlr_slots || first_device_num;
156 struct pci_bus lpci_bus, *pci_bus;
157 int FirstSupported, LastSupported;
158
159 dbg("%s: Enter\n", __FUNCTION__);
160
161 memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
162 pci_bus = &lpci_bus;
163
164 dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__,
165 num_ctlr_slots, first_device_num);
166
167 /* Decide which slots are supported */
168 if (is_hot_plug) {
169 /*********************************
170 * is_hot_plug is the slot mask
171 *********************************/
172 FirstSupported = first_device_num;
173 LastSupported = FirstSupported + num_ctlr_slots - 1;
174 } else {
175 FirstSupported = 0;
176 LastSupported = 0x1F;
177 }
178
179 dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported,
180 LastSupported);
181
182 /* Save PCI configuration space for all devices in supported slots */
183 dbg("%s: pci_bus->number = %x\n", __FUNCTION__, pci_bus->number);
184 pci_bus->number = busnumber;
185 dbg("%s: bus = %x, dev = %x\n", __FUNCTION__, busnumber, device);
186 for (device = FirstSupported; device <= LastSupported; device++) {
187 ID = 0xFFFFFFFF;
188 rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0),
189 PCI_VENDOR_ID, &ID);
190
191 if (ID != 0xFFFFFFFF) { /* device in slot */
192 dbg("%s: ID = %x\n", __FUNCTION__, ID);
193 rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
194 0x0B, &class_code);
195 if (rc)
196 return rc;
197
198 rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
199 PCI_HEADER_TYPE, &header_type);
200 if (rc)
201 return rc;
202
203 dbg("class_code = %x, header_type = %x\n", class_code, header_type);
204
205 /* If multi-function device, set max_functions to 8 */
206 if (header_type & 0x80)
207 max_functions = 8;
208 else
209 max_functions = 1;
210
211 function = 0;
212
213 do {
214 DevError = 0;
215 dbg("%s: In do loop\n", __FUNCTION__);
216
217 if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* P-P Bridge */
218 /* Recurse the subordinate bus
219 * get the subordinate bus number
220 */
221 rc = pci_bus_read_config_byte(pci_bus,
222 PCI_DEVFN(device, function),
223 PCI_SECONDARY_BUS, &secondary_bus);
224 if (rc) {
225 return rc;
226 } else {
227 sub_bus = (int) secondary_bus;
228
229 /* Save secondary bus cfg spc with this recursive call. */
230 rc = pciehp_save_config(ctrl, sub_bus, 0, 0);
231 if (rc)
232 return rc;
233 }
234 }
235
236 index = 0;
237 new_slot = pciehp_slot_find(busnumber, device, index++);
238
239 dbg("%s: new_slot = %p bus %x dev %x fun %x\n",
240 __FUNCTION__, new_slot, busnumber, device, index-1);
241
242 while (new_slot && (new_slot->function != (u8) function)) {
243 new_slot = pciehp_slot_find(busnumber, device, index++);
244 dbg("%s: while loop, new_slot = %p bus %x dev %x fun %x\n",
245 __FUNCTION__, new_slot, busnumber, device, index-1);
246 }
247 if (!new_slot) {
248 /* Setup slot structure. */
249 new_slot = pciehp_slot_create(busnumber);
250 dbg("%s: if, new_slot = %p bus %x dev %x fun %x\n",
251 __FUNCTION__, new_slot, busnumber, device, function);
252
253 if (new_slot == NULL)
254 return(1);
255 }
256
257 new_slot->bus = (u8) busnumber;
258 new_slot->device = (u8) device;
259 new_slot->function = (u8) function;
260 new_slot->is_a_board = 1;
261 new_slot->switch_save = 0x10;
262 /* In case of unsupported board */
263 new_slot->status = DevError;
264 new_slot->pci_dev = pci_find_slot(new_slot->bus,
265 (new_slot->device << 3) | new_slot->function);
266 dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev);
267
268 for (cloop = 0; cloop < 0x20; cloop++) {
269 rc = pci_bus_read_config_dword(pci_bus,
270 PCI_DEVFN(device, function),
271 cloop << 2,
272 (u32 *) &(new_slot->config_space [cloop]));
273 /* dbg("new_slot->config_space[%x] = %x\n",
274 cloop, new_slot->config_space[cloop]); */
275 if (rc)
276 return rc;
277 }
278
279 function++;
280
281 stop_it = 0;
282
283 /* this loop skips to the next present function
284 * reading in Class Code and Header type.
285 */
286
287 while ((function < max_functions)&&(!stop_it)) {
288 dbg("%s: In while loop \n", __FUNCTION__);
289 rc = pci_bus_read_config_dword(pci_bus,
290 PCI_DEVFN(device, function),
291 PCI_VENDOR_ID, &ID);
292
293 if (ID == 0xFFFFFFFF) { /* nothing there. */
294 function++;
295 dbg("Nothing there\n");
296 } else { /* Something there */
297 rc = pci_bus_read_config_byte(pci_bus,
298 PCI_DEVFN(device, function),
299 0x0B, &class_code);
300 if (rc)
301 return rc;
302
303 rc = pci_bus_read_config_byte(pci_bus,
304 PCI_DEVFN(device, function),
305 PCI_HEADER_TYPE, &header_type);
306 if (rc)
307 return rc;
308
309 dbg("class_code = %x, header_type = %x\n", class_code, header_type);
310 stop_it++;
311 }
312 }
313
314 } while (function < max_functions);
315 /* End of IF (device in slot?) */
316 } else if (is_hot_plug) {
317 /* Setup slot structure with entry for empty slot */
318 new_slot = pciehp_slot_create(busnumber);
319
320 if (new_slot == NULL) {
321 return(1);
322 }
323 dbg("new_slot = %p, bus = %x, dev = %x, fun = %x\n", new_slot,
324 new_slot->bus, new_slot->device, new_slot->function);
325
326 new_slot->bus = (u8) busnumber;
327 new_slot->device = (u8) device;
328 new_slot->function = 0;
329 new_slot->is_a_board = 0;
330 new_slot->presence_save = 0;
331 new_slot->switch_save = 0;
332 }
333 } /* End of FOR loop */
334
335 dbg("%s: Exit\n", __FUNCTION__);
336 return(0);
337}
338
339
340/*
341 * pciehp_save_slot_config
342 *
343 * Saves configuration info for all PCI devices in a given slot
344 * including subordinate busses.
345 *
346 * returns 0 if success
347 */
348int pciehp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot)
349{
350 int rc;
351 u8 class_code;
352 u8 header_type;
353 u32 ID;
354 u8 secondary_bus;
355 int sub_bus;
356 int max_functions;
357 int function;
358 int cloop = 0;
359 int stop_it;
360 struct pci_bus lpci_bus, *pci_bus;
361 memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
362 pci_bus = &lpci_bus;
363 pci_bus->number = new_slot->bus;
364
365 ID = 0xFFFFFFFF;
366
367 pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0),
368 PCI_VENDOR_ID, &ID);
369
370 if (ID != 0xFFFFFFFF) { /* device in slot */
371 pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
372 0x0B, &class_code);
373
374 pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
375 PCI_HEADER_TYPE, &header_type);
376
377 if (header_type & 0x80) /* Multi-function device */
378 max_functions = 8;
379 else
380 max_functions = 1;
381
382 function = 0;
383
384 do {
385 if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
386 /* Recurse the subordinate bus */
387 pci_bus_read_config_byte(pci_bus,
388 PCI_DEVFN(new_slot->device, function),
389 PCI_SECONDARY_BUS, &secondary_bus);
390
391 sub_bus = (int) secondary_bus;
392
393 /* Save the config headers for the secondary bus. */
394 rc = pciehp_save_config(ctrl, sub_bus, 0, 0);
395
396 if (rc)
397 return rc;
398
399 } /* End of IF */
400
401 new_slot->status = 0;
402
403 for (cloop = 0; cloop < 0x20; cloop++) {
404 pci_bus_read_config_dword(pci_bus,
405 PCI_DEVFN(new_slot->device, function),
406 cloop << 2,
407 (u32 *) &(new_slot->config_space [cloop]));
408 }
409
410 function++;
411
412 stop_it = 0;
413
414 /* this loop skips to the next present function
415 * reading in the Class Code and the Header type.
416 */
417
418 while ((function < max_functions) && (!stop_it)) {
419 pci_bus_read_config_dword(pci_bus,
420 PCI_DEVFN(new_slot->device, function),
421 PCI_VENDOR_ID, &ID);
422
423 if (ID == 0xFFFFFFFF) { /* nothing there. */
424 function++;
425 } else { /* Something there */
426 pci_bus_read_config_byte(pci_bus,
427 PCI_DEVFN(new_slot->device, function),
428 0x0B, &class_code);
429
430 pci_bus_read_config_byte(pci_bus,
431 PCI_DEVFN(new_slot->device, function),
432 PCI_HEADER_TYPE, &header_type);
433
434 stop_it++;
435 }
436 }
437
438 } while (function < max_functions);
439 } /* End of IF (device in slot?) */
440 else {
441 return 2;
442 }
443
444 return 0;
445}
446