diff options
Diffstat (limited to 'drivers/pci/hotplug/shpchp_ctrl.c')
-rw-r--r-- | drivers/pci/hotplug/shpchp_ctrl.c | 313 |
1 files changed, 89 insertions, 224 deletions
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index b709328a4145..2411f3bd08da 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c | |||
@@ -32,44 +32,46 @@ | |||
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/smp_lock.h> | 33 | #include <linux/smp_lock.h> |
34 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
35 | #include <linux/workqueue.h> | ||
35 | #include "../pci.h" | 36 | #include "../pci.h" |
36 | #include "shpchp.h" | 37 | #include "shpchp.h" |
37 | 38 | ||
38 | static void interrupt_event_handler(struct controller *ctrl); | 39 | static void interrupt_event_handler(void *data); |
39 | 40 | ||
40 | static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ | 41 | static int queue_interrupt_event(struct slot *p_slot, u32 event_type) |
41 | static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */ | 42 | { |
42 | static int event_finished; | 43 | struct event_info *info; |
43 | static unsigned long pushbutton_pending; /* = 0 */ | 44 | |
45 | info = kmalloc(sizeof(*info), GFP_ATOMIC); | ||
46 | if (!info) | ||
47 | return -ENOMEM; | ||
48 | |||
49 | info->event_type = event_type; | ||
50 | info->p_slot = p_slot; | ||
51 | INIT_WORK(&info->work, interrupt_event_handler, info); | ||
52 | |||
53 | queue_work(shpchp_wq, &info->work); | ||
54 | |||
55 | return 0; | ||
56 | } | ||
44 | 57 | ||
45 | u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) | 58 | u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) |
46 | { | 59 | { |
47 | struct controller *ctrl = (struct controller *) inst_id; | 60 | struct controller *ctrl = (struct controller *) inst_id; |
48 | struct slot *p_slot; | 61 | struct slot *p_slot; |
49 | u8 rc = 0; | 62 | u32 event_type; |
50 | u8 getstatus; | ||
51 | struct event_info *taskInfo; | ||
52 | 63 | ||
53 | /* Attention Button Change */ | 64 | /* Attention Button Change */ |
54 | dbg("shpchp: Attention button interrupt received.\n"); | 65 | dbg("shpchp: Attention button interrupt received.\n"); |
55 | 66 | ||
56 | /* This is the structure that tells the worker thread what to do */ | ||
57 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | ||
58 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 67 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
59 | |||
60 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); | 68 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); |
61 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | ||
62 | |||
63 | ctrl->next_event = (ctrl->next_event + 1) % 10; | ||
64 | taskInfo->hp_slot = hp_slot; | ||
65 | |||
66 | rc++; | ||
67 | 69 | ||
68 | /* | 70 | /* |
69 | * Button pressed - See if need to TAKE ACTION!!! | 71 | * Button pressed - See if need to TAKE ACTION!!! |
70 | */ | 72 | */ |
71 | info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); | 73 | info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); |
72 | taskInfo->event_type = INT_BUTTON_PRESS; | 74 | event_type = INT_BUTTON_PRESS; |
73 | 75 | ||
74 | if ((p_slot->state == BLINKINGON_STATE) | 76 | if ((p_slot->state == BLINKINGON_STATE) |
75 | || (p_slot->state == BLINKINGOFF_STATE)) { | 77 | || (p_slot->state == BLINKINGOFF_STATE)) { |
@@ -77,7 +79,7 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) | |||
77 | * attention again before the 5 sec. limit expires to cancel hot-add | 79 | * attention again before the 5 sec. limit expires to cancel hot-add |
78 | * or hot-remove | 80 | * or hot-remove |
79 | */ | 81 | */ |
80 | taskInfo->event_type = INT_BUTTON_CANCEL; | 82 | event_type = INT_BUTTON_CANCEL; |
81 | info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot); | 83 | info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot); |
82 | } else if ((p_slot->state == POWERON_STATE) | 84 | } else if ((p_slot->state == POWERON_STATE) |
83 | || (p_slot->state == POWEROFF_STATE)) { | 85 | || (p_slot->state == POWEROFF_STATE)) { |
@@ -85,12 +87,11 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) | |||
85 | * means that the previous attention button action to hot-add or | 87 | * means that the previous attention button action to hot-add or |
86 | * hot-remove is undergoing | 88 | * hot-remove is undergoing |
87 | */ | 89 | */ |
88 | taskInfo->event_type = INT_BUTTON_IGNORE; | 90 | event_type = INT_BUTTON_IGNORE; |
89 | info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot); | 91 | info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot); |
90 | } | 92 | } |
91 | 93 | ||
92 | if (rc) | 94 | queue_interrupt_event(p_slot, event_type); |
93 | up(&event_semaphore); /* signal event thread that new event is posted */ | ||
94 | 95 | ||
95 | return 0; | 96 | return 0; |
96 | 97 | ||
@@ -100,21 +101,12 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
100 | { | 101 | { |
101 | struct controller *ctrl = (struct controller *) inst_id; | 102 | struct controller *ctrl = (struct controller *) inst_id; |
102 | struct slot *p_slot; | 103 | struct slot *p_slot; |
103 | u8 rc = 0; | ||
104 | u8 getstatus; | 104 | u8 getstatus; |
105 | struct event_info *taskInfo; | 105 | u32 event_type; |
106 | 106 | ||
107 | /* Switch Change */ | 107 | /* Switch Change */ |
108 | dbg("shpchp: Switch interrupt received.\n"); | 108 | dbg("shpchp: Switch interrupt received.\n"); |
109 | 109 | ||
110 | /* This is the structure that tells the worker thread | ||
111 | * what to do | ||
112 | */ | ||
113 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | ||
114 | ctrl->next_event = (ctrl->next_event + 1) % 10; | ||
115 | taskInfo->hp_slot = hp_slot; | ||
116 | |||
117 | rc++; | ||
118 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 110 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
119 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); | 111 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); |
120 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 112 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
@@ -126,9 +118,9 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
126 | * Switch opened | 118 | * Switch opened |
127 | */ | 119 | */ |
128 | info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); | 120 | info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); |
129 | taskInfo->event_type = INT_SWITCH_OPEN; | 121 | event_type = INT_SWITCH_OPEN; |
130 | if (p_slot->pwr_save && p_slot->presence_save) { | 122 | if (p_slot->pwr_save && p_slot->presence_save) { |
131 | taskInfo->event_type = INT_POWER_FAULT; | 123 | event_type = INT_POWER_FAULT; |
132 | err("Surprise Removal of card\n"); | 124 | err("Surprise Removal of card\n"); |
133 | } | 125 | } |
134 | } else { | 126 | } else { |
@@ -136,34 +128,23 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
136 | * Switch closed | 128 | * Switch closed |
137 | */ | 129 | */ |
138 | info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); | 130 | info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); |
139 | taskInfo->event_type = INT_SWITCH_CLOSE; | 131 | event_type = INT_SWITCH_CLOSE; |
140 | } | 132 | } |
141 | 133 | ||
142 | if (rc) | 134 | queue_interrupt_event(p_slot, event_type); |
143 | up(&event_semaphore); /* signal event thread that new event is posted */ | ||
144 | 135 | ||
145 | return rc; | 136 | return 1; |
146 | } | 137 | } |
147 | 138 | ||
148 | u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) | 139 | u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) |
149 | { | 140 | { |
150 | struct controller *ctrl = (struct controller *) inst_id; | 141 | struct controller *ctrl = (struct controller *) inst_id; |
151 | struct slot *p_slot; | 142 | struct slot *p_slot; |
152 | u8 rc = 0; | 143 | u32 event_type; |
153 | /*u8 temp_byte;*/ | ||
154 | struct event_info *taskInfo; | ||
155 | 144 | ||
156 | /* Presence Change */ | 145 | /* Presence Change */ |
157 | dbg("shpchp: Presence/Notify input change.\n"); | 146 | dbg("shpchp: Presence/Notify input change.\n"); |
158 | 147 | ||
159 | /* This is the structure that tells the worker thread | ||
160 | * what to do | ||
161 | */ | ||
162 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | ||
163 | ctrl->next_event = (ctrl->next_event + 1) % 10; | ||
164 | taskInfo->hp_slot = hp_slot; | ||
165 | |||
166 | rc++; | ||
167 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 148 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
168 | 149 | ||
169 | /* | 150 | /* |
@@ -175,39 +156,29 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) | |||
175 | * Card Present | 156 | * Card Present |
176 | */ | 157 | */ |
177 | info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot); | 158 | info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot); |
178 | taskInfo->event_type = INT_PRESENCE_ON; | 159 | event_type = INT_PRESENCE_ON; |
179 | } else { | 160 | } else { |
180 | /* | 161 | /* |
181 | * Not Present | 162 | * Not Present |
182 | */ | 163 | */ |
183 | info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot); | 164 | info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot); |
184 | taskInfo->event_type = INT_PRESENCE_OFF; | 165 | event_type = INT_PRESENCE_OFF; |
185 | } | 166 | } |
186 | 167 | ||
187 | if (rc) | 168 | queue_interrupt_event(p_slot, event_type); |
188 | up(&event_semaphore); /* signal event thread that new event is posted */ | ||
189 | 169 | ||
190 | return rc; | 170 | return 1; |
191 | } | 171 | } |
192 | 172 | ||
193 | u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) | 173 | u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) |
194 | { | 174 | { |
195 | struct controller *ctrl = (struct controller *) inst_id; | 175 | struct controller *ctrl = (struct controller *) inst_id; |
196 | struct slot *p_slot; | 176 | struct slot *p_slot; |
197 | u8 rc = 0; | 177 | u32 event_type; |
198 | struct event_info *taskInfo; | ||
199 | 178 | ||
200 | /* Power fault */ | 179 | /* Power fault */ |
201 | dbg("shpchp: Power fault interrupt received.\n"); | 180 | dbg("shpchp: Power fault interrupt received.\n"); |
202 | 181 | ||
203 | /* This is the structure that tells the worker thread | ||
204 | * what to do | ||
205 | */ | ||
206 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | ||
207 | ctrl->next_event = (ctrl->next_event + 1) % 10; | ||
208 | taskInfo->hp_slot = hp_slot; | ||
209 | |||
210 | rc++; | ||
211 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 182 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
212 | 183 | ||
213 | if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { | 184 | if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { |
@@ -216,21 +187,21 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
216 | */ | 187 | */ |
217 | info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); | 188 | info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); |
218 | p_slot->status = 0x00; | 189 | p_slot->status = 0x00; |
219 | taskInfo->event_type = INT_POWER_FAULT_CLEAR; | 190 | event_type = INT_POWER_FAULT_CLEAR; |
220 | } else { | 191 | } else { |
221 | /* | 192 | /* |
222 | * Power fault | 193 | * Power fault |
223 | */ | 194 | */ |
224 | info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); | 195 | info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); |
225 | taskInfo->event_type = INT_POWER_FAULT; | 196 | event_type = INT_POWER_FAULT; |
226 | /* set power fault status for this board */ | 197 | /* set power fault status for this board */ |
227 | p_slot->status = 0xFF; | 198 | p_slot->status = 0xFF; |
228 | info("power fault bit %x set\n", hp_slot); | 199 | info("power fault bit %x set\n", hp_slot); |
229 | } | 200 | } |
230 | if (rc) | ||
231 | up(&event_semaphore); /* signal event thread that new event is posted */ | ||
232 | 201 | ||
233 | return rc; | 202 | queue_interrupt_event(p_slot, event_type); |
203 | |||
204 | return 1; | ||
234 | } | 205 | } |
235 | 206 | ||
236 | /* The following routines constitute the bulk of the | 207 | /* The following routines constitute the bulk of the |
@@ -521,14 +492,6 @@ static int remove_board(struct slot *p_slot) | |||
521 | } | 492 | } |
522 | 493 | ||
523 | 494 | ||
524 | static void pushbutton_helper_thread (unsigned long data) | ||
525 | { | ||
526 | pushbutton_pending = data; | ||
527 | |||
528 | up(&event_semaphore); | ||
529 | } | ||
530 | |||
531 | |||
532 | /** | 495 | /** |
533 | * shpchp_pushbutton_thread | 496 | * shpchp_pushbutton_thread |
534 | * | 497 | * |
@@ -536,90 +499,24 @@ static void pushbutton_helper_thread (unsigned long data) | |||
536 | * Handles all pending events and exits. | 499 | * Handles all pending events and exits. |
537 | * | 500 | * |
538 | */ | 501 | */ |
539 | static void shpchp_pushbutton_thread (unsigned long slot) | 502 | void shpchp_pushbutton_thread(void *data) |
540 | { | 503 | { |
541 | struct slot *p_slot = (struct slot *) slot; | 504 | struct slot *p_slot = data; |
542 | u8 getstatus; | 505 | u8 getstatus; |
543 | |||
544 | pushbutton_pending = 0; | ||
545 | |||
546 | if (!p_slot) { | ||
547 | dbg("%s: Error! slot NULL\n", __FUNCTION__); | ||
548 | return; | ||
549 | } | ||
550 | 506 | ||
551 | p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | 507 | p_slot->hpc_ops->get_power_status(p_slot, &getstatus); |
552 | if (getstatus) { | 508 | if (getstatus) { |
553 | p_slot->state = POWEROFF_STATE; | 509 | p_slot->state = POWEROFF_STATE; |
554 | |||
555 | shpchp_disable_slot(p_slot); | 510 | shpchp_disable_slot(p_slot); |
556 | p_slot->state = STATIC_STATE; | 511 | p_slot->state = STATIC_STATE; |
557 | } else { | 512 | } else { |
558 | p_slot->state = POWERON_STATE; | 513 | p_slot->state = POWERON_STATE; |
559 | |||
560 | if (shpchp_enable_slot(p_slot)) | 514 | if (shpchp_enable_slot(p_slot)) |
561 | p_slot->hpc_ops->green_led_off(p_slot); | 515 | p_slot->hpc_ops->green_led_off(p_slot); |
562 | |||
563 | p_slot->state = STATIC_STATE; | 516 | p_slot->state = STATIC_STATE; |
564 | } | 517 | } |
565 | |||
566 | return; | ||
567 | } | ||
568 | |||
569 | |||
570 | /* this is the main worker thread */ | ||
571 | static int event_thread(void* data) | ||
572 | { | ||
573 | struct controller *ctrl; | ||
574 | lock_kernel(); | ||
575 | daemonize("shpchpd_event"); | ||
576 | unlock_kernel(); | ||
577 | |||
578 | while (1) { | ||
579 | dbg("!!!!event_thread sleeping\n"); | ||
580 | down_interruptible (&event_semaphore); | ||
581 | dbg("event_thread woken finished = %d\n", event_finished); | ||
582 | if (event_finished || signal_pending(current)) | ||
583 | break; | ||
584 | /* Do stuff here */ | ||
585 | if (pushbutton_pending) | ||
586 | shpchp_pushbutton_thread(pushbutton_pending); | ||
587 | else | ||
588 | list_for_each_entry(ctrl, &shpchp_ctrl_list, ctrl_list) | ||
589 | interrupt_event_handler(ctrl); | ||
590 | } | ||
591 | dbg("event_thread signals exit\n"); | ||
592 | up(&event_exit); | ||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | int shpchp_event_start_thread (void) | ||
597 | { | ||
598 | int pid; | ||
599 | |||
600 | /* initialize our semaphores */ | ||
601 | init_MUTEX_LOCKED(&event_exit); | ||
602 | event_finished=0; | ||
603 | |||
604 | init_MUTEX_LOCKED(&event_semaphore); | ||
605 | pid = kernel_thread(event_thread, NULL, 0); | ||
606 | |||
607 | if (pid < 0) { | ||
608 | err ("Can't start up our event thread\n"); | ||
609 | return -1; | ||
610 | } | ||
611 | return 0; | ||
612 | } | ||
613 | |||
614 | |||
615 | void shpchp_event_stop_thread (void) | ||
616 | { | ||
617 | event_finished = 1; | ||
618 | up(&event_semaphore); | ||
619 | down(&event_exit); | ||
620 | } | 518 | } |
621 | 519 | ||
622 | |||
623 | static int update_slot_info (struct slot *slot) | 520 | static int update_slot_info (struct slot *slot) |
624 | { | 521 | { |
625 | struct hotplug_slot_info *info; | 522 | struct hotplug_slot_info *info; |
@@ -639,91 +536,59 @@ static int update_slot_info (struct slot *slot) | |||
639 | return result; | 536 | return result; |
640 | } | 537 | } |
641 | 538 | ||
642 | static void interrupt_event_handler(struct controller *ctrl) | 539 | static void interrupt_event_handler(void *data) |
643 | { | 540 | { |
644 | int loop = 0; | 541 | struct event_info *info = data; |
645 | int change = 1; | 542 | struct slot *p_slot = info->p_slot; |
646 | u8 hp_slot; | ||
647 | u8 getstatus; | 543 | u8 getstatus; |
648 | struct slot *p_slot; | ||
649 | 544 | ||
650 | while (change) { | 545 | switch (info->event_type) { |
651 | change = 0; | 546 | case INT_BUTTON_CANCEL: |
652 | 547 | dbg("%s: button cancel\n", __FUNCTION__); | |
653 | for (loop = 0; loop < 10; loop++) { | 548 | cancel_delayed_work(&p_slot->work); |
654 | if (ctrl->event_queue[loop].event_type != 0) { | 549 | switch (p_slot->state) { |
655 | dbg("%s:loop %x event_type %x\n", __FUNCTION__, loop, | 550 | case BLINKINGOFF_STATE: |
656 | ctrl->event_queue[loop].event_type); | 551 | p_slot->hpc_ops->green_led_on(p_slot); |
657 | hp_slot = ctrl->event_queue[loop].hp_slot; | 552 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
658 | 553 | break; | |
659 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 554 | case BLINKINGON_STATE: |
660 | 555 | p_slot->hpc_ops->green_led_off(p_slot); | |
661 | if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { | 556 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
662 | dbg("%s: button cancel\n", __FUNCTION__); | 557 | break; |
663 | del_timer(&p_slot->task_event); | 558 | default: |
664 | 559 | warn("Not a valid state\n"); | |
665 | switch (p_slot->state) { | 560 | return; |
666 | case BLINKINGOFF_STATE: | 561 | } |
667 | p_slot->hpc_ops->green_led_on(p_slot); | 562 | info(msg_button_cancel, p_slot->number); |
668 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 563 | p_slot->state = STATIC_STATE; |
669 | break; | 564 | break; |
670 | case BLINKINGON_STATE: | 565 | case INT_BUTTON_PRESS: |
671 | p_slot->hpc_ops->green_led_off(p_slot); | 566 | dbg("%s: Button pressed\n", __FUNCTION__); |
672 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 567 | p_slot->hpc_ops->get_power_status(p_slot, &getstatus); |
673 | break; | 568 | if (getstatus) { |
674 | default: | 569 | p_slot->state = BLINKINGOFF_STATE; |
675 | warn("Not a valid state\n"); | 570 | info(msg_button_off, p_slot->number); |
676 | return; | 571 | } else { |
677 | } | 572 | p_slot->state = BLINKINGON_STATE; |
678 | info(msg_button_cancel, p_slot->number); | 573 | info(msg_button_on, p_slot->number); |
679 | p_slot->state = STATIC_STATE; | 574 | } |
680 | } else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) { | 575 | /* blink green LED and turn off amber */ |
681 | /* Button Pressed (No action on 1st press...) */ | 576 | p_slot->hpc_ops->green_led_blink(p_slot); |
682 | dbg("%s: Button pressed\n", __FUNCTION__); | 577 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
683 | |||
684 | p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | ||
685 | if (getstatus) { | ||
686 | /* slot is on */ | ||
687 | dbg("%s: slot is on\n", __FUNCTION__); | ||
688 | p_slot->state = BLINKINGOFF_STATE; | ||
689 | info(msg_button_off, p_slot->number); | ||
690 | } else { | ||
691 | /* slot is off */ | ||
692 | dbg("%s: slot is off\n", __FUNCTION__); | ||
693 | p_slot->state = BLINKINGON_STATE; | ||
694 | info(msg_button_on, p_slot->number); | ||
695 | } | ||
696 | |||
697 | /* blink green LED and turn off amber */ | ||
698 | p_slot->hpc_ops->green_led_blink(p_slot); | ||
699 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | ||
700 | |||
701 | init_timer(&p_slot->task_event); | ||
702 | p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ | ||
703 | p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; | ||
704 | p_slot->task_event.data = (unsigned long) p_slot; | ||
705 | |||
706 | dbg("%s: add_timer p_slot = %p\n", __FUNCTION__,(void *) p_slot); | ||
707 | add_timer(&p_slot->task_event); | ||
708 | } else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { | ||
709 | /***********POWER FAULT********************/ | ||
710 | dbg("%s: power fault\n", __FUNCTION__); | ||
711 | p_slot->hpc_ops->set_attention_status(p_slot, 1); | ||
712 | p_slot->hpc_ops->green_led_off(p_slot); | ||
713 | } else { | ||
714 | /* refresh notification */ | ||
715 | if (p_slot) | ||
716 | update_slot_info(p_slot); | ||
717 | } | ||
718 | |||
719 | ctrl->event_queue[loop].event_type = 0; | ||
720 | 578 | ||
721 | change = 1; | 579 | queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ); |
722 | } | 580 | break; |
723 | } /* End of FOR loop */ | 581 | case INT_POWER_FAULT: |
582 | dbg("%s: power fault\n", __FUNCTION__); | ||
583 | p_slot->hpc_ops->set_attention_status(p_slot, 1); | ||
584 | p_slot->hpc_ops->green_led_off(p_slot); | ||
585 | break; | ||
586 | default: | ||
587 | update_slot_info(p_slot); | ||
588 | break; | ||
724 | } | 589 | } |
725 | 590 | ||
726 | return; | 591 | kfree(info); |
727 | } | 592 | } |
728 | 593 | ||
729 | 594 | ||