diff options
Diffstat (limited to 'drivers/pci/hotplug/pciehp_ctrl.c')
-rw-r--r-- | drivers/pci/hotplug/pciehp_ctrl.c | 391 |
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 | */ | ||
256 | struct 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 | */ | ||
289 | static 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 | */ | ||
326 | static 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 | */ | ||
379 | struct 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 | |||
421 | static 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 | */ |
475 | static u32 board_added(struct pci_func * func, struct controller * ctrl) | 282 | static 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 | */ |
578 | static u32 remove_board(struct pci_func *func, struct controller *ctrl) | 383 | static 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 | ||
1102 | int pciehp_disable_slot(struct slot *p_slot) | 843 | int 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 | ||