[PATCH] patch 1/8] pciehp: use the PCI core for hotplug resource management
[safe/jmp/linux-2.6] / drivers / pci / hotplug / pciehp_ctrl.c
1 /*
2  * PCI Express Hot Plug Controller Driver
3  *
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
8  *
9  * All rights reserved.
10  *
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.
15  *
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
20  * details.
21  *
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.
25  *
26  * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
27  *
28  */
29
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>
41 #include "../pci.h"
42 #include "pciehp.h"
43 #include "pciehprm.h"
44
45 static void interrupt_event_handler(struct controller *ctrl);
46
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 */
52
53 u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id)
54 {
55         struct controller *ctrl = (struct controller *) inst_id;
56         struct slot *p_slot;
57         u8 rc = 0;
58         u8 getstatus;
59         struct pci_func *func;
60         struct event_info *taskInfo;
61
62         /* Attention Button Change */
63         dbg("pciehp:  Attention button interrupt received.\n");
64         
65         func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
66
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);
70
71         p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
72         p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
73         
74         ctrl->next_event = (ctrl->next_event + 1) % 10;
75         taskInfo->hp_slot = hp_slot;
76
77         rc++;
78
79         /*
80          *  Button pressed - See if need to TAKE ACTION!!!
81          */
82         info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot);
83         taskInfo->event_type = INT_BUTTON_PRESS;
84
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
89                  * or hot-remove
90                  */
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
98                  */
99                 taskInfo->event_type = INT_BUTTON_IGNORE;
100                 info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot);
101         }
102
103         if (rc)
104                 up(&event_semaphore);   /* signal event thread that new event is posted */
105
106         return 0;
107
108 }
109
110 u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id)
111 {
112         struct controller *ctrl = (struct controller *) inst_id;
113         struct slot *p_slot;
114         u8 rc = 0;
115         u8 getstatus;
116         struct pci_func *func;
117         struct event_info *taskInfo;
118
119         /* Switch Change */
120         dbg("pciehp:  Switch interrupt received.\n");
121
122         func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
123
124         /* This is the structure that tells the worker thread
125          * what to do
126          */
127         taskInfo = &(ctrl->event_queue[ctrl->next_event]);
128         ctrl->next_event = (ctrl->next_event + 1) % 10;
129         taskInfo->hp_slot = hp_slot;
130
131         rc++;
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);
135
136         if (getstatus) {
137                 /*
138                  * Switch opened
139                  */
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;
143         } else {
144                 /*
145                  *  Switch closed
146                  */
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;
150         }
151
152         if (rc)
153                 up(&event_semaphore);   /* signal event thread that new event is posted */
154
155         return rc;
156 }
157
158 u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id)
159 {
160         struct controller *ctrl = (struct controller *) inst_id;
161         struct slot *p_slot;
162         u8 rc = 0;
163         struct pci_func *func;
164         struct event_info *taskInfo;
165
166         /* Presence Change */
167         dbg("pciehp:  Presence/Notify input change.\n");
168
169         func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
170
171         /* This is the structure that tells the worker thread
172          * what to do
173          */
174         taskInfo = &(ctrl->event_queue[ctrl->next_event]);
175         ctrl->next_event = (ctrl->next_event + 1) % 10;
176         taskInfo->hp_slot = hp_slot;
177
178         rc++;
179         p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
180
181         /* Switch is open, assume a presence change
182          * Save the presence state
183          */
184         p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
185         if (func->presence_save) {
186                 /*
187                  * Card Present
188                  */
189                 info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot);
190                 taskInfo->event_type = INT_PRESENCE_ON;
191         } else {
192                 /*
193                  * Not Present
194                  */
195                 info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot);
196                 taskInfo->event_type = INT_PRESENCE_OFF;
197         }
198
199         if (rc)
200                 up(&event_semaphore);   /* signal event thread that new event is posted */
201
202         return rc;
203 }
204
205 u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
206 {
207         struct controller *ctrl = (struct controller *) inst_id;
208         struct slot *p_slot;
209         u8 rc = 0;
210         struct pci_func *func;
211         struct event_info *taskInfo;
212
213         /* power fault */
214         dbg("pciehp:  Power fault interrupt received.\n");
215
216         func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
217
218         /* this is the structure that tells the worker thread
219          * what to do
220          */
221         taskInfo = &(ctrl->event_queue[ctrl->next_event]);
222         ctrl->next_event = (ctrl->next_event + 1) % 10;
223         taskInfo->hp_slot = hp_slot;
224
225         rc++;
226         p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
227
228         if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) {
229                 /*
230                  * power fault Cleared
231                  */
232                 info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
233                 func->status = 0x00;
234                 taskInfo->event_type = INT_POWER_FAULT_CLEAR;
235         } else {
236                 /*
237                  *   power fault
238                  */
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 */
242                 func->status = 0xFF;
243                 info("power fault bit %x set\n", hp_slot);
244         }
245         if (rc)
246                 up(&event_semaphore);   /* signal event thread that new event is posted */
247
248         return rc;
249 }
250
251 /**
252  * pciehp_slot_create - Creates a node and adds it to the proper bus.
253  * @busnumber - bus where new node is to be located
254  *
255  * Returns pointer to the new node or NULL if unsuccessful
256  */
257 struct pci_func *pciehp_slot_create(u8 busnumber)
258 {
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);
263
264         if (new_slot == NULL)
265                 return new_slot;
266
267         memset(new_slot, 0, sizeof(struct pci_func));
268
269         new_slot->next = NULL;
270         new_slot->configured = 1;
271
272         if (pciehp_slot_list[busnumber] == NULL) {
273                 pciehp_slot_list[busnumber] = new_slot;
274         } else {
275                 next = pciehp_slot_list[busnumber];
276                 while (next->next != NULL)
277                         next = next->next;
278                 next->next = new_slot;
279         }
280         return new_slot;
281 }
282
283
284 /**
285  * slot_remove - Removes a node from the linked list of slots.
286  * @old_slot: slot to remove
287  *
288  * Returns 0 if successful, !0 otherwise.
289  */
290 static int slot_remove(struct pci_func * old_slot)
291 {
292         struct pci_func *next;
293
294         if (old_slot == NULL)
295                 return 1;
296
297         next = pciehp_slot_list[old_slot->bus];
298
299         if (next == NULL)
300                 return 1;
301
302         if (next == old_slot) {
303                 pciehp_slot_list[old_slot->bus] = old_slot->next;
304                 kfree(old_slot);
305                 return 0;
306         }
307
308         while ((next->next != old_slot) && (next->next != NULL)) {
309                 next = next->next;
310         }
311
312         if (next->next == old_slot) {
313                 next->next = old_slot->next;
314                 kfree(old_slot);
315                 return 0;
316         } else
317                 return 2;
318 }
319
320
321 /**
322  * bridge_slot_remove - Removes a node from the linked list of slots.
323  * @bridge: bridge to remove
324  *
325  * Returns 0 if successful, !0 otherwise.
326  */
327 static int bridge_slot_remove(struct pci_func *bridge)
328 {
329         u8 subordinateBus, secondaryBus;
330         u8 tempBus;
331         struct pci_func *next;
332
333         if (bridge == NULL)
334                 return 1;
335
336         secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF;
337         subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF;
338
339         for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {
340                 next = pciehp_slot_list[tempBus];
341
342                 while (!slot_remove(next)) {
343                         next = pciehp_slot_list[tempBus];
344                 }
345         }
346
347         next = pciehp_slot_list[bridge->bus];
348
349         if (next == NULL) {
350                 return 1;
351         }
352
353         if (next == bridge) {
354                 pciehp_slot_list[bridge->bus] = bridge->next;
355                 kfree(bridge);
356                 return 0;
357         }
358
359         while ((next->next != bridge) && (next->next != NULL)) {
360                 next = next->next;
361         }
362
363         if (next->next == bridge) {
364                 next->next = bridge->next;
365                 kfree(bridge);
366                 return 0;
367         } else
368                 return 2;
369 }
370
371
372 /**
373  * pciehp_slot_find - Looks for a node by bus, and device, multiple functions accessed
374  * @bus: bus to find
375  * @device: device to find
376  * @index: is 0 for first function found, 1 for the second...
377  *
378  * Returns pointer to the node if successful, %NULL otherwise.
379  */
380 struct pci_func *pciehp_slot_find(u8 bus, u8 device, u8 index)
381 {
382         int found = -1;
383         struct pci_func *func;
384
385         func = pciehp_slot_list[bus];
386         dbg("%s: bus %x device %x index %x\n",
387                 __FUNCTION__, bus, device, index);
388         if (func != NULL) {
389                 dbg("%s: func-> bus %x device %x function %x pci_dev %p\n",
390                         __FUNCTION__, func->bus, func->device, func->function,
391                         func->pci_dev);
392         } else
393                 dbg("%s: func == NULL\n", __FUNCTION__);
394
395         if ((func == NULL) || ((func->device == device) && (index == 0)))
396                 return func;
397
398         if (func->device == device)
399                 found++;
400
401         while (func->next != NULL) {
402                 func = func->next;
403
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,
406                         func->pci_dev);
407                 if (func->device == device)
408                         found++;
409                 dbg("%s: while loop, found %d, index %d\n", __FUNCTION__,
410                         found, index);
411
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);
415                         return func;
416                 }
417         }
418
419         return NULL;
420 }
421
422 static int is_bridge(struct pci_func * func)
423 {
424         /* Check the header type */
425         if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01)
426                 return 1;
427         else
428                 return 0;
429 }
430
431
432 /* The following routines constitute the bulk of the 
433    hotplug controller logic
434  */
435
436 static void set_slot_off(struct controller *ctrl, struct slot * pslot)
437 {
438         /* Wait for exclusive access to hardware */
439         down(&ctrl->crit_sect);
440
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);
446                         return;
447                 }
448                 wait_for_ctrl_irq (ctrl);
449         }
450
451         if (PWR_LED(ctrl->ctrlcap)) {
452                 pslot->hpc_ops->green_led_off(pslot);   
453                 wait_for_ctrl_irq (ctrl);
454         }
455
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);
460                         return;
461                 }
462                 wait_for_ctrl_irq (ctrl);
463         }
464
465         /* Done with exclusive hardware access */
466         up(&ctrl->crit_sect);
467 }
468
469 /**
470  * board_added - Called after a board has been added to the system.
471  *
472  * Turns power on for the board
473  * Configures board
474  *
475  */
476 static u32 board_added(struct pci_func * func, struct controller * ctrl)
477 {
478         u8 hp_slot;
479         u32 temp_register = 0xFFFFFFFF;
480         u32 rc = 0;
481         struct slot *p_slot;
482
483         p_slot = pciehp_find_slot(ctrl, func->device);
484         hp_slot = func->device - ctrl->slot_device_offset;
485
486         dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
487
488         /* Wait for exclusive access to hardware */
489         down(&ctrl->crit_sect);
490
491         if (POWER_CTRL(ctrl->ctrlcap)) {
492                 /* Power on slot */
493                 rc = p_slot->hpc_ops->power_on_slot(p_slot);
494                 if (rc) {
495                         up(&ctrl->crit_sect);
496                         return -1;
497                 }
498
499                 /* Wait for the command to complete */
500                 wait_for_ctrl_irq (ctrl);
501         }
502         
503         if (PWR_LED(ctrl->ctrlcap)) {
504                 p_slot->hpc_ops->green_led_blink(p_slot);
505                         
506                 /* Wait for the command to complete */
507                 wait_for_ctrl_irq (ctrl);
508         }
509
510         /* Done with exclusive hardware access */
511         up(&ctrl->crit_sect);
512
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__);
517
518         /*  Check link training status */
519         rc = p_slot->hpc_ops->check_lnk_status(ctrl);  
520         if (rc) {
521                 err("%s: Failed to check link status\n", __FUNCTION__);
522                 set_slot_off(ctrl, p_slot);
523                 return rc;
524         }
525
526         dbg("%s: func status = %x\n", __FUNCTION__, func->status);
527
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);
533                 rc = POWER_FAILURE;
534                 func->status = 0;
535                 goto err_exit;
536         }
537
538         rc = pciehp_configure_device(p_slot);
539         if (rc) {
540                 err("Cannot add device 0x%x:%x\n", p_slot->bus,
541                                 p_slot->device);
542                 goto err_exit;
543         }
544
545         pciehp_save_slot_config(ctrl, func);
546         func->status = 0;
547         func->switch_save = 0x10;
548         func->is_a_board = 0x01;
549
550         /*
551          * Some PCI Express root ports require fixup after hot-plug operation.
552          */
553         if (pcie_mch_quirk)
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);
558
559                 p_slot->hpc_ops->green_led_on(p_slot);
560   
561                 /* Wait for the command to complete */
562                 wait_for_ctrl_irq (ctrl);
563         
564                 /* Done with exclusive hardware access */
565                 up(&ctrl->crit_sect);
566         }
567         return 0;
568
569 err_exit:
570         set_slot_off(ctrl, p_slot);
571         return -1;
572 }
573
574
575 /**
576  * remove_board - Turns off slot and LED's
577  *
578  */
579 static u32 remove_board(struct pci_func *func, struct controller *ctrl)
580 {
581         u8 device;
582         u8 hp_slot;
583         u32 rc;
584         struct slot *p_slot;
585
586         if (func == NULL)
587                 return 1;
588
589         if (pciehp_unconfigure_device(func))
590                 return 1;
591
592         device = func->device;
593
594         hp_slot = func->device - ctrl->slot_device_offset;
595         p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
596
597         dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
598
599         /* Change status to shutdown */
600         if (func->is_a_board)
601                 func->status = 0x01;
602         func->configured = 0;
603
604         /* Wait for exclusive access to hardware */
605         down(&ctrl->crit_sect);
606
607         if (POWER_CTRL(ctrl->ctrlcap)) {
608                 /* power off slot */
609                 rc = p_slot->hpc_ops->power_off_slot(p_slot);
610                 if (rc) {
611                         err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
612                         up(&ctrl->crit_sect);
613                         return rc;
614                 }
615                 /* Wait for the command to complete */
616                 wait_for_ctrl_irq (ctrl);
617         }
618
619         if (PWR_LED(ctrl->ctrlcap)) {
620                 /* turn off Green LED */
621                 p_slot->hpc_ops->green_led_off(p_slot);
622         
623                 /* Wait for the command to complete */
624                 wait_for_ctrl_irq (ctrl);
625         }
626
627         /* Done with exclusive hardware access */
628         up(&ctrl->crit_sect);
629
630         if (ctrl->add_support) {
631                 while (func) {
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);
636                         } else {
637                                 dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", 
638                                         ctrl->seg, func->bus, func->device, func->function);
639                                 slot_remove(func);
640                         }
641
642                         func = pciehp_slot_find(ctrl->slot_bus, device, 0);
643                 }
644
645                 /* Setup slot structure with entry for empty slot */
646                 func = pciehp_slot_create(ctrl->slot_bus);
647
648                 if (func == NULL) {
649                         return 1;
650                 }
651
652                 func->bus = ctrl->slot_bus;
653                 func->device = device;
654                 func->function = 0;
655                 func->configured = 0;
656                 func->switch_save = 0x10;
657                 func->is_a_board = 0;
658         }
659
660         return 0;
661 }
662
663
664 static void pushbutton_helper_thread(unsigned long data)
665 {
666         pushbutton_pending = data;
667
668         up(&event_semaphore);
669 }
670
671 /**
672  * pciehp_pushbutton_thread
673  *
674  * Scheduled procedure to handle blocking stuff for the pushbuttons
675  * Handles all pending events and exits.
676  *
677  */
678 static void pciehp_pushbutton_thread(unsigned long slot)
679 {
680         struct slot *p_slot = (struct slot *) slot;
681         u8 getstatus;
682         
683         pushbutton_pending = 0;
684
685         if (!p_slot) {
686                 dbg("%s: Error! slot NULL\n", __FUNCTION__);
687                 return;
688         }
689
690         p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
691         if (getstatus) {
692                 p_slot->state = POWEROFF_STATE;
693                 dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
694
695                 pciehp_disable_slot(p_slot);
696                 p_slot->state = STATIC_STATE;
697         } else {
698                 p_slot->state = POWERON_STATE;
699                 dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
700
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);
704
705                         p_slot->hpc_ops->green_led_off(p_slot);
706
707                         /* Wait for the command to complete */
708                         wait_for_ctrl_irq (p_slot->ctrl);
709
710                         /* Done with exclusive hardware access */
711                         up(&p_slot->ctrl->crit_sect);
712                 }
713                 p_slot->state = STATIC_STATE;
714         }
715
716         return;
717 }
718
719 /**
720  * pciehp_surprise_rm_thread
721  *
722  * Scheduled procedure to handle blocking stuff for the surprise removal
723  * Handles all pending events and exits.
724  *
725  */
726 static void pciehp_surprise_rm_thread(unsigned long slot)
727 {
728         struct slot *p_slot = (struct slot *) slot;
729         u8 getstatus;
730         
731         surprise_rm_pending = 0;
732
733         if (!p_slot) {
734                 dbg("%s: Error! slot NULL\n", __FUNCTION__);
735                 return;
736         }
737
738         p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
739         if (!getstatus) {
740                 p_slot->state = POWEROFF_STATE;
741                 dbg("In removing board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
742
743                 pciehp_disable_slot(p_slot);
744                 p_slot->state = STATIC_STATE;
745         } else {
746                 p_slot->state = POWERON_STATE;
747                 dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
748
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);
752
753                         p_slot->hpc_ops->green_led_off(p_slot);
754
755                         /* Wait for the command to complete */
756                         wait_for_ctrl_irq (p_slot->ctrl);
757
758                         /* Done with exclusive hardware access */
759                         up(&p_slot->ctrl->crit_sect);
760                 }
761                 p_slot->state = STATIC_STATE;
762         }
763
764         return;
765 }
766
767
768
769 /* this is the main worker thread */
770 static int event_thread(void* data)
771 {
772         struct controller *ctrl;
773         lock_kernel();
774         daemonize("pciehpd_event");
775
776         unlock_kernel();
777
778         while (1) {
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))
783                         break;
784                 /* Do stuff here */
785                 if (pushbutton_pending)
786                         pciehp_pushbutton_thread(pushbutton_pending);
787                 else if (surprise_rm_pending)
788                         pciehp_surprise_rm_thread(surprise_rm_pending);
789                 else
790                         for (ctrl = pciehp_ctrl_list; ctrl; ctrl=ctrl->next)
791                                 interrupt_event_handler(ctrl);
792         }
793         dbg("event_thread signals exit\n");
794         up(&event_exit);
795         return 0;
796 }
797
798 int pciehp_event_start_thread(void)
799 {
800         int pid;
801
802         /* initialize our semaphores */
803         init_MUTEX_LOCKED(&event_exit);
804         event_finished=0;
805
806         init_MUTEX_LOCKED(&event_semaphore);
807         pid = kernel_thread(event_thread, NULL, 0);
808
809         if (pid < 0) {
810                 err ("Can't start up our event thread\n");
811                 return -1;
812         }
813         dbg("Our event thread pid = %d\n", pid);
814         return 0;
815 }
816
817
818 void pciehp_event_stop_thread(void)
819 {
820         event_finished = 1;
821         dbg("event_thread finish command given\n");
822         up(&event_semaphore);
823         dbg("wait for event_thread to exit\n");
824         down(&event_exit);
825 }
826
827
828 static int update_slot_info(struct slot *slot)
829 {
830         struct hotplug_slot_info *info;
831         /* char buffer[SLOT_NAME_SIZE]; */
832         int result;
833
834         info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
835         if (!info)
836                 return -ENOMEM;
837
838         /* make_slot_name (&buffer[0], SLOT_NAME_SIZE, slot); */
839
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));
844
845         /* result = pci_hp_change_slot_info(buffer, info); */
846         result = pci_hp_change_slot_info(slot->hotplug_slot, info);
847         kfree (info);
848         return result;
849 }
850
851 static void interrupt_event_handler(struct controller *ctrl)
852 {
853         int loop = 0;
854         int change = 1;
855         struct pci_func *func;
856         u8 hp_slot;
857         u8 getstatus;
858         struct slot *p_slot;
859
860         while (change) {
861                 change = 0;
862
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;
866
867                                 func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
868
869                                 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
870
871                                 dbg("hp_slot %d, func %p, p_slot %p\n", hp_slot, func, p_slot);
872
873                                 if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) {
874                                         dbg("button cancel\n");
875                                         del_timer(&p_slot->task_event);
876
877                                         switch (p_slot->state) {
878                                         case BLINKINGOFF_STATE:
879                                                 /* Wait for exclusive access to hardware */
880                                                 down(&ctrl->crit_sect);
881                                                 
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);
886                                                 }
887                                                 if (ATTN_LED(ctrl->ctrlcap)) {
888                                                         p_slot->hpc_ops->set_attention_status(p_slot, 0);
889
890                                                         /* Wait for the command to complete */
891                                                         wait_for_ctrl_irq (ctrl);
892                                                 }
893                                                 /* Done with exclusive hardware access */
894                                                 up(&ctrl->crit_sect);
895                                                 break;
896                                         case BLINKINGON_STATE:
897                                                 /* Wait for exclusive access to hardware */
898                                                 down(&ctrl->crit_sect);
899
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);
904                                                 }
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);
909                                                 }
910                                                 /* Done with exclusive hardware access */
911                                                 up(&ctrl->crit_sect);
912
913                                                 break;
914                                         default:
915                                                 warn("Not a valid state\n");
916                                                 return;
917                                         }
918                                         info(msg_button_cancel, p_slot->number);
919                                         p_slot->state = STATIC_STATE;
920                                 }
921                                 /* ***********Button Pressed (No action on 1st press...) */
922                                 else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) {
923                                         
924                                         if (ATTN_BUTTN(ctrl->ctrlcap)) {
925                                                 dbg("Button pressed\n");
926                                                 p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
927                                                 if (getstatus) {
928                                                         /* slot is on */
929                                                         dbg("slot is on\n");
930                                                         p_slot->state = BLINKINGOFF_STATE;
931                                                         info(msg_button_off, p_slot->number);
932                                                 } else {
933                                                         /* slot is off */
934                                                         dbg("slot is off\n");
935                                                         p_slot->state = BLINKINGON_STATE;
936                                                         info(msg_button_on, p_slot->number);
937                                                 }
938
939                                                 /* Wait for exclusive access to hardware */
940                                                 down(&ctrl->crit_sect);
941
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);
947                                                 }
948
949                                                 if (ATTN_LED(ctrl->ctrlcap)) {
950                                                         p_slot->hpc_ops->set_attention_status(p_slot, 0);
951
952                                                         /* Wait for the command to complete */
953                                                         wait_for_ctrl_irq (ctrl);
954                                                 }
955
956                                                 /* Done with exclusive hardware access */
957                                                 up(&ctrl->crit_sect);
958
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;
963
964                                                 dbg("add_timer p_slot = %p\n", (void *) p_slot);
965                                                 add_timer(&p_slot->task_event);
966                                         }
967                                 }
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);
974
975                                                 if (ATTN_LED(ctrl->ctrlcap)) {
976                                                         p_slot->hpc_ops->set_attention_status(p_slot, 1);
977                                                         wait_for_ctrl_irq (ctrl);
978                                                 }
979
980                                                 if (PWR_LED(ctrl->ctrlcap)) {
981                                                         p_slot->hpc_ops->green_led_off(p_slot);
982                                                         wait_for_ctrl_irq (ctrl);
983                                                 }
984
985                                                 /* Done with exclusive hardware access */
986                                                 up(&ctrl->crit_sect);
987                                         }
988                                 }
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");
994                                                 if (p_slot) {
995                                                         surprise_rm_pending = (unsigned long) p_slot;
996                                                         up(&event_semaphore);
997                                                         update_slot_info(p_slot);
998                                                 }
999                                         }
1000                                 } else {
1001                                         /* refresh notification */
1002                                         if (p_slot)
1003                                                 update_slot_info(p_slot);
1004                                 }
1005
1006                                 ctrl->event_queue[loop].event_type = 0;
1007
1008                                 change = 1;
1009                         }
1010                 }               /* End of FOR loop */
1011         }
1012 }
1013
1014
1015 int pciehp_enable_slot(struct slot *p_slot)
1016 {
1017         u8 getstatus = 0;
1018         int rc;
1019         struct pci_func *func;
1020
1021         func = pciehp_slot_find(p_slot->bus, p_slot->device, 0);
1022         if (!func) {
1023                 dbg("%s: Error! slot NULL\n", __FUNCTION__);
1024                 return 1;
1025         }
1026
1027         /* Check to see if (latch closed, card present, power off) */
1028         down(&p_slot->ctrl->crit_sect);
1029
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);
1034                 return 1;
1035         }
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);
1041                         return 1;
1042                 }
1043         }
1044         
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);
1050                         return 1;
1051                 }
1052         }
1053         up(&p_slot->ctrl->crit_sect);
1054
1055         slot_remove(func);
1056
1057         func = pciehp_slot_create(p_slot->bus);
1058         if (func == NULL)
1059                 return 1;
1060
1061         func->bus = p_slot->bus;
1062         func->device = p_slot->device;
1063         func->function = 0;
1064         func->configured = 0;
1065         func->is_a_board = 1;
1066
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;
1071
1072         rc = board_added(func, p_slot->ctrl);
1073         if (rc) {
1074                 if (is_bridge(func))
1075                         bridge_slot_remove(func);
1076                 else
1077                         slot_remove(func);
1078
1079                 /* Setup slot structure with entry for empty slot */
1080                 func = pciehp_slot_create(p_slot->bus);
1081                 if (func == NULL)
1082                         return 1;       /* Out of memory */
1083
1084                 func->bus = p_slot->bus;
1085                 func->device = p_slot->device;
1086                 func->function = 0;
1087                 func->configured = 0;
1088                 func->is_a_board = 1;
1089
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;
1094         }
1095
1096         if (p_slot)
1097                 update_slot_info(p_slot);
1098
1099         return rc;
1100 }
1101
1102
1103 int pciehp_disable_slot(struct slot *p_slot)
1104 {
1105         u8 class_code, header_type, BCR;
1106         u8 index = 0;
1107         u8 getstatus = 0;
1108         u32 rc = 0;
1109         int ret = 0;
1110         unsigned int devfn;
1111         struct pci_bus *pci_bus = p_slot->ctrl->pci_dev->subordinate;
1112         struct pci_func *func;
1113
1114         if (!p_slot->ctrl)
1115                 return 1;
1116
1117         /* Check to see if (latch closed, card present, power on) */
1118         down(&p_slot->ctrl->crit_sect);
1119
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);
1125                         return 1;
1126                 }
1127         }
1128
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);
1134                         return 1;
1135                 }
1136         }
1137
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);
1143                         return 1;
1144                 }
1145         }
1146
1147         up(&p_slot->ctrl->crit_sect);
1148
1149         func = pciehp_slot_find(p_slot->bus, p_slot->device, index++);
1150
1151         /* Make sure there are no video controllers here
1152          * for all func of p_slot
1153          */
1154         while (func && !rc) {
1155                 pci_bus->number = func->bus;
1156                 devfn = PCI_DEVFN(func->device, func->function);
1157
1158                 /* Check the Class Code */
1159                 rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
1160                 if (rc)
1161                         return rc;
1162
1163                 if (class_code == PCI_BASE_CLASS_DISPLAY) {
1164                         /* Display/Video adapter (not supported) */
1165                         rc = REMOVE_NOT_SUPPORTED;
1166                 } else {
1167                         /* See if it's a bridge */
1168                         rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
1169                         if (rc)
1170                                 return rc;
1171
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);
1175                                 if (rc)
1176                                         return rc;
1177
1178                                 /* If the VGA Enable bit is set, remove isn't supported */
1179                                 if (BCR & PCI_BRIDGE_CTL_VGA) {
1180                                         rc = REMOVE_NOT_SUPPORTED;
1181                                 }
1182                         }
1183                 }
1184
1185                 func = pciehp_slot_find(p_slot->bus, p_slot->device, index++);
1186         }
1187
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);
1191         } else if (!rc)
1192                 rc = 1;
1193
1194         if (p_slot)
1195                 update_slot_info(p_slot);
1196
1197         return rc;
1198 }
1199