[PATCH] shpchp: dont save PCI config for hotplug slots/devices
[firefly-linux-kernel-4.4.55.git] / drivers / pci / hotplug / shpchp_ctrl.c
1 /*
2  * Standard Hot Plug Controller Driver
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 #include <linux/config.h>
31 #include <linux/module.h>
32 #include <linux/kernel.h>
33 #include <linux/types.h>
34 #include <linux/slab.h>
35 #include <linux/workqueue.h>
36 #include <linux/interrupt.h>
37 #include <linux/delay.h>
38 #include <linux/wait.h>
39 #include <linux/smp_lock.h>
40 #include <linux/pci.h>
41 #include "../pci.h"
42 #include "shpchp.h"
43
44 static void interrupt_event_handler(struct controller *ctrl);
45
46 static struct semaphore event_semaphore;        /* mutex for process loop (up if something to process) */
47 static struct semaphore event_exit;             /* guard ensure thread has exited before calling it quits */
48 static int event_finished;
49 static unsigned long pushbutton_pending;        /* = 0 */
50
51 u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id)
52 {
53         struct controller *ctrl = (struct controller *) inst_id;
54         struct slot *p_slot;
55         u8 rc = 0;
56         u8 getstatus;
57         struct pci_func *func;
58         struct event_info *taskInfo;
59
60         /* Attention Button Change */
61         dbg("shpchp:  Attention button interrupt received.\n");
62         
63         func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
64
65         /* This is the structure that tells the worker thread what to do */
66         taskInfo = &(ctrl->event_queue[ctrl->next_event]);
67         p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
68
69         p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
70         p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
71         
72         ctrl->next_event = (ctrl->next_event + 1) % 10;
73         taskInfo->hp_slot = hp_slot;
74
75         rc++;
76
77         /*
78          *  Button pressed - See if need to TAKE ACTION!!!
79          */
80         info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot);
81         taskInfo->event_type = INT_BUTTON_PRESS;
82
83         if ((p_slot->state == BLINKINGON_STATE)
84             || (p_slot->state == BLINKINGOFF_STATE)) {
85                 /* Cancel if we are still blinking; this means that we press the
86                  * attention again before the 5 sec. limit expires to cancel hot-add
87                  * or hot-remove
88                  */
89                 taskInfo->event_type = INT_BUTTON_CANCEL;
90                 info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot);
91         } else if ((p_slot->state == POWERON_STATE)
92                    || (p_slot->state == POWEROFF_STATE)) {
93                 /* Ignore if the slot is on power-on or power-off state; this 
94                  * means that the previous attention button action to hot-add or
95                  * hot-remove is undergoing
96                  */
97                 taskInfo->event_type = INT_BUTTON_IGNORE;
98                 info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot);
99         }
100
101         if (rc)
102                 up(&event_semaphore);   /* signal event thread that new event is posted */
103
104         return 0;
105
106 }
107
108 u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
109 {
110         struct controller *ctrl = (struct controller *) inst_id;
111         struct slot *p_slot;
112         u8 rc = 0;
113         u8 getstatus;
114         struct pci_func *func;
115         struct event_info *taskInfo;
116
117         /* Switch Change */
118         dbg("shpchp:  Switch interrupt received.\n");
119
120         func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
121
122         /* This is the structure that tells the worker thread
123          * what to do
124          */
125         taskInfo = &(ctrl->event_queue[ctrl->next_event]);
126         ctrl->next_event = (ctrl->next_event + 1) % 10;
127         taskInfo->hp_slot = hp_slot;
128
129         rc++;
130         p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
131         p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
132         p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
133         dbg("%s: Card present %x Power status %x\n", __FUNCTION__,
134                 func->presence_save, func->pwr_save);
135
136         if (getstatus) {
137                 /*
138                  * Switch opened
139                  */
140                 info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
141                 func->switch_save = 0;
142                 taskInfo->event_type = INT_SWITCH_OPEN;
143                 if (func->pwr_save && func->presence_save) {
144                         taskInfo->event_type = INT_POWER_FAULT;
145                         err("Surprise Removal of card\n");
146                 }
147         } else {
148                 /*
149                  *  Switch closed
150                  */
151                 info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
152                 func->switch_save = 0x10;
153                 taskInfo->event_type = INT_SWITCH_CLOSE;
154         }
155
156         if (rc)
157                 up(&event_semaphore);   /* signal event thread that new event is posted */
158
159         return rc;
160 }
161
162 u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id)
163 {
164         struct controller *ctrl = (struct controller *) inst_id;
165         struct slot *p_slot;
166         u8 rc = 0;
167         /*u8 temp_byte;*/
168         struct pci_func *func;
169         struct event_info *taskInfo;
170
171         /* Presence Change */
172         dbg("shpchp:  Presence/Notify input change.\n");
173
174         func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
175
176         /* This is the structure that tells the worker thread
177          * what to do
178          */
179         taskInfo = &(ctrl->event_queue[ctrl->next_event]);
180         ctrl->next_event = (ctrl->next_event + 1) % 10;
181         taskInfo->hp_slot = hp_slot;
182
183         rc++;
184         p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
185
186         /* 
187          * Save the presence state
188          */
189         p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
190         if (func->presence_save) {
191                 /*
192                  * Card Present
193                  */
194                 info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot);
195                 taskInfo->event_type = INT_PRESENCE_ON;
196         } else {
197                 /*
198                  * Not Present
199                  */
200                 info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot);
201                 taskInfo->event_type = INT_PRESENCE_OFF;
202         }
203
204         if (rc)
205                 up(&event_semaphore);   /* signal event thread that new event is posted */
206
207         return rc;
208 }
209
210 u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
211 {
212         struct controller *ctrl = (struct controller *) inst_id;
213         struct slot *p_slot;
214         u8 rc = 0;
215         struct pci_func *func;
216         struct event_info *taskInfo;
217
218         /* Power fault */
219         dbg("shpchp:  Power fault interrupt received.\n");
220
221         func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
222
223         /* This is the structure that tells the worker thread
224          * what to do
225          */
226         taskInfo = &(ctrl->event_queue[ctrl->next_event]);
227         ctrl->next_event = (ctrl->next_event + 1) % 10;
228         taskInfo->hp_slot = hp_slot;
229
230         rc++;
231         p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
232
233         if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) {
234                 /*
235                  * Power fault Cleared
236                  */
237                 info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
238                 func->status = 0x00;
239                 taskInfo->event_type = INT_POWER_FAULT_CLEAR;
240         } else {
241                 /*
242                  *   Power fault
243                  */
244                 info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
245                 taskInfo->event_type = INT_POWER_FAULT;
246                 /* set power fault status for this board */
247                 func->status = 0xFF;
248                 info("power fault bit %x set\n", hp_slot);
249         }
250         if (rc)
251                 up(&event_semaphore);   /* signal event thread that new event is posted */
252
253         return rc;
254 }
255
256 /**
257  * shpchp_slot_create - Creates a node and adds it to the proper bus.
258  * @busnumber - bus where new node is to be located
259  *
260  * Returns pointer to the new node or NULL if unsuccessful
261  */
262 struct pci_func *shpchp_slot_create(u8 busnumber)
263 {
264         struct pci_func *new_slot;
265         struct pci_func *next;
266
267         new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL);
268
269         if (new_slot == NULL) {
270                 return(new_slot);
271         }
272
273         memset(new_slot, 0, sizeof(struct pci_func));
274
275         new_slot->next = NULL;
276         new_slot->configured = 1;
277
278         if (shpchp_slot_list[busnumber] == NULL) {
279                 shpchp_slot_list[busnumber] = new_slot;
280         } else {
281                 next = shpchp_slot_list[busnumber];
282                 while (next->next != NULL)
283                         next = next->next;
284                 next->next = new_slot;
285         }
286         return(new_slot);
287 }
288
289
290 /*
291  * slot_remove - Removes a node from the linked list of slots.
292  * @old_slot: slot to remove
293  *
294  * Returns 0 if successful, !0 otherwise.
295  */
296 static int slot_remove(struct pci_func * old_slot)
297 {
298         struct pci_func *next;
299
300         if (old_slot == NULL)
301                 return(1);
302
303         next = shpchp_slot_list[old_slot->bus];
304
305         if (next == NULL) {
306                 return(1);
307         }
308
309         if (next == old_slot) {
310                 shpchp_slot_list[old_slot->bus] = old_slot->next;
311                 kfree(old_slot);
312                 return(0);
313         }
314
315         while ((next->next != old_slot) && (next->next != NULL)) {
316                 next = next->next;
317         }
318
319         if (next->next == old_slot) {
320                 next->next = old_slot->next;
321                 kfree(old_slot);
322                 return(0);
323         } else
324                 return(2);
325 }
326
327
328 /**
329  * bridge_slot_remove - Removes a node from the linked list of slots.
330  * @bridge: bridge to remove
331  * @secondaryBus: secondary PCI bus number for bridge being removed
332  * @subordinateBus: subordinate PCI bus number for bridge being removed
333  *
334  * Returns 0 if successful, !0 otherwise.
335  */
336 static int bridge_slot_remove(struct pci_func *bridge, u8 secondaryBus,
337                 u8 subordinateBus)
338 {
339         u8 tempBus;
340         struct pci_func *next;
341
342         if (bridge == NULL)
343                 return(1);
344
345         for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {
346                 next = shpchp_slot_list[tempBus];
347
348                 while (!slot_remove(next)) {
349                         next = shpchp_slot_list[tempBus];
350                 }
351         }
352
353         next = shpchp_slot_list[bridge->bus];
354
355         if (next == NULL) {
356                 return(1);
357         }
358
359         if (next == bridge) {
360                 shpchp_slot_list[bridge->bus] = bridge->next;
361                 kfree(bridge);
362                 return(0);
363         }
364
365         while ((next->next != bridge) && (next->next != NULL)) {
366                 next = next->next;
367         }
368
369         if (next->next == bridge) {
370                 next->next = bridge->next;
371                 kfree(bridge);
372                 return(0);
373         } else
374                 return(2);
375 }
376
377
378 /**
379  * shpchp_slot_find - Looks for a node by bus, and device, multiple functions accessed
380  * @bus: bus to find
381  * @device: device to find
382  * @index: is 0 for first function found, 1 for the second...
383  *
384  * Returns pointer to the node if successful, %NULL otherwise.
385  */
386 struct pci_func *shpchp_slot_find(u8 bus, u8 device, u8 index)
387 {
388         int found = -1;
389         struct pci_func *func;
390
391         func = shpchp_slot_list[bus];
392
393         if ((func == NULL) || ((func->device == device) && (index == 0)))
394                 return(func);
395
396         if (func->device == device)
397                 found++;
398
399         while (func->next != NULL) {
400                 func = func->next;
401
402                 if (func->device == device)
403                         found++;
404
405                 if (found == index)
406                         return(func);
407         }
408
409         return(NULL);
410 }
411
412 static int is_bridge(struct pci_func *func, struct controller *ctrl)
413 {
414         u8 hdr_type;
415         struct pci_bus *bus = ctrl->pci_dev->subordinate;
416
417         /*
418          * Note: device may have just been hot-added and not yet scanned
419          * by the pci core, so its pci_dev structure may not exist yet
420          */
421         pci_bus_read_config_byte(bus, PCI_DEVFN(func->device, func->function),
422                         PCI_HEADER_TYPE, &hdr_type);
423         if ((hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE)
424                 return 1;
425         else
426                 return 0;
427 }
428
429 /* The following routines constitute the bulk of the 
430    hotplug controller logic
431  */
432 static u32 change_bus_speed(struct controller *ctrl, struct slot *p_slot, enum pci_bus_speed speed)
433
434         u32 rc = 0;
435
436         dbg("%s: change to speed %d\n", __FUNCTION__, speed);
437         down(&ctrl->crit_sect);
438         if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) {
439                 err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
440                 up(&ctrl->crit_sect);
441                 return WRONG_BUS_FREQUENCY;
442         }
443         wait_for_ctrl_irq (ctrl);
444                 
445         if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
446                 err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
447                           __FUNCTION__);
448                 err("%s: Error code (%d)\n", __FUNCTION__, rc);
449                 up(&ctrl->crit_sect);
450                 return WRONG_BUS_FREQUENCY;
451         }
452         up(&ctrl->crit_sect);
453         return rc;
454 }
455
456 static u32 fix_bus_speed(struct controller *ctrl, struct slot *pslot, u8 flag, 
457 enum pci_bus_speed asp, enum pci_bus_speed bsp, enum pci_bus_speed msp)
458
459         u32 rc = 0;
460         
461         if (flag != 0) { /* Other slots on the same bus are occupied */
462                 if ( asp < bsp ) {
463                         err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bsp, asp);
464                         return WRONG_BUS_FREQUENCY;
465                 }
466         } else {
467                 /* Other slots on the same bus are empty */
468                 if (msp == bsp) {
469                 /* if adapter_speed >= bus_speed, do nothing */
470                         if (asp < bsp) {
471                                 /* 
472                                 * Try to lower bus speed to accommodate the adapter if other slots 
473                                 * on the same controller are empty
474                                 */
475                                 if ((rc = change_bus_speed(ctrl, pslot, asp)))
476                                         return rc;
477                         } 
478                 } else {
479                         if (asp < msp) {
480                                 if ((rc = change_bus_speed(ctrl, pslot, asp)))
481                                         return rc;
482                         } else {
483                                 if ((rc = change_bus_speed(ctrl, pslot, msp)))
484                                         return rc;
485                         }
486                 }
487         }
488         return rc;
489 }
490
491 /**
492  * board_added - Called after a board has been added to the system.
493  *
494  * Turns power on for the board
495  * Configures board
496  *
497  */
498 static u32 board_added(struct pci_func * func, struct controller * ctrl)
499 {
500         u8 hp_slot;
501         u8 slots_not_empty = 0;
502         u32 rc = 0;
503         struct slot *p_slot;
504         enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed;
505         u8 pi, mode;
506
507         p_slot = shpchp_find_slot(ctrl, func->device);
508         hp_slot = func->device - ctrl->slot_device_offset;
509
510         dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
511
512         /* Wait for exclusive access to hardware */
513         down(&ctrl->crit_sect);
514
515         /* Power on slot without connecting to bus */
516         rc = p_slot->hpc_ops->power_on_slot(p_slot);
517         if (rc) {
518                 err("%s: Failed to power on slot\n", __FUNCTION__);
519                 /* Done with exclusive hardware access */
520                 up(&ctrl->crit_sect);
521                 return -1;
522         }
523                         
524         /* Wait for the command to complete */
525         wait_for_ctrl_irq (ctrl);
526         
527         rc = p_slot->hpc_ops->check_cmd_status(ctrl);
528         if (rc) {
529                 err("%s: Failed to power on slot, error code(%d)\n", __FUNCTION__, rc);
530                 /* Done with exclusive hardware access */
531                 up(&ctrl->crit_sect);
532                 return -1;
533         }
534
535         
536         if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) {
537                 if (slots_not_empty)
538                         return WRONG_BUS_FREQUENCY;
539                 
540                 if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) {
541                         err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
542                         up(&ctrl->crit_sect);
543                         return WRONG_BUS_FREQUENCY;
544                 }
545                 wait_for_ctrl_irq (ctrl);
546                 
547                 if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
548                         err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
549                                   __FUNCTION__);
550                         err("%s: Error code (%d)\n", __FUNCTION__, rc);
551                         up(&ctrl->crit_sect);
552                         return WRONG_BUS_FREQUENCY;
553                 }
554                 /* turn on board, blink green LED, turn off Amber LED */
555                 if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {
556                         err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
557                         up(&ctrl->crit_sect);
558                         return rc;
559                 }
560                 wait_for_ctrl_irq (ctrl);
561
562                 if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
563                         err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc);
564                         up(&ctrl->crit_sect);
565                         return rc;  
566                 }
567         }
568  
569         rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed);
570         /* 0 = PCI 33Mhz, 1 = PCI 66 Mhz, 2 = PCI-X 66 PA, 4 = PCI-X 66 ECC, */
571         /* 5 = PCI-X 133 PA, 7 = PCI-X 133 ECC,  0xa = PCI-X 133 Mhz 266, */
572         /* 0xd = PCI-X 133 Mhz 533 */
573         /* This encoding is different from the one used in cur_bus_speed & */
574         /* max_bus_speed */
575
576         if (rc  || adapter_speed == PCI_SPEED_UNKNOWN) {
577                 err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__);
578                 /* Done with exclusive hardware access */
579                 up(&ctrl->crit_sect);
580                 return WRONG_BUS_FREQUENCY;
581         }
582
583         rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bus_speed);
584         if (rc || bus_speed == PCI_SPEED_UNKNOWN) {
585                 err("%s: Can't get bus operation speed\n", __FUNCTION__);
586                 /* Done with exclusive hardware access */
587                 up(&ctrl->crit_sect);
588                 return WRONG_BUS_FREQUENCY;
589         }
590
591         rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &max_bus_speed);
592         if (rc || max_bus_speed == PCI_SPEED_UNKNOWN) {
593                 err("%s: Can't get max bus operation speed\n", __FUNCTION__);
594                 max_bus_speed = bus_speed;
595         }
596
597         /* Done with exclusive hardware access */
598         up(&ctrl->crit_sect);
599
600         if ((rc  = p_slot->hpc_ops->get_prog_int(p_slot, &pi))) {
601                 err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__);
602                 pi = 1;
603         }
604
605         /* Check if there are other slots or devices on the same bus */
606         if (!list_empty(&ctrl->pci_dev->subordinate->devices))
607                 slots_not_empty = 1;
608
609         dbg("%s: slots_not_empty %d, pi %d\n", __FUNCTION__, 
610                 slots_not_empty, pi);
611         dbg("adapter_speed %d, bus_speed %d, max_bus_speed %d\n", 
612                 adapter_speed, bus_speed, max_bus_speed);
613
614         if (pi == 2) {
615                 dbg("%s: In PI = %d\n", __FUNCTION__, pi);
616                 if ((rc = p_slot->hpc_ops->get_mode1_ECC_cap(p_slot, &mode))) {
617                         err("%s: Can't get Mode1_ECC, set mode to 0\n", __FUNCTION__);
618                         mode = 0;
619                 }
620
621                 switch (adapter_speed) {
622                 case PCI_SPEED_133MHz_PCIX_533:
623                 case PCI_SPEED_133MHz_PCIX_266:
624                         if ((bus_speed != adapter_speed) &&
625                            ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) 
626                                 return rc;
627                         break;  
628                 case PCI_SPEED_133MHz_PCIX_ECC:
629                 case PCI_SPEED_133MHz_PCIX:
630                         if (mode) { /* Bus - Mode 1 ECC */
631                                 if ((bus_speed != 0x7) &&
632                                    ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) 
633                                         return rc;
634                         } else {
635                                 if ((bus_speed != 0x4) &&
636                                    ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) 
637                                         return rc;
638                         }
639                         break;
640                 case PCI_SPEED_66MHz_PCIX_ECC:
641                 case PCI_SPEED_66MHz_PCIX:
642                         if (mode) { /* Bus - Mode 1 ECC */
643                                 if ((bus_speed != 0x5) &&
644                                    ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) 
645                                         return rc;
646                         } else {
647                                 if ((bus_speed != 0x2) &&
648                                    ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) 
649                                         return rc;
650                         }
651                         break;
652                 case PCI_SPEED_66MHz:
653                         if ((bus_speed != 0x1) &&
654                            ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) 
655                                 return rc;
656                         break;  
657                 case PCI_SPEED_33MHz:
658                         if (bus_speed > 0x0) {
659                                 if (slots_not_empty == 0) {
660                                         if ((rc = change_bus_speed(ctrl, p_slot, adapter_speed)))
661                                                 return rc;
662                                 } else {
663                                         err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
664                                         return WRONG_BUS_FREQUENCY;
665                                 }
666                         }
667                         break;
668                 default:
669                         err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
670                         return WRONG_BUS_FREQUENCY;
671                 }
672         } else {
673                 /* If adpater_speed == bus_speed, nothing to do here */
674                 dbg("%s: In PI = %d\n", __FUNCTION__, pi);
675                 if ((adapter_speed != bus_speed) &&
676                    ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed))))
677                                 return rc;
678         }
679
680         down(&ctrl->crit_sect);
681         /* turn on board, blink green LED, turn off Amber LED */
682         if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {
683                 err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
684                 up(&ctrl->crit_sect);
685                 return rc;
686         }
687         wait_for_ctrl_irq (ctrl);
688
689         if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
690                 err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc);
691                 up(&ctrl->crit_sect);
692                 return rc;  
693         }
694
695         up(&ctrl->crit_sect);
696
697         /* Wait for ~1 second */
698         dbg("%s: before long_delay\n", __FUNCTION__);
699         wait_for_ctrl_irq (ctrl);
700         dbg("%s: after long_delay\n", __FUNCTION__);
701
702         dbg("%s: func status = %x\n", __FUNCTION__, func->status);
703         /* Check for a power fault */
704         if (func->status == 0xFF) {
705                 /* power fault occurred, but it was benign */
706                 dbg("%s: power fault\n", __FUNCTION__);
707                 rc = POWER_FAILURE;
708                 func->status = 0;
709                 goto err_exit;
710         }
711
712         if (shpchp_configure_device(p_slot)) {
713                 err("Cannot add device at 0x%x:0x%x\n", p_slot->bus,
714                                 p_slot->device);
715                 goto err_exit;
716         }
717
718         func->status = 0;
719         func->switch_save = 0x10;
720         func->is_a_board = 0x01;
721         func->pwr_save = 1;
722
723         /* Wait for exclusive access to hardware */
724         down(&ctrl->crit_sect);
725
726         p_slot->hpc_ops->green_led_on(p_slot);
727
728         /* Wait for the command to complete */
729         wait_for_ctrl_irq (ctrl);
730
731         /* Done with exclusive hardware access */
732         up(&ctrl->crit_sect);
733
734         return 0;
735
736 err_exit:
737         /* Wait for exclusive access to hardware */
738         down(&ctrl->crit_sect);
739
740         /* turn off slot, turn on Amber LED, turn off Green LED */
741         rc = p_slot->hpc_ops->slot_disable(p_slot);
742         if (rc) {
743                 err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
744                 /* Done with exclusive hardware access */
745                 up(&ctrl->crit_sect);
746                 return rc;
747         }
748         /* Wait for the command to complete */
749         wait_for_ctrl_irq (ctrl);
750
751         rc = p_slot->hpc_ops->check_cmd_status(ctrl);
752         if (rc) {
753                 err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc);
754                 /* Done with exclusive hardware access */
755                 up(&ctrl->crit_sect);
756                 return rc;
757         }
758
759         /* Done with exclusive hardware access */
760         up(&ctrl->crit_sect);
761
762         return(rc);
763 }
764
765
766 /**
767  * remove_board - Turns off slot and LED's
768  *
769  */
770 static u32 remove_board(struct pci_func *func, struct controller *ctrl)
771 {
772         u8 device;
773         u8 hp_slot;
774         u32 rc;
775         struct slot *p_slot;
776         u8 secondary = 0, subordinate = 0;
777         int remove_bridge;
778
779         if (func == NULL)
780                 return(1);
781
782         if ((remove_bridge = is_bridge(func, ctrl))) {
783                 /* Stash away bus information before we destroy it */
784                 secondary = func->pci_dev->subordinate->secondary;
785                 subordinate = func->pci_dev->subordinate->subordinate;
786         }
787
788         if (shpchp_unconfigure_device(func))
789                 return(1);
790
791         device = func->device;
792
793         hp_slot = func->device - ctrl->slot_device_offset;
794         p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
795
796         dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
797
798         /* Change status to shutdown */
799         if (func->is_a_board)
800                 func->status = 0x01;
801         func->configured = 0;
802
803         /* Wait for exclusive access to hardware */
804         down(&ctrl->crit_sect);
805
806         /* turn off slot, turn on Amber LED, turn off Green LED */
807         rc = p_slot->hpc_ops->slot_disable(p_slot);
808         if (rc) {
809                 err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
810                 /* Done with exclusive hardware access */
811                 up(&ctrl->crit_sect);
812                 return rc;
813         }
814         /* Wait for the command to complete */
815         wait_for_ctrl_irq (ctrl);
816
817         rc = p_slot->hpc_ops->check_cmd_status(ctrl);
818         if (rc) {
819                 err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc);
820                 /* Done with exclusive hardware access */
821                 up(&ctrl->crit_sect);
822                 return rc;  
823         }
824         
825         rc = p_slot->hpc_ops->set_attention_status(p_slot, 0);
826         if (rc) {
827                 err("%s: Issue of Set Attention command failed\n", __FUNCTION__);
828                 /* Done with exclusive hardware access */
829                 up(&ctrl->crit_sect);
830                 return rc;
831         }
832         /* Wait for the command to complete */
833         wait_for_ctrl_irq (ctrl);
834
835         /* Done with exclusive hardware access */
836         up(&ctrl->crit_sect);
837
838         if (ctrl->add_support) {
839                 while (func) {
840                         if (remove_bridge) {
841                                 dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, 
842                                         func->device, func->function);
843                                 bridge_slot_remove(func, secondary,
844                                                 subordinate);
845                         } else
846                                 dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, 
847                                         func->device, func->function);
848                                 slot_remove(func);
849
850                         func = shpchp_slot_find(ctrl->slot_bus, device, 0);
851                 }
852
853                 /* Setup slot structure with entry for empty slot */
854                 func = shpchp_slot_create(ctrl->slot_bus);
855
856                 if (func == NULL) {
857                         return(1);
858                 }
859
860                 func->bus = ctrl->slot_bus;
861                 func->device = device;
862                 func->function = 0;
863                 func->configured = 0;
864                 func->switch_save = 0x10;
865                 func->pwr_save = 0;
866                 func->is_a_board = 0;
867         }
868
869         return 0;
870 }
871
872
873 static void pushbutton_helper_thread (unsigned long data)
874 {
875         pushbutton_pending = data;
876
877         up(&event_semaphore);
878 }
879
880
881 /**
882  * shpchp_pushbutton_thread
883  *
884  * Scheduled procedure to handle blocking stuff for the pushbuttons
885  * Handles all pending events and exits.
886  *
887  */
888 static void shpchp_pushbutton_thread (unsigned long slot)
889 {
890         struct slot *p_slot = (struct slot *) slot;
891         u8 getstatus;
892         
893         pushbutton_pending = 0;
894
895         if (!p_slot) {
896                 dbg("%s: Error! slot NULL\n", __FUNCTION__);
897                 return;
898         }
899
900         p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
901         if (getstatus) {
902                 p_slot->state = POWEROFF_STATE;
903                 dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
904
905                 shpchp_disable_slot(p_slot);
906                 p_slot->state = STATIC_STATE;
907         } else {
908                 p_slot->state = POWERON_STATE;
909                 dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
910
911                 if (shpchp_enable_slot(p_slot)) {
912                         /* Wait for exclusive access to hardware */
913                         down(&p_slot->ctrl->crit_sect);
914
915                         p_slot->hpc_ops->green_led_off(p_slot);
916
917                         /* Wait for the command to complete */
918                         wait_for_ctrl_irq (p_slot->ctrl);
919
920                         /* Done with exclusive hardware access */
921                         up(&p_slot->ctrl->crit_sect);
922                 }
923                 p_slot->state = STATIC_STATE;
924         }
925
926         return;
927 }
928
929
930 /* this is the main worker thread */
931 static int event_thread(void* data)
932 {
933         struct controller *ctrl;
934         lock_kernel();
935         daemonize("shpchpd_event");
936         unlock_kernel();
937
938         while (1) {
939                 dbg("!!!!event_thread sleeping\n");
940                 down_interruptible (&event_semaphore);
941                 dbg("event_thread woken finished = %d\n", event_finished);
942                 if (event_finished || signal_pending(current))
943                         break;
944                 /* Do stuff here */
945                 if (pushbutton_pending)
946                         shpchp_pushbutton_thread(pushbutton_pending);
947                 else
948                         for (ctrl = shpchp_ctrl_list; ctrl; ctrl=ctrl->next)
949                                 interrupt_event_handler(ctrl);
950         }
951         dbg("event_thread signals exit\n");
952         up(&event_exit);
953         return 0;
954 }
955
956 int shpchp_event_start_thread (void)
957 {
958         int pid;
959
960         /* initialize our semaphores */
961         init_MUTEX_LOCKED(&event_exit);
962         event_finished=0;
963
964         init_MUTEX_LOCKED(&event_semaphore);
965         pid = kernel_thread(event_thread, NULL, 0);
966
967         if (pid < 0) {
968                 err ("Can't start up our event thread\n");
969                 return -1;
970         }
971         dbg("Our event thread pid = %d\n", pid);
972         return 0;
973 }
974
975
976 void shpchp_event_stop_thread (void)
977 {
978         event_finished = 1;
979         dbg("event_thread finish command given\n");
980         up(&event_semaphore);
981         dbg("wait for event_thread to exit\n");
982         down(&event_exit);
983 }
984
985
986 static int update_slot_info (struct slot *slot)
987 {
988         struct hotplug_slot_info *info;
989         int result;
990
991         info = kmalloc(sizeof(*info), GFP_KERNEL);
992         if (!info)
993                 return -ENOMEM;
994
995         slot->hpc_ops->get_power_status(slot, &(info->power_status));
996         slot->hpc_ops->get_attention_status(slot, &(info->attention_status));
997         slot->hpc_ops->get_latch_status(slot, &(info->latch_status));
998         slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status));
999
1000         result = pci_hp_change_slot_info(slot->hotplug_slot, info);
1001         kfree (info);
1002         return result;
1003 }
1004
1005 static void interrupt_event_handler(struct controller *ctrl)
1006 {
1007         int loop = 0;
1008         int change = 1;
1009         struct pci_func *func;
1010         u8 hp_slot;
1011         u8 getstatus;
1012         struct slot *p_slot;
1013
1014         dbg("%s:\n", __FUNCTION__);
1015         while (change) {
1016                 change = 0;
1017
1018                 for (loop = 0; loop < 10; loop++) {
1019                         if (ctrl->event_queue[loop].event_type != 0) {
1020                                 dbg("%s:loop %x event_type %x\n", __FUNCTION__, loop, 
1021                                         ctrl->event_queue[loop].event_type);
1022                                 hp_slot = ctrl->event_queue[loop].hp_slot;
1023
1024                                 func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
1025
1026                                 p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
1027
1028                                 dbg("%s: hp_slot %d, func %p, p_slot %p\n", __FUNCTION__, hp_slot, func, p_slot);
1029
1030                                 if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) {
1031                                         dbg("%s: button cancel\n", __FUNCTION__);
1032                                         del_timer(&p_slot->task_event);
1033
1034                                         switch (p_slot->state) {
1035                                         case BLINKINGOFF_STATE:
1036                                                 /* Wait for exclusive access to hardware */
1037                                                 down(&ctrl->crit_sect);
1038
1039                                                 p_slot->hpc_ops->green_led_on(p_slot);
1040                                                 /* Wait for the command to complete */
1041                                                 wait_for_ctrl_irq (ctrl);
1042
1043                                                 p_slot->hpc_ops->set_attention_status(p_slot, 0);
1044
1045                                                 /* Wait for the command to complete */
1046                                                 wait_for_ctrl_irq (ctrl);
1047
1048                                                 /* Done with exclusive hardware access */
1049                                                 up(&ctrl->crit_sect);
1050                                                 break;
1051                                         case BLINKINGON_STATE:
1052                                                 /* Wait for exclusive access to hardware */
1053                                                 down(&ctrl->crit_sect);
1054
1055                                                 p_slot->hpc_ops->green_led_off(p_slot);
1056                                                 /* Wait for the command to complete */
1057                                                 wait_for_ctrl_irq (ctrl);
1058
1059                                                 p_slot->hpc_ops->set_attention_status(p_slot, 0);
1060                                                 /* Wait for the command to complete */
1061                                                 wait_for_ctrl_irq (ctrl);
1062
1063                                                 /* Done with exclusive hardware access */
1064                                                 up(&ctrl->crit_sect);
1065
1066                                                 break;
1067                                         default:
1068                                                 warn("Not a valid state\n");
1069                                                 return;
1070                                         }
1071                                         info(msg_button_cancel, p_slot->number);
1072                                         p_slot->state = STATIC_STATE;
1073                                 } else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) {
1074                                         /* Button Pressed (No action on 1st press...) */
1075                                         dbg("%s: Button pressed\n", __FUNCTION__);
1076
1077                                         p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
1078                                         if (getstatus) {
1079                                                 /* slot is on */
1080                                                 dbg("%s: slot is on\n", __FUNCTION__);
1081                                                 p_slot->state = BLINKINGOFF_STATE;
1082                                                 info(msg_button_off, p_slot->number);
1083                                         } else {
1084                                                 /* slot is off */
1085                                                 dbg("%s: slot is off\n", __FUNCTION__);
1086                                                 p_slot->state = BLINKINGON_STATE;
1087                                                 info(msg_button_on, p_slot->number);
1088                                         }
1089
1090                                         /* Wait for exclusive access to hardware */
1091                                         down(&ctrl->crit_sect);
1092
1093                                         /* blink green LED and turn off amber */
1094                                         p_slot->hpc_ops->green_led_blink(p_slot);
1095                                         /* Wait for the command to complete */
1096                                         wait_for_ctrl_irq (ctrl);
1097                                         
1098                                         p_slot->hpc_ops->set_attention_status(p_slot, 0);
1099
1100                                         /* Wait for the command to complete */
1101                                         wait_for_ctrl_irq (ctrl);
1102
1103                                         /* Done with exclusive hardware access */
1104                                         up(&ctrl->crit_sect);
1105
1106                                         init_timer(&p_slot->task_event);
1107                                         p_slot->task_event.expires = jiffies + 5 * HZ;   /* 5 second delay */
1108                                         p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
1109                                         p_slot->task_event.data = (unsigned long) p_slot;
1110
1111                                         dbg("%s: add_timer p_slot = %p\n", __FUNCTION__,(void *) p_slot);
1112                                         add_timer(&p_slot->task_event);
1113                                 } else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
1114                                         /***********POWER FAULT********************/
1115                                         dbg("%s: power fault\n", __FUNCTION__);
1116                                         /* Wait for exclusive access to hardware */
1117                                         down(&ctrl->crit_sect);
1118
1119                                         p_slot->hpc_ops->set_attention_status(p_slot, 1);
1120                                         /* Wait for the command to complete */
1121                                         wait_for_ctrl_irq (ctrl);
1122                                         
1123                                         p_slot->hpc_ops->green_led_off(p_slot);
1124                                         /* Wait for the command to complete */
1125                                         wait_for_ctrl_irq (ctrl);
1126
1127                                         /* Done with exclusive hardware access */
1128                                         up(&ctrl->crit_sect);
1129                                 } else {
1130                                         /* refresh notification */
1131                                         if (p_slot)
1132                                                 update_slot_info(p_slot);
1133                                 }
1134
1135                                 ctrl->event_queue[loop].event_type = 0;
1136
1137                                 change = 1;
1138                         }
1139                 }               /* End of FOR loop */
1140         }
1141
1142         return;
1143 }
1144
1145
1146 int shpchp_enable_slot (struct slot *p_slot)
1147 {
1148         u8 getstatus = 0;
1149         int rc;
1150         struct pci_func *func;
1151
1152         func = shpchp_slot_find(p_slot->bus, p_slot->device, 0);
1153         if (!func) {
1154                 dbg("%s: Error! slot NULL\n", __FUNCTION__);
1155                 return -ENODEV;
1156         }
1157
1158         /* Check to see if (latch closed, card present, power off) */
1159         down(&p_slot->ctrl->crit_sect);
1160         rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
1161         if (rc || !getstatus) {
1162                 info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
1163                 up(&p_slot->ctrl->crit_sect);
1164                 return -ENODEV;
1165         }
1166         rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
1167         if (rc || getstatus) {
1168                 info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
1169                 up(&p_slot->ctrl->crit_sect);
1170                 return -ENODEV;
1171         }
1172         rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
1173         if (rc || getstatus) {
1174                 info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
1175                 up(&p_slot->ctrl->crit_sect);
1176                 return -ENODEV;
1177         }
1178         up(&p_slot->ctrl->crit_sect);
1179
1180         slot_remove(func);
1181
1182         func = shpchp_slot_create(p_slot->bus);
1183         if (func == NULL)
1184                 return -ENOMEM;
1185
1186         func->bus = p_slot->bus;
1187         func->device = p_slot->device;
1188         func->function = 0;
1189         func->configured = 0;
1190         func->is_a_board = 1;
1191
1192         /* We have to save the presence info for these slots */
1193         p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
1194         p_slot->hpc_ops->get_power_status(p_slot, &(func->pwr_save));
1195         dbg("%s: func->pwr_save %x\n", __FUNCTION__, func->pwr_save);
1196         p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
1197         func->switch_save = !getstatus? 0x10:0;
1198
1199         rc = board_added(func, p_slot->ctrl);
1200         if (rc) {
1201                 if (is_bridge(func, p_slot->ctrl)) {
1202                         u8 secondary = func->pci_dev->subordinate->secondary;
1203                         u8 subordinate =
1204                                 func->pci_dev->subordinate->subordinate;
1205                         bridge_slot_remove(func, secondary, subordinate);
1206                 } else
1207                         slot_remove(func);
1208
1209                 /* Setup slot structure with entry for empty slot */
1210                 func = shpchp_slot_create(p_slot->bus);
1211                 if (func == NULL)
1212                         return -ENOMEM; /* Out of memory */
1213
1214                 func->bus = p_slot->bus;
1215                 func->device = p_slot->device;
1216                 func->function = 0;
1217                 func->configured = 0;
1218                 func->is_a_board = 1;
1219
1220                 /* We have to save the presence info for these slots */
1221                 p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
1222                 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
1223                 func->switch_save = !getstatus? 0x10:0;
1224         }
1225
1226         if (p_slot)
1227                 update_slot_info(p_slot);
1228
1229         return rc;
1230 }
1231
1232
1233 int shpchp_disable_slot (struct slot *p_slot)
1234 {
1235         u8 class_code, header_type, BCR;
1236         u8 index = 0;
1237         u8 getstatus = 0;
1238         u32 rc = 0;
1239         int ret = 0;
1240         unsigned int devfn;
1241         struct pci_bus *pci_bus;
1242         struct pci_func *func;
1243
1244         if (!p_slot->ctrl)
1245                 return -ENODEV;
1246
1247         pci_bus = p_slot->ctrl->pci_dev->subordinate;
1248
1249         /* Check to see if (latch closed, card present, power on) */
1250         down(&p_slot->ctrl->crit_sect);
1251
1252         ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
1253         if (ret || !getstatus) {
1254                 info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
1255                 up(&p_slot->ctrl->crit_sect);
1256                 return -ENODEV;
1257         }
1258         ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
1259         if (ret || getstatus) {
1260                 info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
1261                 up(&p_slot->ctrl->crit_sect);
1262                 return -ENODEV;
1263         }
1264         ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
1265         if (ret || !getstatus) {
1266                 info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
1267                 up(&p_slot->ctrl->crit_sect);
1268                 return -ENODEV;
1269         }
1270         up(&p_slot->ctrl->crit_sect);
1271
1272         func = shpchp_slot_find(p_slot->bus, p_slot->device, index++);
1273
1274         /* Make sure there are no video controllers here
1275          * for all func of p_slot
1276          */
1277         while (func && !rc) {
1278                 pci_bus->number = func->bus;
1279                 devfn = PCI_DEVFN(func->device, func->function);
1280
1281                 /* Check the Class Code */
1282                 rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
1283                 if (rc)
1284                         return -ENODEV;
1285
1286                 if (class_code == PCI_BASE_CLASS_DISPLAY) {
1287                         /* Display/Video adapter (not supported) */
1288                         rc = REMOVE_NOT_SUPPORTED;
1289                 } else {
1290                         /* See if it's a bridge */
1291                         rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
1292                         if (rc)
1293                                 return -ENODEV;
1294
1295                         /* If it's a bridge, check the VGA Enable bit */
1296                         if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
1297                                 rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR);
1298                                 if (rc)
1299                                         return -ENODEV;
1300
1301                                 /* If the VGA Enable bit is set, remove isn't supported */
1302                                 if (BCR & PCI_BRIDGE_CTL_VGA) {
1303                                         rc = REMOVE_NOT_SUPPORTED;
1304                                 }
1305                         }
1306                 }
1307
1308                 func = shpchp_slot_find(p_slot->bus, p_slot->device, index++);
1309         }
1310
1311         func = shpchp_slot_find(p_slot->bus, p_slot->device, 0);
1312         if ((func != NULL) && !rc) {
1313                 rc = remove_board(func, p_slot->ctrl);
1314         } else if (!rc)
1315                 rc = -ENODEV;
1316
1317         if (p_slot)
1318                 update_slot_info(p_slot);
1319
1320         return rc;
1321 }
1322