aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/pciehp_ctrl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug/pciehp_ctrl.c')
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c616
1 files changed, 282 insertions, 334 deletions
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 4283ef56dbd9..7f22caa70178 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -32,92 +32,61 @@
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 "pciehp.h" 37#include "pciehp.h"
37 38
38static void interrupt_event_handler(struct controller *ctrl); 39static void interrupt_event_handler(struct work_struct *work);
40static int pciehp_enable_slot(struct slot *p_slot);
41static int pciehp_disable_slot(struct slot *p_slot);
39 42
40static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ 43static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
41static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */
42static int event_finished;
43static unsigned long pushbutton_pending; /* = 0 */
44static unsigned long surprise_rm_pending; /* = 0 */
45
46static inline char *slot_name(struct slot *p_slot)
47{ 44{
48 return p_slot->hotplug_slot->name; 45 struct event_info *info;
46
47 info = kmalloc(sizeof(*info), GFP_ATOMIC);
48 if (!info)
49 return -ENOMEM;
50
51 info->event_type = event_type;
52 info->p_slot = p_slot;
53 INIT_WORK(&info->work, interrupt_event_handler);
54
55 schedule_work(&info->work);
56
57 return 0;
49} 58}
50 59
51u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl) 60u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl)
52{ 61{
53 struct slot *p_slot; 62 struct slot *p_slot;
54 u8 rc = 0; 63 u32 event_type;
55 u8 getstatus;
56 struct event_info *taskInfo;
57 64
58 /* Attention Button Change */ 65 /* Attention Button Change */
59 dbg("pciehp: Attention button interrupt received.\n"); 66 dbg("pciehp: Attention button interrupt received.\n");
60
61 /* This is the structure that tells the worker thread what to do */
62 taskInfo = &(ctrl->event_queue[ctrl->next_event]);
63 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
64
65 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
66
67 ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
68 taskInfo->hp_slot = hp_slot;
69 67
70 rc++; 68 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
71 69
72 /* 70 /*
73 * Button pressed - See if need to TAKE ACTION!!! 71 * Button pressed - See if need to TAKE ACTION!!!
74 */ 72 */
75 info("Button pressed on Slot(%s)\n", slot_name(p_slot)); 73 info("Button pressed on Slot(%s)\n", p_slot->name);
76 taskInfo->event_type = INT_BUTTON_PRESS; 74 event_type = INT_BUTTON_PRESS;
77
78 if ((p_slot->state == BLINKINGON_STATE)
79 || (p_slot->state == BLINKINGOFF_STATE)) {
80 /* Cancel if we are still blinking; this means that we press the
81 * attention again before the 5 sec. limit expires to cancel hot-add
82 * or hot-remove
83 */
84 taskInfo->event_type = INT_BUTTON_CANCEL;
85 info("Button cancel on Slot(%s)\n", slot_name(p_slot));
86 } else if ((p_slot->state == POWERON_STATE)
87 || (p_slot->state == POWEROFF_STATE)) {
88 /* Ignore if the slot is on power-on or power-off state; this
89 * means that the previous attention button action to hot-add or
90 * hot-remove is undergoing
91 */
92 taskInfo->event_type = INT_BUTTON_IGNORE;
93 info("Button ignore on Slot(%s)\n", slot_name(p_slot));
94 }
95 75
96 if (rc) 76 queue_interrupt_event(p_slot, event_type);
97 up(&event_semaphore); /* signal event thread that new event is posted */
98 77
99 return 0; 78 return 0;
100
101} 79}
102 80
103u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl) 81u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
104{ 82{
105 struct slot *p_slot; 83 struct slot *p_slot;
106 u8 rc = 0;
107 u8 getstatus; 84 u8 getstatus;
108 struct event_info *taskInfo; 85 u32 event_type;
109 86
110 /* Switch Change */ 87 /* Switch Change */
111 dbg("pciehp: Switch interrupt received.\n"); 88 dbg("pciehp: Switch interrupt received.\n");
112 89
113 /* This is the structure that tells the worker thread
114 * what to do
115 */
116 taskInfo = &(ctrl->event_queue[ctrl->next_event]);
117 ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
118 taskInfo->hp_slot = hp_slot;
119
120 rc++;
121 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 90 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
122 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 91 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
123 92
@@ -125,39 +94,30 @@ u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
125 /* 94 /*
126 * Switch opened 95 * Switch opened
127 */ 96 */
128 info("Latch open on Slot(%s)\n", slot_name(p_slot)); 97 info("Latch open on Slot(%s)\n", p_slot->name);
129 taskInfo->event_type = INT_SWITCH_OPEN; 98 event_type = INT_SWITCH_OPEN;
130 } else { 99 } else {
131 /* 100 /*
132 * Switch closed 101 * Switch closed
133 */ 102 */
134 info("Latch close on Slot(%s)\n", slot_name(p_slot)); 103 info("Latch close on Slot(%s)\n", p_slot->name);
135 taskInfo->event_type = INT_SWITCH_CLOSE; 104 event_type = INT_SWITCH_CLOSE;
136 } 105 }
137 106
138 if (rc) 107 queue_interrupt_event(p_slot, event_type);
139 up(&event_semaphore); /* signal event thread that new event is posted */
140 108
141 return rc; 109 return 1;
142} 110}
143 111
144u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl) 112u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
145{ 113{
146 struct slot *p_slot; 114 struct slot *p_slot;
147 u8 presence_save, rc = 0; 115 u32 event_type;
148 struct event_info *taskInfo; 116 u8 presence_save;
149 117
150 /* Presence Change */ 118 /* Presence Change */
151 dbg("pciehp: Presence/Notify input change.\n"); 119 dbg("pciehp: Presence/Notify input change.\n");
152 120
153 /* This is the structure that tells the worker thread
154 * what to do
155 */
156 taskInfo = &(ctrl->event_queue[ctrl->next_event]);
157 ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
158 taskInfo->hp_slot = hp_slot;
159
160 rc++;
161 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 121 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
162 122
163 /* Switch is open, assume a presence change 123 /* Switch is open, assume a presence change
@@ -168,59 +128,49 @@ u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
168 /* 128 /*
169 * Card Present 129 * Card Present
170 */ 130 */
171 info("Card present on Slot(%s)\n", slot_name(p_slot)); 131 info("Card present on Slot(%s)\n", p_slot->name);
172 taskInfo->event_type = INT_PRESENCE_ON; 132 event_type = INT_PRESENCE_ON;
173 } else { 133 } else {
174 /* 134 /*
175 * Not Present 135 * Not Present
176 */ 136 */
177 info("Card not present on Slot(%s)\n", slot_name(p_slot)); 137 info("Card not present on Slot(%s)\n", p_slot->name);
178 taskInfo->event_type = INT_PRESENCE_OFF; 138 event_type = INT_PRESENCE_OFF;
179 } 139 }
180 140
181 if (rc) 141 queue_interrupt_event(p_slot, event_type);
182 up(&event_semaphore); /* signal event thread that new event is posted */
183 142
184 return rc; 143 return 1;
185} 144}
186 145
187u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl) 146u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
188{ 147{
189 struct slot *p_slot; 148 struct slot *p_slot;
190 u8 rc = 0; 149 u32 event_type;
191 struct event_info *taskInfo;
192 150
193 /* power fault */ 151 /* power fault */
194 dbg("pciehp: Power fault interrupt received.\n"); 152 dbg("pciehp: Power fault interrupt received.\n");
195 153
196 /* this is the structure that tells the worker thread
197 * what to do
198 */
199 taskInfo = &(ctrl->event_queue[ctrl->next_event]);
200 ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
201 taskInfo->hp_slot = hp_slot;
202
203 rc++;
204 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 154 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
205 155
206 if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { 156 if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) {
207 /* 157 /*
208 * power fault Cleared 158 * power fault Cleared
209 */ 159 */
210 info("Power fault cleared on Slot(%s)\n", slot_name(p_slot)); 160 info("Power fault cleared on Slot(%s)\n", p_slot->name);
211 taskInfo->event_type = INT_POWER_FAULT_CLEAR; 161 event_type = INT_POWER_FAULT_CLEAR;
212 } else { 162 } else {
213 /* 163 /*
214 * power fault 164 * power fault
215 */ 165 */
216 info("Power fault on Slot(%s)\n", slot_name(p_slot)); 166 info("Power fault on Slot(%s)\n", p_slot->name);
217 taskInfo->event_type = INT_POWER_FAULT; 167 event_type = INT_POWER_FAULT;
218 info("power fault bit %x set\n", hp_slot); 168 info("power fault bit %x set\n", hp_slot);
219 } 169 }
220 if (rc)
221 up(&event_semaphore); /* signal event thread that new event is posted */
222 170
223 return rc; 171 queue_interrupt_event(p_slot, event_type);
172
173 return 1;
224} 174}
225 175
226/* The following routines constitute the bulk of the 176/* The following routines constitute the bulk of the
@@ -357,13 +307,10 @@ static int remove_board(struct slot *p_slot)
357 return 0; 307 return 0;
358} 308}
359 309
360 310struct power_work_info {
361static void pushbutton_helper_thread(unsigned long data) 311 struct slot *p_slot;
362{ 312 struct work_struct work;
363 pushbutton_pending = data; 313};
364
365 up(&event_semaphore);
366}
367 314
368/** 315/**
369 * pciehp_pushbutton_thread 316 * pciehp_pushbutton_thread
@@ -372,276 +319,214 @@ static void pushbutton_helper_thread(unsigned long data)
372 * Handles all pending events and exits. 319 * Handles all pending events and exits.
373 * 320 *
374 */ 321 */
375static void pciehp_pushbutton_thread(unsigned long slot) 322static void pciehp_power_thread(struct work_struct *work)
376{ 323{
377 struct slot *p_slot = (struct slot *) slot; 324 struct power_work_info *info =
378 u8 getstatus; 325 container_of(work, struct power_work_info, work);
379 326 struct slot *p_slot = info->p_slot;
380 pushbutton_pending = 0; 327
381 328 mutex_lock(&p_slot->lock);
382 if (!p_slot) { 329 switch (p_slot->state) {
383 dbg("%s: Error! slot NULL\n", __FUNCTION__); 330 case POWEROFF_STATE:
384 return; 331 mutex_unlock(&p_slot->lock);
385 } 332 dbg("%s: disabling bus:device(%x:%x)\n",
386 333 __FUNCTION__, p_slot->bus, p_slot->device);
387 p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
388 if (getstatus) {
389 p_slot->state = POWEROFF_STATE;
390 dbg("%s: disabling bus:device(%x:%x)\n", __FUNCTION__,
391 p_slot->bus, p_slot->device);
392
393 pciehp_disable_slot(p_slot); 334 pciehp_disable_slot(p_slot);
335 mutex_lock(&p_slot->lock);
394 p_slot->state = STATIC_STATE; 336 p_slot->state = STATIC_STATE;
395 } else { 337 break;
396 p_slot->state = POWERON_STATE; 338 case POWERON_STATE:
397 dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__, 339 mutex_unlock(&p_slot->lock);
398 p_slot->bus, p_slot->device);
399
400 if (pciehp_enable_slot(p_slot) && 340 if (pciehp_enable_slot(p_slot) &&
401 PWR_LED(p_slot->ctrl->ctrlcap)) 341 PWR_LED(p_slot->ctrl->ctrlcap))
402 p_slot->hpc_ops->green_led_off(p_slot); 342 p_slot->hpc_ops->green_led_off(p_slot);
403 343 mutex_lock(&p_slot->lock);
404 p_slot->state = STATIC_STATE; 344 p_slot->state = STATIC_STATE;
345 break;
346 default:
347 break;
405 } 348 }
349 mutex_unlock(&p_slot->lock);
406 350
407 return; 351 kfree(info);
408} 352}
409 353
410/** 354void pciehp_queue_pushbutton_work(struct work_struct *work)
411 * pciehp_surprise_rm_thread
412 *
413 * Scheduled procedure to handle blocking stuff for the surprise removal
414 * Handles all pending events and exits.
415 *
416 */
417static void pciehp_surprise_rm_thread(unsigned long slot)
418{ 355{
419 struct slot *p_slot = (struct slot *) slot; 356 struct slot *p_slot = container_of(work, struct slot, work.work);
420 u8 getstatus; 357 struct power_work_info *info;
421
422 surprise_rm_pending = 0;
423 358
424 if (!p_slot) { 359 info = kmalloc(sizeof(*info), GFP_KERNEL);
425 dbg("%s: Error! slot NULL\n", __FUNCTION__); 360 if (!info) {
361 err("%s: Cannot allocate memory\n", __FUNCTION__);
426 return; 362 return;
427 } 363 }
364 info->p_slot = p_slot;
365 INIT_WORK(&info->work, pciehp_power_thread);
428 366
429 p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); 367 mutex_lock(&p_slot->lock);
430 if (!getstatus) { 368 switch (p_slot->state) {
369 case BLINKINGOFF_STATE:
431 p_slot->state = POWEROFF_STATE; 370 p_slot->state = POWEROFF_STATE;
432 dbg("%s: removing bus:device(%x:%x)\n", 371 break;
433 __FUNCTION__, p_slot->bus, p_slot->device); 372 case BLINKINGON_STATE:
434
435 pciehp_disable_slot(p_slot);
436 p_slot->state = STATIC_STATE;
437 } else {
438 p_slot->state = POWERON_STATE; 373 p_slot->state = POWERON_STATE;
439 dbg("%s: adding bus:device(%x:%x)\n", 374 break;
440 __FUNCTION__, p_slot->bus, p_slot->device); 375 default:
441 376 goto out;
442 if (pciehp_enable_slot(p_slot) &&
443 PWR_LED(p_slot->ctrl->ctrlcap))
444 p_slot->hpc_ops->green_led_off(p_slot);
445
446 p_slot->state = STATIC_STATE;
447 } 377 }
448 378 queue_work(pciehp_wq, &info->work);
449 return; 379 out:
380 mutex_unlock(&p_slot->lock);
450} 381}
451 382
452
453
454/* this is the main worker thread */
455static int event_thread(void* data)
456{
457 struct controller *ctrl;
458 lock_kernel();
459 daemonize("pciehpd_event");
460
461 unlock_kernel();
462
463 while (1) {
464 dbg("!!!!event_thread sleeping\n");
465 down_interruptible (&event_semaphore);
466 dbg("event_thread woken finished = %d\n", event_finished);
467 if (event_finished || signal_pending(current))
468 break;
469 /* Do stuff here */
470 if (pushbutton_pending)
471 pciehp_pushbutton_thread(pushbutton_pending);
472 else if (surprise_rm_pending)
473 pciehp_surprise_rm_thread(surprise_rm_pending);
474 else
475 for (ctrl = pciehp_ctrl_list; ctrl; ctrl=ctrl->next)
476 interrupt_event_handler(ctrl);
477 }
478 dbg("event_thread signals exit\n");
479 up(&event_exit);
480 return 0;
481}
482
483int pciehp_event_start_thread(void)
484{
485 int pid;
486
487 /* initialize our semaphores */
488 init_MUTEX_LOCKED(&event_exit);
489 event_finished=0;
490
491 init_MUTEX_LOCKED(&event_semaphore);
492 pid = kernel_thread(event_thread, NULL, 0);
493
494 if (pid < 0) {
495 err ("Can't start up our event thread\n");
496 return -1;
497 }
498 return 0;
499}
500
501
502void pciehp_event_stop_thread(void)
503{
504 event_finished = 1;
505 up(&event_semaphore);
506 down(&event_exit);
507}
508
509
510static int update_slot_info(struct slot *slot) 383static int update_slot_info(struct slot *slot)
511{ 384{
512 struct hotplug_slot_info *info; 385 struct hotplug_slot_info *info;
513 /* char buffer[SLOT_NAME_SIZE]; */
514 int result; 386 int result;
515 387
516 info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); 388 info = kmalloc(sizeof(*info), GFP_KERNEL);
517 if (!info) 389 if (!info)
518 return -ENOMEM; 390 return -ENOMEM;
519 391
520 /* make_slot_name (&buffer[0], SLOT_NAME_SIZE, slot); */
521
522 slot->hpc_ops->get_power_status(slot, &(info->power_status)); 392 slot->hpc_ops->get_power_status(slot, &(info->power_status));
523 slot->hpc_ops->get_attention_status(slot, &(info->attention_status)); 393 slot->hpc_ops->get_attention_status(slot, &(info->attention_status));
524 slot->hpc_ops->get_latch_status(slot, &(info->latch_status)); 394 slot->hpc_ops->get_latch_status(slot, &(info->latch_status));
525 slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status)); 395 slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status));
526 396
527 /* result = pci_hp_change_slot_info(buffer, info); */
528 result = pci_hp_change_slot_info(slot->hotplug_slot, info); 397 result = pci_hp_change_slot_info(slot->hotplug_slot, info);
529 kfree (info); 398 kfree (info);
530 return result; 399 return result;
531} 400}
532 401
533static void interrupt_event_handler(struct controller *ctrl) 402/*
403 * Note: This function must be called with slot->lock held
404 */
405static void handle_button_press_event(struct slot *p_slot)
534{ 406{
535 int loop = 0; 407 struct controller *ctrl = p_slot->ctrl;
536 int change = 1;
537 u8 hp_slot;
538 u8 getstatus; 408 u8 getstatus;
539 struct slot *p_slot;
540 409
541 while (change) { 410 switch (p_slot->state) {
542 change = 0; 411 case STATIC_STATE:
543 412 p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
544 for (loop = 0; loop < MAX_EVENTS; loop++) { 413 if (getstatus) {
545 if (ctrl->event_queue[loop].event_type != 0) { 414 p_slot->state = BLINKINGOFF_STATE;
546 hp_slot = ctrl->event_queue[loop].hp_slot; 415 info("PCI slot #%s - powering off due to button "
547 416 "press.\n", p_slot->name);
548 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 417 } else {
549 418 p_slot->state = BLINKINGON_STATE;
550 if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { 419 info("PCI slot #%s - powering on due to button "
551 dbg("button cancel\n"); 420 "press.\n", p_slot->name);
552 del_timer(&p_slot->task_event); 421 }
553 422 /* blink green LED and turn off amber */
554 switch (p_slot->state) { 423 if (PWR_LED(ctrl->ctrlcap))
555 case BLINKINGOFF_STATE: 424 p_slot->hpc_ops->green_led_blink(p_slot);
556 if (PWR_LED(ctrl->ctrlcap)) 425 if (ATTN_LED(ctrl->ctrlcap))
557 p_slot->hpc_ops->green_led_on(p_slot); 426 p_slot->hpc_ops->set_attention_status(p_slot, 0);
558 427
559 if (ATTN_LED(ctrl->ctrlcap)) 428 schedule_delayed_work(&p_slot->work, 5*HZ);
560 p_slot->hpc_ops->set_attention_status(p_slot, 0); 429 break;
561 break; 430 case BLINKINGOFF_STATE:
562 case BLINKINGON_STATE: 431 case BLINKINGON_STATE:
563 if (PWR_LED(ctrl->ctrlcap)) 432 /*
564 p_slot->hpc_ops->green_led_off(p_slot); 433 * Cancel if we are still blinking; this means that we
565 434 * press the attention again before the 5 sec. limit
566 if (ATTN_LED(ctrl->ctrlcap)) 435 * expires to cancel hot-add or hot-remove
567 p_slot->hpc_ops->set_attention_status(p_slot, 0); 436 */
568 break; 437 info("Button cancel on Slot(%s)\n", p_slot->name);
569 default: 438 dbg("%s: button cancel\n", __FUNCTION__);
570 warn("Not a valid state\n"); 439 cancel_delayed_work(&p_slot->work);
571 return; 440 if (p_slot->state == BLINKINGOFF_STATE) {
572 } 441 if (PWR_LED(ctrl->ctrlcap))
573 info("PCI slot #%s - action canceled due to button press.\n", slot_name(p_slot)); 442 p_slot->hpc_ops->green_led_on(p_slot);
574 p_slot->state = STATIC_STATE; 443 } else {
575 } 444 if (PWR_LED(ctrl->ctrlcap))
576 /* ***********Button Pressed (No action on 1st press...) */ 445 p_slot->hpc_ops->green_led_off(p_slot);
577 else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) { 446 }
578 447 if (ATTN_LED(ctrl->ctrlcap))
579 if (ATTN_BUTTN(ctrl->ctrlcap)) { 448 p_slot->hpc_ops->set_attention_status(p_slot, 0);
580 dbg("Button pressed\n"); 449 info("PCI slot #%s - action canceled due to button press\n",
581 p_slot->hpc_ops->get_power_status(p_slot, &getstatus); 450 p_slot->name);
582 if (getstatus) { 451 p_slot->state = STATIC_STATE;
583 /* slot is on */ 452 break;
584 dbg("slot is on\n"); 453 case POWEROFF_STATE:
585 p_slot->state = BLINKINGOFF_STATE; 454 case POWERON_STATE:
586 info("PCI slot #%s - powering off due to button press.\n", slot_name(p_slot)); 455 /*
587 } else { 456 * Ignore if the slot is on power-on or power-off state;
588 /* slot is off */ 457 * this means that the previous attention button action
589 dbg("slot is off\n"); 458 * to hot-add or hot-remove is undergoing
590 p_slot->state = BLINKINGON_STATE; 459 */
591 info("PCI slot #%s - powering on due to button press.\n", slot_name(p_slot)); 460 info("Button ignore on Slot(%s)\n", p_slot->name);
592 } 461 update_slot_info(p_slot);
593 462 break;
594 /* blink green LED and turn off amber */ 463 default:
595 if (PWR_LED(ctrl->ctrlcap)) 464 warn("Not a valid state\n");
596 p_slot->hpc_ops->green_led_blink(p_slot); 465 break;
597
598 if (ATTN_LED(ctrl->ctrlcap))
599 p_slot->hpc_ops->set_attention_status(p_slot, 0);
600
601 init_timer(&p_slot->task_event);
602 p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */
603 p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
604 p_slot->task_event.data = (unsigned long) p_slot;
605
606 add_timer(&p_slot->task_event);
607 }
608 }
609 /***********POWER FAULT********************/
610 else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
611 if (POWER_CTRL(ctrl->ctrlcap)) {
612 dbg("power fault\n");
613 if (ATTN_LED(ctrl->ctrlcap))
614 p_slot->hpc_ops->set_attention_status(p_slot, 1);
615
616 if (PWR_LED(ctrl->ctrlcap))
617 p_slot->hpc_ops->green_led_off(p_slot);
618 }
619 }
620 /***********SURPRISE REMOVAL********************/
621 else if ((ctrl->event_queue[loop].event_type == INT_PRESENCE_ON) ||
622 (ctrl->event_queue[loop].event_type == INT_PRESENCE_OFF)) {
623 if (HP_SUPR_RM(ctrl->ctrlcap)) {
624 dbg("Surprise Removal\n");
625 if (p_slot) {
626 surprise_rm_pending = (unsigned long) p_slot;
627 up(&event_semaphore);
628 update_slot_info(p_slot);
629 }
630 }
631 } else {
632 /* refresh notification */
633 if (p_slot)
634 update_slot_info(p_slot);
635 }
636
637 ctrl->event_queue[loop].event_type = 0;
638
639 change = 1;
640 }
641 } /* End of FOR loop */
642 } 466 }
643} 467}
644 468
469/*
470 * Note: This function must be called with slot->lock held
471 */
472static void handle_surprise_event(struct slot *p_slot)
473{
474 u8 getstatus;
475 struct power_work_info *info;
476
477 info = kmalloc(sizeof(*info), GFP_KERNEL);
478 if (!info) {
479 err("%s: Cannot allocate memory\n", __FUNCTION__);
480 return;
481 }
482 info->p_slot = p_slot;
483 INIT_WORK(&info->work, pciehp_power_thread);
484
485 p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
486 if (!getstatus)
487 p_slot->state = POWEROFF_STATE;
488 else
489 p_slot->state = POWERON_STATE;
490
491 queue_work(pciehp_wq, &info->work);
492}
493
494static void interrupt_event_handler(struct work_struct *work)
495{
496 struct event_info *info = container_of(work, struct event_info, work);
497 struct slot *p_slot = info->p_slot;
498 struct controller *ctrl = p_slot->ctrl;
499
500 mutex_lock(&p_slot->lock);
501 switch (info->event_type) {
502 case INT_BUTTON_PRESS:
503 handle_button_press_event(p_slot);
504 break;
505 case INT_POWER_FAULT:
506 if (!POWER_CTRL(ctrl->ctrlcap))
507 break;
508 if (ATTN_LED(ctrl->ctrlcap))
509 p_slot->hpc_ops->set_attention_status(p_slot, 1);
510 if (PWR_LED(ctrl->ctrlcap))
511 p_slot->hpc_ops->green_led_off(p_slot);
512 break;
513 case INT_PRESENCE_ON:
514 case INT_PRESENCE_OFF:
515 if (!HP_SUPR_RM(ctrl->ctrlcap))
516 break;
517 dbg("Surprise Removal\n");
518 update_slot_info(p_slot);
519 handle_surprise_event(p_slot);
520 break;
521 default:
522 update_slot_info(p_slot);
523 break;
524 }
525 mutex_unlock(&p_slot->lock);
526
527 kfree(info);
528}
529
645int pciehp_enable_slot(struct slot *p_slot) 530int pciehp_enable_slot(struct slot *p_slot)
646{ 531{
647 u8 getstatus = 0; 532 u8 getstatus = 0;
@@ -653,7 +538,7 @@ int pciehp_enable_slot(struct slot *p_slot)
653 rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); 538 rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
654 if (rc || !getstatus) { 539 if (rc || !getstatus) {
655 info("%s: no adapter on slot(%s)\n", __FUNCTION__, 540 info("%s: no adapter on slot(%s)\n", __FUNCTION__,
656 slot_name(p_slot)); 541 p_slot->name);
657 mutex_unlock(&p_slot->ctrl->crit_sect); 542 mutex_unlock(&p_slot->ctrl->crit_sect);
658 return -ENODEV; 543 return -ENODEV;
659 } 544 }
@@ -661,7 +546,7 @@ int pciehp_enable_slot(struct slot *p_slot)
661 rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 546 rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
662 if (rc || getstatus) { 547 if (rc || getstatus) {
663 info("%s: latch open on slot(%s)\n", __FUNCTION__, 548 info("%s: latch open on slot(%s)\n", __FUNCTION__,
664 slot_name(p_slot)); 549 p_slot->name);
665 mutex_unlock(&p_slot->ctrl->crit_sect); 550 mutex_unlock(&p_slot->ctrl->crit_sect);
666 return -ENODEV; 551 return -ENODEV;
667 } 552 }
@@ -671,7 +556,7 @@ int pciehp_enable_slot(struct slot *p_slot)
671 rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); 556 rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
672 if (rc || getstatus) { 557 if (rc || getstatus) {
673 info("%s: already enabled on slot(%s)\n", __FUNCTION__, 558 info("%s: already enabled on slot(%s)\n", __FUNCTION__,
674 slot_name(p_slot)); 559 p_slot->name);
675 mutex_unlock(&p_slot->ctrl->crit_sect); 560 mutex_unlock(&p_slot->ctrl->crit_sect);
676 return -EINVAL; 561 return -EINVAL;
677 } 562 }
@@ -706,7 +591,7 @@ int pciehp_disable_slot(struct slot *p_slot)
706 ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); 591 ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
707 if (ret || !getstatus) { 592 if (ret || !getstatus) {
708 info("%s: no adapter on slot(%s)\n", __FUNCTION__, 593 info("%s: no adapter on slot(%s)\n", __FUNCTION__,
709 slot_name(p_slot)); 594 p_slot->name);
710 mutex_unlock(&p_slot->ctrl->crit_sect); 595 mutex_unlock(&p_slot->ctrl->crit_sect);
711 return -ENODEV; 596 return -ENODEV;
712 } 597 }
@@ -716,7 +601,7 @@ int pciehp_disable_slot(struct slot *p_slot)
716 ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 601 ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
717 if (ret || getstatus) { 602 if (ret || getstatus) {
718 info("%s: latch open on slot(%s)\n", __FUNCTION__, 603 info("%s: latch open on slot(%s)\n", __FUNCTION__,
719 slot_name(p_slot)); 604 p_slot->name);
720 mutex_unlock(&p_slot->ctrl->crit_sect); 605 mutex_unlock(&p_slot->ctrl->crit_sect);
721 return -ENODEV; 606 return -ENODEV;
722 } 607 }
@@ -726,7 +611,7 @@ int pciehp_disable_slot(struct slot *p_slot)
726 ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); 611 ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
727 if (ret || !getstatus) { 612 if (ret || !getstatus) {
728 info("%s: already disabled slot(%s)\n", __FUNCTION__, 613 info("%s: already disabled slot(%s)\n", __FUNCTION__,
729 slot_name(p_slot)); 614 p_slot->name);
730 mutex_unlock(&p_slot->ctrl->crit_sect); 615 mutex_unlock(&p_slot->ctrl->crit_sect);
731 return -EINVAL; 616 return -EINVAL;
732 } 617 }
@@ -739,3 +624,66 @@ int pciehp_disable_slot(struct slot *p_slot)
739 return ret; 624 return ret;
740} 625}
741 626
627int pciehp_sysfs_enable_slot(struct slot *p_slot)
628{
629 int retval = -ENODEV;
630
631 mutex_lock(&p_slot->lock);
632 switch (p_slot->state) {
633 case BLINKINGON_STATE:
634 cancel_delayed_work(&p_slot->work);
635 case STATIC_STATE:
636 p_slot->state = POWERON_STATE;
637 mutex_unlock(&p_slot->lock);
638 retval = pciehp_enable_slot(p_slot);
639 mutex_lock(&p_slot->lock);
640 p_slot->state = STATIC_STATE;
641 break;
642 case POWERON_STATE:
643 info("Slot %s is already in powering on state\n",
644 p_slot->name);
645 break;
646 case BLINKINGOFF_STATE:
647 case POWEROFF_STATE:
648 info("Already enabled on slot %s\n", p_slot->name);
649 break;
650 default:
651 err("Not a valid state on slot %s\n", p_slot->name);
652 break;
653 }
654 mutex_unlock(&p_slot->lock);
655
656 return retval;
657}
658
659int pciehp_sysfs_disable_slot(struct slot *p_slot)
660{
661 int retval = -ENODEV;
662
663 mutex_lock(&p_slot->lock);
664 switch (p_slot->state) {
665 case BLINKINGOFF_STATE:
666 cancel_delayed_work(&p_slot->work);
667 case STATIC_STATE:
668 p_slot->state = POWEROFF_STATE;
669 mutex_unlock(&p_slot->lock);
670 retval = pciehp_disable_slot(p_slot);
671 mutex_lock(&p_slot->lock);
672 p_slot->state = STATIC_STATE;
673 break;
674 case POWEROFF_STATE:
675 info("Slot %s is already in powering off state\n",
676 p_slot->name);
677 break;
678 case BLINKINGON_STATE:
679 case POWERON_STATE:
680 info("Already disabled on slot %s\n", p_slot->name);
681 break;
682 default:
683 err("Not a valid state on slot %s\n", p_slot->name);
684 break;
685 }
686 mutex_unlock(&p_slot->lock);
687
688 return retval;
689}