diff options
Diffstat (limited to 'drivers/pci/hotplug/shpchp_ctrl.c')
-rw-r--r-- | drivers/pci/hotplug/shpchp_ctrl.c | 405 |
1 files changed, 40 insertions, 365 deletions
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index c55103f3cebd..b6fde3565e55 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c | |||
@@ -54,19 +54,16 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) | |||
54 | struct slot *p_slot; | 54 | struct slot *p_slot; |
55 | u8 rc = 0; | 55 | u8 rc = 0; |
56 | u8 getstatus; | 56 | u8 getstatus; |
57 | struct pci_func *func; | ||
58 | struct event_info *taskInfo; | 57 | struct event_info *taskInfo; |
59 | 58 | ||
60 | /* Attention Button Change */ | 59 | /* Attention Button Change */ |
61 | dbg("shpchp: Attention button interrupt received.\n"); | 60 | dbg("shpchp: Attention button interrupt received.\n"); |
62 | 61 | ||
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 */ | 62 | /* This is the structure that tells the worker thread what to do */ |
66 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | 63 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); |
67 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 64 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
68 | 65 | ||
69 | p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); | 66 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); |
70 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 67 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
71 | 68 | ||
72 | ctrl->next_event = (ctrl->next_event + 1) % 10; | 69 | ctrl->next_event = (ctrl->next_event + 1) % 10; |
@@ -111,14 +108,11 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
111 | struct slot *p_slot; | 108 | struct slot *p_slot; |
112 | u8 rc = 0; | 109 | u8 rc = 0; |
113 | u8 getstatus; | 110 | u8 getstatus; |
114 | struct pci_func *func; | ||
115 | struct event_info *taskInfo; | 111 | struct event_info *taskInfo; |
116 | 112 | ||
117 | /* Switch Change */ | 113 | /* Switch Change */ |
118 | dbg("shpchp: Switch interrupt received.\n"); | 114 | dbg("shpchp: Switch interrupt received.\n"); |
119 | 115 | ||
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 | 116 | /* This is the structure that tells the worker thread |
123 | * what to do | 117 | * what to do |
124 | */ | 118 | */ |
@@ -128,19 +122,18 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
128 | 122 | ||
129 | rc++; | 123 | rc++; |
130 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 124 | 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)); | 125 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); |
132 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 126 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
133 | dbg("%s: Card present %x Power status %x\n", __FUNCTION__, | 127 | dbg("%s: Card present %x Power status %x\n", __FUNCTION__, |
134 | func->presence_save, func->pwr_save); | 128 | p_slot->presence_save, p_slot->pwr_save); |
135 | 129 | ||
136 | if (getstatus) { | 130 | if (getstatus) { |
137 | /* | 131 | /* |
138 | * Switch opened | 132 | * Switch opened |
139 | */ | 133 | */ |
140 | info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); | 134 | info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); |
141 | func->switch_save = 0; | ||
142 | taskInfo->event_type = INT_SWITCH_OPEN; | 135 | taskInfo->event_type = INT_SWITCH_OPEN; |
143 | if (func->pwr_save && func->presence_save) { | 136 | if (p_slot->pwr_save && p_slot->presence_save) { |
144 | taskInfo->event_type = INT_POWER_FAULT; | 137 | taskInfo->event_type = INT_POWER_FAULT; |
145 | err("Surprise Removal of card\n"); | 138 | err("Surprise Removal of card\n"); |
146 | } | 139 | } |
@@ -149,7 +142,6 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
149 | * Switch closed | 142 | * Switch closed |
150 | */ | 143 | */ |
151 | info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); | 144 | info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); |
152 | func->switch_save = 0x10; | ||
153 | taskInfo->event_type = INT_SWITCH_CLOSE; | 145 | taskInfo->event_type = INT_SWITCH_CLOSE; |
154 | } | 146 | } |
155 | 147 | ||
@@ -165,14 +157,11 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) | |||
165 | struct slot *p_slot; | 157 | struct slot *p_slot; |
166 | u8 rc = 0; | 158 | u8 rc = 0; |
167 | /*u8 temp_byte;*/ | 159 | /*u8 temp_byte;*/ |
168 | struct pci_func *func; | ||
169 | struct event_info *taskInfo; | 160 | struct event_info *taskInfo; |
170 | 161 | ||
171 | /* Presence Change */ | 162 | /* Presence Change */ |
172 | dbg("shpchp: Presence/Notify input change.\n"); | 163 | dbg("shpchp: Presence/Notify input change.\n"); |
173 | 164 | ||
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 | 165 | /* This is the structure that tells the worker thread |
177 | * what to do | 166 | * what to do |
178 | */ | 167 | */ |
@@ -186,8 +175,8 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) | |||
186 | /* | 175 | /* |
187 | * Save the presence state | 176 | * Save the presence state |
188 | */ | 177 | */ |
189 | p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); | 178 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); |
190 | if (func->presence_save) { | 179 | if (p_slot->presence_save) { |
191 | /* | 180 | /* |
192 | * Card Present | 181 | * Card Present |
193 | */ | 182 | */ |
@@ -212,14 +201,11 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
212 | struct controller *ctrl = (struct controller *) inst_id; | 201 | struct controller *ctrl = (struct controller *) inst_id; |
213 | struct slot *p_slot; | 202 | struct slot *p_slot; |
214 | u8 rc = 0; | 203 | u8 rc = 0; |
215 | struct pci_func *func; | ||
216 | struct event_info *taskInfo; | 204 | struct event_info *taskInfo; |
217 | 205 | ||
218 | /* Power fault */ | 206 | /* Power fault */ |
219 | dbg("shpchp: Power fault interrupt received.\n"); | 207 | dbg("shpchp: Power fault interrupt received.\n"); |
220 | 208 | ||
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 | 209 | /* This is the structure that tells the worker thread |
224 | * what to do | 210 | * what to do |
225 | */ | 211 | */ |
@@ -235,7 +221,7 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
235 | * Power fault Cleared | 221 | * Power fault Cleared |
236 | */ | 222 | */ |
237 | info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); | 223 | info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); |
238 | func->status = 0x00; | 224 | p_slot->status = 0x00; |
239 | taskInfo->event_type = INT_POWER_FAULT_CLEAR; | 225 | taskInfo->event_type = INT_POWER_FAULT_CLEAR; |
240 | } else { | 226 | } else { |
241 | /* | 227 | /* |
@@ -244,7 +230,7 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
244 | info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); | 230 | info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); |
245 | taskInfo->event_type = INT_POWER_FAULT; | 231 | taskInfo->event_type = INT_POWER_FAULT; |
246 | /* set power fault status for this board */ | 232 | /* set power fault status for this board */ |
247 | func->status = 0xFF; | 233 | p_slot->status = 0xFF; |
248 | info("power fault bit %x set\n", hp_slot); | 234 | info("power fault bit %x set\n", hp_slot); |
249 | } | 235 | } |
250 | if (rc) | 236 | if (rc) |
@@ -253,179 +239,6 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
253 | return rc; | 239 | return rc; |
254 | } | 240 | } |
255 | 241 | ||
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 | 242 | /* The following routines constitute the bulk of the |
430 | hotplug controller logic | 243 | hotplug controller logic |
431 | */ | 244 | */ |
@@ -495,19 +308,20 @@ enum pci_bus_speed asp, enum pci_bus_speed bsp, enum pci_bus_speed msp) | |||
495 | * Configures board | 308 | * Configures board |
496 | * | 309 | * |
497 | */ | 310 | */ |
498 | static u32 board_added(struct pci_func * func, struct controller * ctrl) | 311 | static u32 board_added(struct slot *p_slot) |
499 | { | 312 | { |
500 | u8 hp_slot; | 313 | u8 hp_slot; |
501 | u8 slots_not_empty = 0; | 314 | u8 slots_not_empty = 0; |
502 | u32 rc = 0; | 315 | u32 rc = 0; |
503 | struct slot *p_slot; | ||
504 | enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed; | 316 | enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed; |
505 | u8 pi, mode; | 317 | u8 pi, mode; |
318 | struct controller *ctrl = p_slot->ctrl; | ||
506 | 319 | ||
507 | p_slot = shpchp_find_slot(ctrl, func->device); | 320 | hp_slot = p_slot->device - ctrl->slot_device_offset; |
508 | hp_slot = func->device - ctrl->slot_device_offset; | ||
509 | 321 | ||
510 | dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); | 322 | dbg("%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n", |
323 | __FUNCTION__, p_slot->device, | ||
324 | ctrl->slot_device_offset, hp_slot); | ||
511 | 325 | ||
512 | /* Wait for exclusive access to hardware */ | 326 | /* Wait for exclusive access to hardware */ |
513 | down(&ctrl->crit_sect); | 327 | down(&ctrl->crit_sect); |
@@ -699,13 +513,13 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) | |||
699 | wait_for_ctrl_irq (ctrl); | 513 | wait_for_ctrl_irq (ctrl); |
700 | dbg("%s: after long_delay\n", __FUNCTION__); | 514 | dbg("%s: after long_delay\n", __FUNCTION__); |
701 | 515 | ||
702 | dbg("%s: func status = %x\n", __FUNCTION__, func->status); | 516 | dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status); |
703 | /* Check for a power fault */ | 517 | /* Check for a power fault */ |
704 | if (func->status == 0xFF) { | 518 | if (p_slot->status == 0xFF) { |
705 | /* power fault occurred, but it was benign */ | 519 | /* power fault occurred, but it was benign */ |
706 | dbg("%s: power fault\n", __FUNCTION__); | 520 | dbg("%s: power fault\n", __FUNCTION__); |
707 | rc = POWER_FAILURE; | 521 | rc = POWER_FAILURE; |
708 | func->status = 0; | 522 | p_slot->status = 0; |
709 | goto err_exit; | 523 | goto err_exit; |
710 | } | 524 | } |
711 | 525 | ||
@@ -715,10 +529,9 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) | |||
715 | goto err_exit; | 529 | goto err_exit; |
716 | } | 530 | } |
717 | 531 | ||
718 | func->status = 0; | 532 | p_slot->status = 0; |
719 | func->switch_save = 0x10; | 533 | p_slot->is_a_board = 0x01; |
720 | func->is_a_board = 0x01; | 534 | p_slot->pwr_save = 1; |
721 | func->pwr_save = 1; | ||
722 | 535 | ||
723 | /* Wait for exclusive access to hardware */ | 536 | /* Wait for exclusive access to hardware */ |
724 | down(&ctrl->crit_sect); | 537 | down(&ctrl->crit_sect); |
@@ -767,38 +580,23 @@ err_exit: | |||
767 | * remove_board - Turns off slot and LED's | 580 | * remove_board - Turns off slot and LED's |
768 | * | 581 | * |
769 | */ | 582 | */ |
770 | static u32 remove_board(struct pci_func *func, struct controller *ctrl) | 583 | static u32 remove_board(struct slot *p_slot) |
771 | { | 584 | { |
772 | u8 device; | 585 | struct controller *ctrl = p_slot->ctrl; |
773 | u8 hp_slot; | 586 | u8 hp_slot; |
774 | u32 rc; | 587 | 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 | 588 | ||
788 | if (shpchp_unconfigure_device(func)) | 589 | if (shpchp_unconfigure_device(p_slot)) |
789 | return(1); | 590 | return(1); |
790 | 591 | ||
791 | device = func->device; | 592 | hp_slot = p_slot->device - ctrl->slot_device_offset; |
792 | |||
793 | hp_slot = func->device - ctrl->slot_device_offset; | ||
794 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 593 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
795 | 594 | ||
796 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); | 595 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); |
797 | 596 | ||
798 | /* Change status to shutdown */ | 597 | /* Change status to shutdown */ |
799 | if (func->is_a_board) | 598 | if (p_slot->is_a_board) |
800 | func->status = 0x01; | 599 | p_slot->status = 0x01; |
801 | func->configured = 0; | ||
802 | 600 | ||
803 | /* Wait for exclusive access to hardware */ | 601 | /* Wait for exclusive access to hardware */ |
804 | down(&ctrl->crit_sect); | 602 | down(&ctrl->crit_sect); |
@@ -835,36 +633,8 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl) | |||
835 | /* Done with exclusive hardware access */ | 633 | /* Done with exclusive hardware access */ |
836 | up(&ctrl->crit_sect); | 634 | up(&ctrl->crit_sect); |
837 | 635 | ||
838 | if (ctrl->add_support) { | 636 | p_slot->pwr_save = 0; |
839 | while (func) { | 637 | p_slot->is_a_board = 0; |
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 | 638 | ||
869 | return 0; | 639 | return 0; |
870 | } | 640 | } |
@@ -1006,7 +776,6 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
1006 | { | 776 | { |
1007 | int loop = 0; | 777 | int loop = 0; |
1008 | int change = 1; | 778 | int change = 1; |
1009 | struct pci_func *func; | ||
1010 | u8 hp_slot; | 779 | u8 hp_slot; |
1011 | u8 getstatus; | 780 | u8 getstatus; |
1012 | struct slot *p_slot; | 781 | struct slot *p_slot; |
@@ -1021,11 +790,10 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
1021 | ctrl->event_queue[loop].event_type); | 790 | ctrl->event_queue[loop].event_type); |
1022 | hp_slot = ctrl->event_queue[loop].hp_slot; | 791 | hp_slot = ctrl->event_queue[loop].hp_slot; |
1023 | 792 | ||
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); | 793 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
1027 | 794 | ||
1028 | dbg("%s: hp_slot %d, func %p, p_slot %p\n", __FUNCTION__, hp_slot, func, p_slot); | 795 | dbg("%s: hp_slot %d, p_slot %p\n", |
796 | __FUNCTION__, hp_slot, p_slot); | ||
1029 | 797 | ||
1030 | if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { | 798 | if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { |
1031 | dbg("%s: button cancel\n", __FUNCTION__); | 799 | dbg("%s: button cancel\n", __FUNCTION__); |
@@ -1147,13 +915,6 @@ int shpchp_enable_slot (struct slot *p_slot) | |||
1147 | { | 915 | { |
1148 | u8 getstatus = 0; | 916 | u8 getstatus = 0; |
1149 | int rc; | 917 | 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 | 918 | ||
1158 | /* Check to see if (latch closed, card present, power off) */ | 919 | /* Check to see if (latch closed, card present, power off) */ |
1159 | down(&p_slot->ctrl->crit_sect); | 920 | down(&p_slot->ctrl->crit_sect); |
@@ -1177,75 +938,35 @@ int shpchp_enable_slot (struct slot *p_slot) | |||
1177 | } | 938 | } |
1178 | up(&p_slot->ctrl->crit_sect); | 939 | up(&p_slot->ctrl->crit_sect); |
1179 | 940 | ||
1180 | slot_remove(func); | 941 | p_slot->is_a_board = 1; |
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 | 942 | ||
1192 | /* We have to save the presence info for these slots */ | 943 | /* We have to save the presence info for these slots */ |
1193 | p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); | 944 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); |
1194 | p_slot->hpc_ops->get_power_status(p_slot, &(func->pwr_save)); | 945 | p_slot->hpc_ops->get_power_status(p_slot, &(p_slot->pwr_save)); |
1195 | dbg("%s: func->pwr_save %x\n", __FUNCTION__, func->pwr_save); | 946 | dbg("%s: p_slot->pwr_save %x\n", __FUNCTION__, p_slot->pwr_save); |
1196 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 947 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
1197 | func->switch_save = !getstatus? 0x10:0; | ||
1198 | 948 | ||
1199 | rc = board_added(func, p_slot->ctrl); | 949 | rc = board_added(p_slot); |
1200 | if (rc) { | 950 | if (rc) { |
1201 | if (is_bridge(func, p_slot->ctrl)) { | 951 | p_slot->hpc_ops->get_adapter_status(p_slot, |
1202 | u8 secondary = func->pci_dev->subordinate->secondary; | 952 | &(p_slot->presence_save)); |
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); | 953 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
1223 | func->switch_save = !getstatus? 0x10:0; | ||
1224 | } | 954 | } |
1225 | 955 | ||
1226 | if (p_slot) | 956 | update_slot_info(p_slot); |
1227 | update_slot_info(p_slot); | ||
1228 | |||
1229 | return rc; | 957 | return rc; |
1230 | } | 958 | } |
1231 | 959 | ||
1232 | 960 | ||
1233 | int shpchp_disable_slot (struct slot *p_slot) | 961 | int shpchp_disable_slot (struct slot *p_slot) |
1234 | { | 962 | { |
1235 | u8 class_code, header_type, BCR; | ||
1236 | u8 index = 0; | ||
1237 | u8 getstatus = 0; | 963 | u8 getstatus = 0; |
1238 | u32 rc = 0; | 964 | u32 rc = 0; |
1239 | int ret = 0; | 965 | int ret = 0; |
1240 | unsigned int devfn; | ||
1241 | struct pci_bus *pci_bus; | ||
1242 | struct pci_func *func; | ||
1243 | 966 | ||
1244 | if (!p_slot->ctrl) | 967 | if (!p_slot->ctrl) |
1245 | return -ENODEV; | 968 | return -ENODEV; |
1246 | 969 | ||
1247 | pci_bus = p_slot->ctrl->pci_dev->subordinate; | ||
1248 | |||
1249 | /* Check to see if (latch closed, card present, power on) */ | 970 | /* Check to see if (latch closed, card present, power on) */ |
1250 | down(&p_slot->ctrl->crit_sect); | 971 | down(&p_slot->ctrl->crit_sect); |
1251 | 972 | ||
@@ -1269,54 +990,8 @@ int shpchp_disable_slot (struct slot *p_slot) | |||
1269 | } | 990 | } |
1270 | up(&p_slot->ctrl->crit_sect); | 991 | up(&p_slot->ctrl->crit_sect); |
1271 | 992 | ||
1272 | func = shpchp_slot_find(p_slot->bus, p_slot->device, index++); | 993 | rc = remove_board(p_slot); |
1273 | 994 | update_slot_info(p_slot); | |
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; | 995 | return rc; |
1321 | } | 996 | } |
1322 | 997 | ||