2 * PCI Express Hot Plug Controller Driver
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
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.
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
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.
26 * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
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>
45 static void interrupt_event_handler(struct controller
*ctrl
);
47 static struct semaphore event_semaphore
; /* mutex for process loop (up if something to process) */
48 static struct semaphore event_exit
; /* guard ensure thread has exited before calling it quits */
49 static int event_finished
;
50 static unsigned long pushbutton_pending
; /* = 0 */
51 static unsigned long surprise_rm_pending
; /* = 0 */
53 u8
pciehp_handle_attention_button(u8 hp_slot
, void *inst_id
)
55 struct controller
*ctrl
= (struct controller
*) inst_id
;
59 struct pci_func
*func
;
60 struct event_info
*taskInfo
;
62 /* Attention Button Change */
63 dbg("pciehp: Attention button interrupt received.\n");
65 func
= pciehp_slot_find(ctrl
->slot_bus
, (hp_slot
+ ctrl
->slot_device_offset
), 0);
67 /* This is the structure that tells the worker thread what to do */
68 taskInfo
= &(ctrl
->event_queue
[ctrl
->next_event
]);
69 p_slot
= pciehp_find_slot(ctrl
, hp_slot
+ ctrl
->slot_device_offset
);
71 p_slot
->hpc_ops
->get_adapter_status(p_slot
, &(func
->presence_save
));
72 p_slot
->hpc_ops
->get_latch_status(p_slot
, &getstatus
);
74 ctrl
->next_event
= (ctrl
->next_event
+ 1) % 10;
75 taskInfo
->hp_slot
= hp_slot
;
80 * Button pressed - See if need to TAKE ACTION!!!
82 info("Button pressed on Slot(%d)\n", ctrl
->first_slot
+ hp_slot
);
83 taskInfo
->event_type
= INT_BUTTON_PRESS
;
85 if ((p_slot
->state
== BLINKINGON_STATE
)
86 || (p_slot
->state
== BLINKINGOFF_STATE
)) {
87 /* Cancel if we are still blinking; this means that we press the
88 * attention again before the 5 sec. limit expires to cancel hot-add
91 taskInfo
->event_type
= INT_BUTTON_CANCEL
;
92 info("Button cancel on Slot(%d)\n", ctrl
->first_slot
+ hp_slot
);
93 } else if ((p_slot
->state
== POWERON_STATE
)
94 || (p_slot
->state
== POWEROFF_STATE
)) {
95 /* Ignore if the slot is on power-on or power-off state; this
96 * means that the previous attention button action to hot-add or
97 * hot-remove is undergoing
99 taskInfo
->event_type
= INT_BUTTON_IGNORE
;
100 info("Button ignore on Slot(%d)\n", ctrl
->first_slot
+ hp_slot
);
104 up(&event_semaphore
); /* signal event thread that new event is posted */
110 u8
pciehp_handle_switch_change(u8 hp_slot
, void *inst_id
)
112 struct controller
*ctrl
= (struct controller
*) inst_id
;
116 struct pci_func
*func
;
117 struct event_info
*taskInfo
;
120 dbg("pciehp: Switch interrupt received.\n");
122 func
= pciehp_slot_find(ctrl
->slot_bus
, (hp_slot
+ ctrl
->slot_device_offset
), 0);
124 /* This is the structure that tells the worker thread
127 taskInfo
= &(ctrl
->event_queue
[ctrl
->next_event
]);
128 ctrl
->next_event
= (ctrl
->next_event
+ 1) % 10;
129 taskInfo
->hp_slot
= hp_slot
;
132 p_slot
= pciehp_find_slot(ctrl
, hp_slot
+ ctrl
->slot_device_offset
);
133 p_slot
->hpc_ops
->get_adapter_status(p_slot
, &(func
->presence_save
));
134 p_slot
->hpc_ops
->get_latch_status(p_slot
, &getstatus
);
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
;
147 info("Latch close on Slot(%d)\n", ctrl
->first_slot
+ hp_slot
);
148 func
->switch_save
= 0x10;
149 taskInfo
->event_type
= INT_SWITCH_CLOSE
;
153 up(&event_semaphore
); /* signal event thread that new event is posted */
158 u8
pciehp_handle_presence_change(u8 hp_slot
, void *inst_id
)
160 struct controller
*ctrl
= (struct controller
*) inst_id
;
163 struct pci_func
*func
;
164 struct event_info
*taskInfo
;
166 /* Presence Change */
167 dbg("pciehp: Presence/Notify input change.\n");
169 func
= pciehp_slot_find(ctrl
->slot_bus
, (hp_slot
+ ctrl
->slot_device_offset
), 0);
171 /* This is the structure that tells the worker thread
174 taskInfo
= &(ctrl
->event_queue
[ctrl
->next_event
]);
175 ctrl
->next_event
= (ctrl
->next_event
+ 1) % 10;
176 taskInfo
->hp_slot
= hp_slot
;
179 p_slot
= pciehp_find_slot(ctrl
, hp_slot
+ ctrl
->slot_device_offset
);
181 /* Switch is open, assume a presence change
182 * Save the presence state
184 p_slot
->hpc_ops
->get_adapter_status(p_slot
, &(func
->presence_save
));
185 if (func
->presence_save
) {
189 info("Card present on Slot(%d)\n", ctrl
->first_slot
+ hp_slot
);
190 taskInfo
->event_type
= INT_PRESENCE_ON
;
195 info("Card not present on Slot(%d)\n", ctrl
->first_slot
+ hp_slot
);
196 taskInfo
->event_type
= INT_PRESENCE_OFF
;
200 up(&event_semaphore
); /* signal event thread that new event is posted */
205 u8
pciehp_handle_power_fault(u8 hp_slot
, void *inst_id
)
207 struct controller
*ctrl
= (struct controller
*) inst_id
;
210 struct pci_func
*func
;
211 struct event_info
*taskInfo
;
214 dbg("pciehp: Power fault interrupt received.\n");
216 func
= pciehp_slot_find(ctrl
->slot_bus
, (hp_slot
+ ctrl
->slot_device_offset
), 0);
218 /* this is the structure that tells the worker thread
221 taskInfo
= &(ctrl
->event_queue
[ctrl
->next_event
]);
222 ctrl
->next_event
= (ctrl
->next_event
+ 1) % 10;
223 taskInfo
->hp_slot
= hp_slot
;
226 p_slot
= pciehp_find_slot(ctrl
, hp_slot
+ ctrl
->slot_device_offset
);
228 if ( !(p_slot
->hpc_ops
->query_power_fault(p_slot
))) {
230 * power fault Cleared
232 info("Power fault cleared on Slot(%d)\n", ctrl
->first_slot
+ hp_slot
);
234 taskInfo
->event_type
= INT_POWER_FAULT_CLEAR
;
239 info("Power fault on Slot(%d)\n", ctrl
->first_slot
+ hp_slot
);
240 taskInfo
->event_type
= INT_POWER_FAULT
;
241 /* set power fault status for this board */
243 info("power fault bit %x set\n", hp_slot
);
246 up(&event_semaphore
); /* signal event thread that new event is posted */
252 * pciehp_slot_create - Creates a node and adds it to the proper bus.
253 * @busnumber - bus where new node is to be located
255 * Returns pointer to the new node or NULL if unsuccessful
257 struct pci_func
*pciehp_slot_create(u8 busnumber
)
259 struct pci_func
*new_slot
;
260 struct pci_func
*next
;
261 dbg("%s: busnumber %x\n", __FUNCTION__
, busnumber
);
262 new_slot
= kmalloc(sizeof(struct pci_func
), GFP_KERNEL
);
264 if (new_slot
== NULL
)
267 memset(new_slot
, 0, sizeof(struct pci_func
));
269 new_slot
->next
= NULL
;
270 new_slot
->configured
= 1;
272 if (pciehp_slot_list
[busnumber
] == NULL
) {
273 pciehp_slot_list
[busnumber
] = new_slot
;
275 next
= pciehp_slot_list
[busnumber
];
276 while (next
->next
!= NULL
)
278 next
->next
= new_slot
;
285 * slot_remove - Removes a node from the linked list of slots.
286 * @old_slot: slot to remove
288 * Returns 0 if successful, !0 otherwise.
290 static int slot_remove(struct pci_func
* old_slot
)
292 struct pci_func
*next
;
294 if (old_slot
== NULL
)
297 next
= pciehp_slot_list
[old_slot
->bus
];
302 if (next
== old_slot
) {
303 pciehp_slot_list
[old_slot
->bus
] = old_slot
->next
;
308 while ((next
->next
!= old_slot
) && (next
->next
!= NULL
)) {
312 if (next
->next
== old_slot
) {
313 next
->next
= old_slot
->next
;
322 * bridge_slot_remove - Removes a node from the linked list of slots.
323 * @bridge: bridge to remove
325 * Returns 0 if successful, !0 otherwise.
327 static int bridge_slot_remove(struct pci_func
*bridge
)
329 u8 subordinateBus
, secondaryBus
;
331 struct pci_func
*next
;
336 secondaryBus
= (bridge
->config_space
[0x06] >> 8) & 0xFF;
337 subordinateBus
= (bridge
->config_space
[0x06] >> 16) & 0xFF;
339 for (tempBus
= secondaryBus
; tempBus
<= subordinateBus
; tempBus
++) {
340 next
= pciehp_slot_list
[tempBus
];
342 while (!slot_remove(next
)) {
343 next
= pciehp_slot_list
[tempBus
];
347 next
= pciehp_slot_list
[bridge
->bus
];
353 if (next
== bridge
) {
354 pciehp_slot_list
[bridge
->bus
] = bridge
->next
;
359 while ((next
->next
!= bridge
) && (next
->next
!= NULL
)) {
363 if (next
->next
== bridge
) {
364 next
->next
= bridge
->next
;
373 * pciehp_slot_find - Looks for a node by bus, and device, multiple functions accessed
375 * @device: device to find
376 * @index: is 0 for first function found, 1 for the second...
378 * Returns pointer to the node if successful, %NULL otherwise.
380 struct pci_func
*pciehp_slot_find(u8 bus
, u8 device
, u8 index
)
383 struct pci_func
*func
;
385 func
= pciehp_slot_list
[bus
];
386 dbg("%s: bus %x device %x index %x\n",
387 __FUNCTION__
, bus
, device
, index
);
389 dbg("%s: func-> bus %x device %x function %x pci_dev %p\n",
390 __FUNCTION__
, func
->bus
, func
->device
, func
->function
,
393 dbg("%s: func == NULL\n", __FUNCTION__
);
395 if ((func
== NULL
) || ((func
->device
== device
) && (index
== 0)))
398 if (func
->device
== device
)
401 while (func
->next
!= NULL
) {
404 dbg("%s: In while loop, func-> bus %x device %x function %x pci_dev %p\n",
405 __FUNCTION__
, func
->bus
, func
->device
, func
->function
,
407 if (func
->device
== device
)
409 dbg("%s: while loop, found %d, index %d\n", __FUNCTION__
,
412 if ((found
== index
) || (func
->function
== index
)) {
413 dbg("%s: Found bus %x dev %x func %x\n", __FUNCTION__
,
414 func
->bus
, func
->device
, func
->function
);
422 static int is_bridge(struct pci_func
* func
)
424 /* Check the header type */
425 if (((func
->config_space
[0x03] >> 16) & 0xFF) == 0x01)
432 /* The following routines constitute the bulk of the
433 hotplug controller logic
436 static void set_slot_off(struct controller
*ctrl
, struct slot
* pslot
)
438 /* Wait for exclusive access to hardware */
439 down(&ctrl
->crit_sect
);
441 /* turn off slot, turn on Amber LED, turn off Green LED if supported*/
442 if (POWER_CTRL(ctrl
->ctrlcap
)) {
443 if (pslot
->hpc_ops
->power_off_slot(pslot
)) {
444 err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__
);
445 up(&ctrl
->crit_sect
);
448 wait_for_ctrl_irq (ctrl
);
451 if (PWR_LED(ctrl
->ctrlcap
)) {
452 pslot
->hpc_ops
->green_led_off(pslot
);
453 wait_for_ctrl_irq (ctrl
);
456 if (ATTN_LED(ctrl
->ctrlcap
)) {
457 if (pslot
->hpc_ops
->set_attention_status(pslot
, 1)) {
458 err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__
);
459 up(&ctrl
->crit_sect
);
462 wait_for_ctrl_irq (ctrl
);
465 /* Done with exclusive hardware access */
466 up(&ctrl
->crit_sect
);
470 * board_added - Called after a board has been added to the system.
472 * Turns power on for the board
476 static u32
board_added(struct pci_func
* func
, struct controller
* ctrl
)
479 u32 temp_register
= 0xFFFFFFFF;
483 p_slot
= pciehp_find_slot(ctrl
, func
->device
);
484 hp_slot
= func
->device
- ctrl
->slot_device_offset
;
486 dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__
, func
->device
, ctrl
->slot_device_offset
, hp_slot
);
488 /* Wait for exclusive access to hardware */
489 down(&ctrl
->crit_sect
);
491 if (POWER_CTRL(ctrl
->ctrlcap
)) {
493 rc
= p_slot
->hpc_ops
->power_on_slot(p_slot
);
495 up(&ctrl
->crit_sect
);
499 /* Wait for the command to complete */
500 wait_for_ctrl_irq (ctrl
);
503 if (PWR_LED(ctrl
->ctrlcap
)) {
504 p_slot
->hpc_ops
->green_led_blink(p_slot
);
506 /* Wait for the command to complete */
507 wait_for_ctrl_irq (ctrl
);
510 /* Done with exclusive hardware access */
511 up(&ctrl
->crit_sect
);
513 /* Wait for ~1 second */
514 dbg("%s: before long_delay\n", __FUNCTION__
);
515 wait_for_ctrl_irq (ctrl
);
516 dbg("%s: afterlong_delay\n", __FUNCTION__
);
518 /* Check link training status */
519 rc
= p_slot
->hpc_ops
->check_lnk_status(ctrl
);
521 err("%s: Failed to check link status\n", __FUNCTION__
);
522 set_slot_off(ctrl
, p_slot
);
526 dbg("%s: func status = %x\n", __FUNCTION__
, func
->status
);
528 /* Check for a power fault */
529 if (func
->status
== 0xFF) {
530 /* power fault occurred, but it was benign */
531 temp_register
= 0xFFFFFFFF;
532 dbg("%s: temp register set to %x by power fault\n", __FUNCTION__
, temp_register
);
538 rc
= pciehp_configure_device(p_slot
);
540 err("Cannot add device 0x%x:%x\n", p_slot
->bus
,
545 pciehp_save_slot_config(ctrl
, func
);
547 func
->switch_save
= 0x10;
548 func
->is_a_board
= 0x01;
551 * Some PCI Express root ports require fixup after hot-plug operation.
554 pci_fixup_device(pci_fixup_final
, ctrl
->pci_dev
);
555 if (PWR_LED(ctrl
->ctrlcap
)) {
556 /* Wait for exclusive access to hardware */
557 down(&ctrl
->crit_sect
);
559 p_slot
->hpc_ops
->green_led_on(p_slot
);
561 /* Wait for the command to complete */
562 wait_for_ctrl_irq (ctrl
);
564 /* Done with exclusive hardware access */
565 up(&ctrl
->crit_sect
);
570 set_slot_off(ctrl
, p_slot
);
576 * remove_board - Turns off slot and LED's
579 static u32
remove_board(struct pci_func
*func
, struct controller
*ctrl
)
589 if (pciehp_unconfigure_device(func
))
592 device
= func
->device
;
594 hp_slot
= func
->device
- ctrl
->slot_device_offset
;
595 p_slot
= pciehp_find_slot(ctrl
, hp_slot
+ ctrl
->slot_device_offset
);
597 dbg("In %s, hp_slot = %d\n", __FUNCTION__
, hp_slot
);
599 /* Change status to shutdown */
600 if (func
->is_a_board
)
602 func
->configured
= 0;
604 /* Wait for exclusive access to hardware */
605 down(&ctrl
->crit_sect
);
607 if (POWER_CTRL(ctrl
->ctrlcap
)) {
609 rc
= p_slot
->hpc_ops
->power_off_slot(p_slot
);
611 err("%s: Issue of Slot Disable command failed\n", __FUNCTION__
);
612 up(&ctrl
->crit_sect
);
615 /* Wait for the command to complete */
616 wait_for_ctrl_irq (ctrl
);
619 if (PWR_LED(ctrl
->ctrlcap
)) {
620 /* turn off Green LED */
621 p_slot
->hpc_ops
->green_led_off(p_slot
);
623 /* Wait for the command to complete */
624 wait_for_ctrl_irq (ctrl
);
627 /* Done with exclusive hardware access */
628 up(&ctrl
->crit_sect
);
630 if (ctrl
->add_support
) {
632 if (is_bridge(func
)) {
633 dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n",
634 ctrl
->seg
, func
->bus
, func
->device
, func
->function
);
635 bridge_slot_remove(func
);
637 dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n",
638 ctrl
->seg
, func
->bus
, func
->device
, func
->function
);
642 func
= pciehp_slot_find(ctrl
->slot_bus
, device
, 0);
645 /* Setup slot structure with entry for empty slot */
646 func
= pciehp_slot_create(ctrl
->slot_bus
);
652 func
->bus
= ctrl
->slot_bus
;
653 func
->device
= device
;
655 func
->configured
= 0;
656 func
->switch_save
= 0x10;
657 func
->is_a_board
= 0;
664 static void pushbutton_helper_thread(unsigned long data
)
666 pushbutton_pending
= data
;
668 up(&event_semaphore
);
672 * pciehp_pushbutton_thread
674 * Scheduled procedure to handle blocking stuff for the pushbuttons
675 * Handles all pending events and exits.
678 static void pciehp_pushbutton_thread(unsigned long slot
)
680 struct slot
*p_slot
= (struct slot
*) slot
;
683 pushbutton_pending
= 0;
686 dbg("%s: Error! slot NULL\n", __FUNCTION__
);
690 p_slot
->hpc_ops
->get_power_status(p_slot
, &getstatus
);
692 p_slot
->state
= POWEROFF_STATE
;
693 dbg("In power_down_board, b:d(%x:%x)\n", p_slot
->bus
, p_slot
->device
);
695 pciehp_disable_slot(p_slot
);
696 p_slot
->state
= STATIC_STATE
;
698 p_slot
->state
= POWERON_STATE
;
699 dbg("In add_board, b:d(%x:%x)\n", p_slot
->bus
, p_slot
->device
);
701 if (pciehp_enable_slot(p_slot
) && PWR_LED(p_slot
->ctrl
->ctrlcap
)) {
702 /* Wait for exclusive access to hardware */
703 down(&p_slot
->ctrl
->crit_sect
);
705 p_slot
->hpc_ops
->green_led_off(p_slot
);
707 /* Wait for the command to complete */
708 wait_for_ctrl_irq (p_slot
->ctrl
);
710 /* Done with exclusive hardware access */
711 up(&p_slot
->ctrl
->crit_sect
);
713 p_slot
->state
= STATIC_STATE
;
720 * pciehp_surprise_rm_thread
722 * Scheduled procedure to handle blocking stuff for the surprise removal
723 * Handles all pending events and exits.
726 static void pciehp_surprise_rm_thread(unsigned long slot
)
728 struct slot
*p_slot
= (struct slot
*) slot
;
731 surprise_rm_pending
= 0;
734 dbg("%s: Error! slot NULL\n", __FUNCTION__
);
738 p_slot
->hpc_ops
->get_adapter_status(p_slot
, &getstatus
);
740 p_slot
->state
= POWEROFF_STATE
;
741 dbg("In removing board, b:d(%x:%x)\n", p_slot
->bus
, p_slot
->device
);
743 pciehp_disable_slot(p_slot
);
744 p_slot
->state
= STATIC_STATE
;
746 p_slot
->state
= POWERON_STATE
;
747 dbg("In add_board, b:d(%x:%x)\n", p_slot
->bus
, p_slot
->device
);
749 if (pciehp_enable_slot(p_slot
) && PWR_LED(p_slot
->ctrl
->ctrlcap
)) {
750 /* Wait for exclusive access to hardware */
751 down(&p_slot
->ctrl
->crit_sect
);
753 p_slot
->hpc_ops
->green_led_off(p_slot
);
755 /* Wait for the command to complete */
756 wait_for_ctrl_irq (p_slot
->ctrl
);
758 /* Done with exclusive hardware access */
759 up(&p_slot
->ctrl
->crit_sect
);
761 p_slot
->state
= STATIC_STATE
;
769 /* this is the main worker thread */
770 static int event_thread(void* data
)
772 struct controller
*ctrl
;
774 daemonize("pciehpd_event");
779 dbg("!!!!event_thread sleeping\n");
780 down_interruptible (&event_semaphore
);
781 dbg("event_thread woken finished = %d\n", event_finished
);
782 if (event_finished
|| signal_pending(current
))
785 if (pushbutton_pending
)
786 pciehp_pushbutton_thread(pushbutton_pending
);
787 else if (surprise_rm_pending
)
788 pciehp_surprise_rm_thread(surprise_rm_pending
);
790 for (ctrl
= pciehp_ctrl_list
; ctrl
; ctrl
=ctrl
->next
)
791 interrupt_event_handler(ctrl
);
793 dbg("event_thread signals exit\n");
798 int pciehp_event_start_thread(void)
802 /* initialize our semaphores */
803 init_MUTEX_LOCKED(&event_exit
);
806 init_MUTEX_LOCKED(&event_semaphore
);
807 pid
= kernel_thread(event_thread
, NULL
, 0);
810 err ("Can't start up our event thread\n");
813 dbg("Our event thread pid = %d\n", pid
);
818 void pciehp_event_stop_thread(void)
821 dbg("event_thread finish command given\n");
822 up(&event_semaphore
);
823 dbg("wait for event_thread to exit\n");
828 static int update_slot_info(struct slot
*slot
)
830 struct hotplug_slot_info
*info
;
831 /* char buffer[SLOT_NAME_SIZE]; */
834 info
= kmalloc(sizeof(struct hotplug_slot_info
), GFP_KERNEL
);
838 /* make_slot_name (&buffer[0], SLOT_NAME_SIZE, slot); */
840 slot
->hpc_ops
->get_power_status(slot
, &(info
->power_status
));
841 slot
->hpc_ops
->get_attention_status(slot
, &(info
->attention_status
));
842 slot
->hpc_ops
->get_latch_status(slot
, &(info
->latch_status
));
843 slot
->hpc_ops
->get_adapter_status(slot
, &(info
->adapter_status
));
845 /* result = pci_hp_change_slot_info(buffer, info); */
846 result
= pci_hp_change_slot_info(slot
->hotplug_slot
, info
);
851 static void interrupt_event_handler(struct controller
*ctrl
)
855 struct pci_func
*func
;
863 for (loop
= 0; loop
< 10; loop
++) {
864 if (ctrl
->event_queue
[loop
].event_type
!= 0) {
865 hp_slot
= ctrl
->event_queue
[loop
].hp_slot
;
867 func
= pciehp_slot_find(ctrl
->slot_bus
, (hp_slot
+ ctrl
->slot_device_offset
), 0);
869 p_slot
= pciehp_find_slot(ctrl
, hp_slot
+ ctrl
->slot_device_offset
);
871 dbg("hp_slot %d, func %p, p_slot %p\n", hp_slot
, func
, p_slot
);
873 if (ctrl
->event_queue
[loop
].event_type
== INT_BUTTON_CANCEL
) {
874 dbg("button cancel\n");
875 del_timer(&p_slot
->task_event
);
877 switch (p_slot
->state
) {
878 case BLINKINGOFF_STATE
:
879 /* Wait for exclusive access to hardware */
880 down(&ctrl
->crit_sect
);
882 if (PWR_LED(ctrl
->ctrlcap
)) {
883 p_slot
->hpc_ops
->green_led_on(p_slot
);
884 /* Wait for the command to complete */
885 wait_for_ctrl_irq (ctrl
);
887 if (ATTN_LED(ctrl
->ctrlcap
)) {
888 p_slot
->hpc_ops
->set_attention_status(p_slot
, 0);
890 /* Wait for the command to complete */
891 wait_for_ctrl_irq (ctrl
);
893 /* Done with exclusive hardware access */
894 up(&ctrl
->crit_sect
);
896 case BLINKINGON_STATE
:
897 /* Wait for exclusive access to hardware */
898 down(&ctrl
->crit_sect
);
900 if (PWR_LED(ctrl
->ctrlcap
)) {
901 p_slot
->hpc_ops
->green_led_off(p_slot
);
902 /* Wait for the command to complete */
903 wait_for_ctrl_irq (ctrl
);
905 if (ATTN_LED(ctrl
->ctrlcap
)){
906 p_slot
->hpc_ops
->set_attention_status(p_slot
, 0);
907 /* Wait for the command to complete */
908 wait_for_ctrl_irq (ctrl
);
910 /* Done with exclusive hardware access */
911 up(&ctrl
->crit_sect
);
915 warn("Not a valid state\n");
918 info(msg_button_cancel
, p_slot
->number
);
919 p_slot
->state
= STATIC_STATE
;
921 /* ***********Button Pressed (No action on 1st press...) */
922 else if (ctrl
->event_queue
[loop
].event_type
== INT_BUTTON_PRESS
) {
924 if (ATTN_BUTTN(ctrl
->ctrlcap
)) {
925 dbg("Button pressed\n");
926 p_slot
->hpc_ops
->get_power_status(p_slot
, &getstatus
);
930 p_slot
->state
= BLINKINGOFF_STATE
;
931 info(msg_button_off
, p_slot
->number
);
934 dbg("slot is off\n");
935 p_slot
->state
= BLINKINGON_STATE
;
936 info(msg_button_on
, p_slot
->number
);
939 /* Wait for exclusive access to hardware */
940 down(&ctrl
->crit_sect
);
942 /* blink green LED and turn off amber */
943 if (PWR_LED(ctrl
->ctrlcap
)) {
944 p_slot
->hpc_ops
->green_led_blink(p_slot
);
945 /* Wait for the command to complete */
946 wait_for_ctrl_irq (ctrl
);
949 if (ATTN_LED(ctrl
->ctrlcap
)) {
950 p_slot
->hpc_ops
->set_attention_status(p_slot
, 0);
952 /* Wait for the command to complete */
953 wait_for_ctrl_irq (ctrl
);
956 /* Done with exclusive hardware access */
957 up(&ctrl
->crit_sect
);
959 init_timer(&p_slot
->task_event
);
960 p_slot
->task_event
.expires
= jiffies
+ 5 * HZ
; /* 5 second delay */
961 p_slot
->task_event
.function
= (void (*)(unsigned long)) pushbutton_helper_thread
;
962 p_slot
->task_event
.data
= (unsigned long) p_slot
;
964 dbg("add_timer p_slot = %p\n", (void *) p_slot
);
965 add_timer(&p_slot
->task_event
);
968 /***********POWER FAULT********************/
969 else if (ctrl
->event_queue
[loop
].event_type
== INT_POWER_FAULT
) {
970 if (POWER_CTRL(ctrl
->ctrlcap
)) {
971 dbg("power fault\n");
972 /* Wait for exclusive access to hardware */
973 down(&ctrl
->crit_sect
);
975 if (ATTN_LED(ctrl
->ctrlcap
)) {
976 p_slot
->hpc_ops
->set_attention_status(p_slot
, 1);
977 wait_for_ctrl_irq (ctrl
);
980 if (PWR_LED(ctrl
->ctrlcap
)) {
981 p_slot
->hpc_ops
->green_led_off(p_slot
);
982 wait_for_ctrl_irq (ctrl
);
985 /* Done with exclusive hardware access */
986 up(&ctrl
->crit_sect
);
989 /***********SURPRISE REMOVAL********************/
990 else if ((ctrl
->event_queue
[loop
].event_type
== INT_PRESENCE_ON
) ||
991 (ctrl
->event_queue
[loop
].event_type
== INT_PRESENCE_OFF
)) {
992 if (HP_SUPR_RM(ctrl
->ctrlcap
)) {
993 dbg("Surprise Removal\n");
995 surprise_rm_pending
= (unsigned long) p_slot
;
996 up(&event_semaphore
);
997 update_slot_info(p_slot
);
1001 /* refresh notification */
1003 update_slot_info(p_slot
);
1006 ctrl
->event_queue
[loop
].event_type
= 0;
1010 } /* End of FOR loop */
1015 int pciehp_enable_slot(struct slot
*p_slot
)
1019 struct pci_func
*func
;
1021 func
= pciehp_slot_find(p_slot
->bus
, p_slot
->device
, 0);
1023 dbg("%s: Error! slot NULL\n", __FUNCTION__
);
1027 /* Check to see if (latch closed, card present, power off) */
1028 down(&p_slot
->ctrl
->crit_sect
);
1030 rc
= p_slot
->hpc_ops
->get_adapter_status(p_slot
, &getstatus
);
1031 if (rc
|| !getstatus
) {
1032 info("%s: no adapter on slot(%x)\n", __FUNCTION__
, p_slot
->number
);
1033 up(&p_slot
->ctrl
->crit_sect
);
1036 if (MRL_SENS(p_slot
->ctrl
->ctrlcap
)) {
1037 rc
= p_slot
->hpc_ops
->get_latch_status(p_slot
, &getstatus
);
1038 if (rc
|| getstatus
) {
1039 info("%s: latch open on slot(%x)\n", __FUNCTION__
, p_slot
->number
);
1040 up(&p_slot
->ctrl
->crit_sect
);
1045 if (POWER_CTRL(p_slot
->ctrl
->ctrlcap
)) {
1046 rc
= p_slot
->hpc_ops
->get_power_status(p_slot
, &getstatus
);
1047 if (rc
|| getstatus
) {
1048 info("%s: already enabled on slot(%x)\n", __FUNCTION__
, p_slot
->number
);
1049 up(&p_slot
->ctrl
->crit_sect
);
1053 up(&p_slot
->ctrl
->crit_sect
);
1057 func
= pciehp_slot_create(p_slot
->bus
);
1061 func
->bus
= p_slot
->bus
;
1062 func
->device
= p_slot
->device
;
1064 func
->configured
= 0;
1065 func
->is_a_board
= 1;
1067 /* We have to save the presence info for these slots */
1068 p_slot
->hpc_ops
->get_adapter_status(p_slot
, &(func
->presence_save
));
1069 p_slot
->hpc_ops
->get_latch_status(p_slot
, &getstatus
);
1070 func
->switch_save
= !getstatus
? 0x10:0;
1072 rc
= board_added(func
, p_slot
->ctrl
);
1074 if (is_bridge(func
))
1075 bridge_slot_remove(func
);
1079 /* Setup slot structure with entry for empty slot */
1080 func
= pciehp_slot_create(p_slot
->bus
);
1082 return 1; /* Out of memory */
1084 func
->bus
= p_slot
->bus
;
1085 func
->device
= p_slot
->device
;
1087 func
->configured
= 0;
1088 func
->is_a_board
= 1;
1090 /* We have to save the presence info for these slots */
1091 p_slot
->hpc_ops
->get_adapter_status(p_slot
, &(func
->presence_save
));
1092 p_slot
->hpc_ops
->get_latch_status(p_slot
, &getstatus
);
1093 func
->switch_save
= !getstatus
? 0x10:0;
1097 update_slot_info(p_slot
);
1103 int pciehp_disable_slot(struct slot
*p_slot
)
1105 u8 class_code
, header_type
, BCR
;
1111 struct pci_bus
*pci_bus
= p_slot
->ctrl
->pci_dev
->subordinate
;
1112 struct pci_func
*func
;
1117 /* Check to see if (latch closed, card present, power on) */
1118 down(&p_slot
->ctrl
->crit_sect
);
1120 if (!HP_SUPR_RM(p_slot
->ctrl
->ctrlcap
)) {
1121 ret
= p_slot
->hpc_ops
->get_adapter_status(p_slot
, &getstatus
);
1122 if (ret
|| !getstatus
) {
1123 info("%s: no adapter on slot(%x)\n", __FUNCTION__
, p_slot
->number
);
1124 up(&p_slot
->ctrl
->crit_sect
);
1129 if (MRL_SENS(p_slot
->ctrl
->ctrlcap
)) {
1130 ret
= p_slot
->hpc_ops
->get_latch_status(p_slot
, &getstatus
);
1131 if (ret
|| getstatus
) {
1132 info("%s: latch open on slot(%x)\n", __FUNCTION__
, p_slot
->number
);
1133 up(&p_slot
->ctrl
->crit_sect
);
1138 if (POWER_CTRL(p_slot
->ctrl
->ctrlcap
)) {
1139 ret
= p_slot
->hpc_ops
->get_power_status(p_slot
, &getstatus
);
1140 if (ret
|| !getstatus
) {
1141 info("%s: already disabled slot(%x)\n", __FUNCTION__
, p_slot
->number
);
1142 up(&p_slot
->ctrl
->crit_sect
);
1147 up(&p_slot
->ctrl
->crit_sect
);
1149 func
= pciehp_slot_find(p_slot
->bus
, p_slot
->device
, index
++);
1151 /* Make sure there are no video controllers here
1152 * for all func of p_slot
1154 while (func
&& !rc
) {
1155 pci_bus
->number
= func
->bus
;
1156 devfn
= PCI_DEVFN(func
->device
, func
->function
);
1158 /* Check the Class Code */
1159 rc
= pci_bus_read_config_byte (pci_bus
, devfn
, 0x0B, &class_code
);
1163 if (class_code
== PCI_BASE_CLASS_DISPLAY
) {
1164 /* Display/Video adapter (not supported) */
1165 rc
= REMOVE_NOT_SUPPORTED
;
1167 /* See if it's a bridge */
1168 rc
= pci_bus_read_config_byte (pci_bus
, devfn
, PCI_HEADER_TYPE
, &header_type
);
1172 /* If it's a bridge, check the VGA Enable bit */
1173 if ((header_type
& 0x7F) == PCI_HEADER_TYPE_BRIDGE
) {
1174 rc
= pci_bus_read_config_byte (pci_bus
, devfn
, PCI_BRIDGE_CONTROL
, &BCR
);
1178 /* If the VGA Enable bit is set, remove isn't supported */
1179 if (BCR
& PCI_BRIDGE_CTL_VGA
) {
1180 rc
= REMOVE_NOT_SUPPORTED
;
1185 func
= pciehp_slot_find(p_slot
->bus
, p_slot
->device
, index
++);
1188 func
= pciehp_slot_find(p_slot
->bus
, p_slot
->device
, 0);
1189 if ((func
!= NULL
) && !rc
) {
1190 rc
= remove_board(func
, p_slot
->ctrl
);
1195 update_slot_info(p_slot
);