aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/pciehp_ctrl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug/pciehp_ctrl.c')
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c391
1 files changed, 40 insertions, 351 deletions
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