aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>2007-03-06 18:02:26 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2007-05-02 22:02:34 -0400
commit5d386e1ac4025b4bcc6bad6811e771cb76064dfe (patch)
treed673b9686ed60aa43c1c0f43abc8bc54d19b6649 /drivers/pci
parentf7bdd12d234d9064bd0aa1b5610508959120a9b4 (diff)
pciehp: Event handling rework
The event handler of PCIEHP driver is unnecessarily very complex. In addition, current event handler can only a fixed number of events at the same time, and some of events would be lost if several number of events happened at the same time. This patch simplify the event handler using 'work queue', and it also fix the above-mentioned issue. Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/hotplug/pciehp.h16
-rw-r--r--drivers/pci/hotplug/pciehp_core.c44
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c616
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c34
4 files changed, 321 insertions, 389 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index d19fcae8a7c0..c98e27128cc4 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -43,6 +43,7 @@ extern int pciehp_poll_mode;
43extern int pciehp_poll_time; 43extern int pciehp_poll_time;
44extern int pciehp_debug; 44extern int pciehp_debug;
45extern int pciehp_force; 45extern int pciehp_force;
46extern struct workqueue_struct *pciehp_wq;
46 47
47#define dbg(format, arg...) \ 48#define dbg(format, arg...) \
48 do { \ 49 do { \
@@ -70,14 +71,16 @@ struct slot {
70 struct list_head slot_list; 71 struct list_head slot_list;
71 char name[SLOT_NAME_SIZE]; 72 char name[SLOT_NAME_SIZE];
72 unsigned long last_emi_toggle; 73 unsigned long last_emi_toggle;
74 struct delayed_work work; /* work for button event */
75 struct mutex lock;
73}; 76};
74 77
75struct event_info { 78struct event_info {
76 u32 event_type; 79 u32 event_type;
77 u8 hp_slot; 80 struct slot *p_slot;
81 struct work_struct work;
78}; 82};
79 83
80#define MAX_EVENTS 10
81struct controller { 84struct controller {
82 struct controller *next; 85 struct controller *next;
83 struct mutex crit_sect; /* critical section mutex */ 86 struct mutex crit_sect; /* critical section mutex */
@@ -86,11 +89,9 @@ struct controller {
86 int slot_num_inc; /* 1 or -1 */ 89 int slot_num_inc; /* 1 or -1 */
87 struct pci_dev *pci_dev; 90 struct pci_dev *pci_dev;
88 struct list_head slot_list; 91 struct list_head slot_list;
89 struct event_info event_queue[MAX_EVENTS];
90 struct slot *slot; 92 struct slot *slot;
91 struct hpc_ops *hpc_ops; 93 struct hpc_ops *hpc_ops;
92 wait_queue_head_t queue; /* sleep & wake process */ 94 wait_queue_head_t queue; /* sleep & wake process */
93 u8 next_event;
94 u8 bus; 95 u8 bus;
95 u8 device; 96 u8 device;
96 u8 function; 97 u8 function;
@@ -149,16 +150,15 @@ struct controller {
149#define HP_SUPR_RM(cap) (cap & HP_SUPR_RM_SUP) 150#define HP_SUPR_RM(cap) (cap & HP_SUPR_RM_SUP)
150#define EMI(cap) (cap & EMI_PRSN) 151#define EMI(cap) (cap & EMI_PRSN)
151 152
152extern int pciehp_event_start_thread(void); 153extern int pciehp_sysfs_enable_slot(struct slot *slot);
153extern void pciehp_event_stop_thread(void); 154extern int pciehp_sysfs_disable_slot(struct slot *slot);
154extern int pciehp_enable_slot(struct slot *slot);
155extern int pciehp_disable_slot(struct slot *slot);
156extern u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl); 155extern u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl);
157extern u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl); 156extern u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl);
158extern u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl); 157extern u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl);
159extern u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl); 158extern u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl);
160extern int pciehp_configure_device(struct slot *p_slot); 159extern int pciehp_configure_device(struct slot *p_slot);
161extern int pciehp_unconfigure_device(struct slot *p_slot); 160extern int pciehp_unconfigure_device(struct slot *p_slot);
161extern void queue_pushbutton_work(struct work_struct *work);
162int pcie_init(struct controller *ctrl, struct pcie_device *dev); 162int pcie_init(struct controller *ctrl, struct pcie_device *dev);
163 163
164/* Global variables */ 164/* Global variables */
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index a92eda6e02f6..749227ecdb04 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -41,6 +41,7 @@ int pciehp_debug;
41int pciehp_poll_mode; 41int pciehp_poll_mode;
42int pciehp_poll_time; 42int pciehp_poll_time;
43int pciehp_force; 43int pciehp_force;
44struct workqueue_struct *pciehp_wq;
44struct controller *pciehp_ctrl_list; 45struct controller *pciehp_ctrl_list;
45 46
46#define DRIVER_VERSION "0.4" 47#define DRIVER_VERSION "0.4"
@@ -62,7 +63,6 @@ MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing"
62 63
63#define PCIE_MODULE_NAME "pciehp" 64#define PCIE_MODULE_NAME "pciehp"
64 65
65static int pcie_start_thread (void);
66static int set_attention_status (struct hotplug_slot *slot, u8 value); 66static int set_attention_status (struct hotplug_slot *slot, u8 value);
67static int enable_slot (struct hotplug_slot *slot); 67static int enable_slot (struct hotplug_slot *slot);
68static int disable_slot (struct hotplug_slot *slot); 68static int disable_slot (struct hotplug_slot *slot);
@@ -229,6 +229,8 @@ static int init_slots(struct controller *ctrl)
229 slot->device = ctrl->slot_device_offset + i; 229 slot->device = ctrl->slot_device_offset + i;
230 slot->hpc_ops = ctrl->hpc_ops; 230 slot->hpc_ops = ctrl->hpc_ops;
231 slot->number = ctrl->first_slot; 231 slot->number = ctrl->first_slot;
232 mutex_init(&slot->lock);
233 INIT_DELAYED_WORK(&slot->work, queue_pushbutton_work);
232 234
233 /* register this slot with the hotplug pci core */ 235 /* register this slot with the hotplug pci core */
234 hotplug_slot->private = slot; 236 hotplug_slot->private = slot;
@@ -286,6 +288,9 @@ static void cleanup_slots(struct controller *ctrl)
286 if (EMI(ctrl->ctrlcap)) 288 if (EMI(ctrl->ctrlcap))
287 sysfs_remove_file(&slot->hotplug_slot->kobj, 289 sysfs_remove_file(&slot->hotplug_slot->kobj,
288 &hotplug_slot_attr_lock.attr); 290 &hotplug_slot_attr_lock.attr);
291 cancel_delayed_work(&slot->work);
292 flush_scheduled_work();
293 flush_workqueue(pciehp_wq);
289 pci_hp_deregister(slot->hotplug_slot); 294 pci_hp_deregister(slot->hotplug_slot);
290 } 295 }
291} 296}
@@ -314,7 +319,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
314 319
315 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 320 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
316 321
317 return pciehp_enable_slot(slot); 322 return pciehp_sysfs_enable_slot(slot);
318} 323}
319 324
320 325
@@ -324,7 +329,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
324 329
325 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 330 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
326 331
327 return pciehp_disable_slot(slot); 332 return pciehp_sysfs_disable_slot(slot);
328} 333}
329 334
330static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) 335static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
@@ -466,9 +471,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
466 471
467 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); 472 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
468 473
469 /* Finish setting up the hot plug ctrl device */
470 ctrl->next_event = 0;
471
472 if (!pciehp_ctrl_list) { 474 if (!pciehp_ctrl_list) {
473 pciehp_ctrl_list = ctrl; 475 pciehp_ctrl_list = ctrl;
474 ctrl->next = NULL; 476 ctrl->next = NULL;
@@ -496,22 +498,6 @@ err_out_none:
496 return -ENODEV; 498 return -ENODEV;
497} 499}
498 500
499
500static int pcie_start_thread(void)
501{
502 int retval = 0;
503
504 dbg("Initialize + Start the notification/polling mechanism \n");
505
506 retval = pciehp_event_start_thread();
507 if (retval) {
508 dbg("pciehp_event_start_thread() failed\n");
509 return retval;
510 }
511
512 return retval;
513}
514
515static void __exit unload_pciehpd(void) 501static void __exit unload_pciehpd(void)
516{ 502{
517 struct controller *ctrl; 503 struct controller *ctrl;
@@ -529,10 +515,6 @@ static void __exit unload_pciehpd(void)
529 515
530 kfree(tctrl); 516 kfree(tctrl);
531 } 517 }
532
533 /* Stop the notification mechanism */
534 pciehp_event_stop_thread();
535
536} 518}
537 519
538static void pciehp_remove (struct pcie_device *device) 520static void pciehp_remove (struct pcie_device *device)
@@ -585,21 +567,11 @@ static int __init pcied_init(void)
585 pciehp_poll_mode = 1; 567 pciehp_poll_mode = 1;
586#endif 568#endif
587 569
588 retval = pcie_start_thread();
589 if (retval)
590 goto error_hpc_init;
591
592 retval = pcie_port_service_register(&hpdriver_portdrv); 570 retval = pcie_port_service_register(&hpdriver_portdrv);
593 dbg("pcie_port_service_register = %d\n", retval); 571 dbg("pcie_port_service_register = %d\n", retval);
594 info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); 572 info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
595 if (retval) 573 if (retval)
596 dbg("%s: Failure to register service\n", __FUNCTION__); 574 dbg("%s: Failure to register service\n", __FUNCTION__);
597
598error_hpc_init:
599 if (retval) {
600 pciehp_event_stop_thread();
601 };
602
603 return retval; 575 return retval;
604} 576}
605 577
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 4283ef56dbd9..91441e5ae631 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 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}
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index fbc64aa2dd68..9aac6a87eb53 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -71,6 +71,8 @@
71#define DBG_LEAVE_ROUTINE 71#define DBG_LEAVE_ROUTINE
72#endif /* DEBUG */ 72#endif /* DEBUG */
73 73
74static atomic_t pciehp_num_controllers = ATOMIC_INIT(0);
75
74struct ctrl_reg { 76struct ctrl_reg {
75 u8 cap_id; 77 u8 cap_id;
76 u8 nxt_ptr; 78 u8 nxt_ptr;
@@ -219,10 +221,7 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value)
219#define EMI_STATE 0x0080 221#define EMI_STATE 0x0080
220#define EMI_STATUS_BIT 7 222#define EMI_STATUS_BIT 7
221 223
222static spinlock_t hpc_event_lock;
223
224DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ 224DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */
225static int ctlr_seq_num = 0; /* Controller sequence # */
226 225
227static irqreturn_t pcie_isr(int irq, void *dev_id); 226static irqreturn_t pcie_isr(int irq, void *dev_id);
228static void start_int_poll_timer(struct controller *ctrl, int sec); 227static void start_int_poll_timer(struct controller *ctrl, int sec);
@@ -656,6 +655,13 @@ static void hpc_release_ctlr(struct controller *ctrl)
656 else 655 else
657 free_irq(ctrl->pci_dev->irq, ctrl); 656 free_irq(ctrl->pci_dev->irq, ctrl);
658 657
658 /*
659 * If this is the last controller to be released, destroy the
660 * pciehp work queue
661 */
662 if (atomic_dec_and_test(&pciehp_num_controllers))
663 destroy_workqueue(pciehp_wq);
664
659 DBG_LEAVE_ROUTINE 665 DBG_LEAVE_ROUTINE
660} 666}
661 667
@@ -1152,7 +1158,6 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
1152int pcie_init(struct controller * ctrl, struct pcie_device *dev) 1158int pcie_init(struct controller * ctrl, struct pcie_device *dev)
1153{ 1159{
1154 int rc; 1160 int rc;
1155 static int first = 1;
1156 u16 temp_word; 1161 u16 temp_word;
1157 u16 cap_reg; 1162 u16 cap_reg;
1158 u16 intr_enable = 0; 1163 u16 intr_enable = 0;
@@ -1221,11 +1226,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
1221 dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n", 1226 dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
1222 __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl); 1227 __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
1223 1228
1224 if (first) {
1225 spin_lock_init(&hpc_event_lock);
1226 first = 0;
1227 }
1228
1229 for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++) 1229 for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
1230 if (pci_resource_len(pdev, rc) > 0) 1230 if (pci_resource_len(pdev, rc) > 0)
1231 dbg("pci resource[%d] start=0x%llx(len=0x%llx)\n", rc, 1231 dbg("pci resource[%d] start=0x%llx(len=0x%llx)\n", rc,
@@ -1286,7 +1286,8 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
1286 rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED, 1286 rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED,
1287 MY_NAME, (void *)ctrl); 1287 MY_NAME, (void *)ctrl);
1288 dbg("%s: request_irq %d for hpc%d (returns %d)\n", 1288 dbg("%s: request_irq %d for hpc%d (returns %d)\n",
1289 __FUNCTION__, ctrl->pci_dev->irq, ctlr_seq_num, rc); 1289 __FUNCTION__, ctrl->pci_dev->irq,
1290 atomic_read(&pciehp_num_controllers), rc);
1290 if (rc) { 1291 if (rc) {
1291 err("Can't get irq %d for the hotplug controller\n", 1292 err("Can't get irq %d for the hotplug controller\n",
1292 ctrl->pci_dev->irq); 1293 ctrl->pci_dev->irq);
@@ -1296,6 +1297,18 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
1296 dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number, 1297 dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
1297 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq); 1298 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq);
1298 1299
1300 /*
1301 * If this is the first controller to be initialized,
1302 * initialize the pciehp work queue
1303 */
1304 if (atomic_add_return(1, &pciehp_num_controllers) == 1) {
1305 pciehp_wq = create_singlethread_workqueue("pciehpd");
1306 if (!pciehp_wq) {
1307 rc = -ENOMEM;
1308 goto abort_free_irq;
1309 }
1310 }
1311
1299 rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); 1312 rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
1300 if (rc) { 1313 if (rc) {
1301 err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); 1314 err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
@@ -1349,7 +1362,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
1349 goto abort_disable_intr; 1362 goto abort_disable_intr;
1350 } 1363 }
1351 1364
1352 ctlr_seq_num++;
1353 ctrl->hpc_ops = &pciehp_hpc_ops; 1365 ctrl->hpc_ops = &pciehp_hpc_ops;
1354 1366
1355 DBG_LEAVE_ROUTINE 1367 DBG_LEAVE_ROUTINE