xref: /linux/drivers/pci/hotplug/pciehp_core.c (revision 36ca1195ad7f760a6af3814cb002bd3a3d4b4db1)
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>, <dely.l.sy@intel.com>
27  *
28  */
29 
30 #include <linux/config.h>
31 #include <linux/module.h>
32 #include <linux/moduleparam.h>
33 #include <linux/kernel.h>
34 #include <linux/types.h>
35 #include <linux/proc_fs.h>
36 #include <linux/slab.h>
37 #include <linux/workqueue.h>
38 #include <linux/pci.h>
39 #include <linux/init.h>
40 #include <asm/uaccess.h>
41 #include "pciehp.h"
42 #include "pciehprm.h"
43 #include <linux/interrupt.h>
44 
45 /* Global variables */
46 int pciehp_debug;
47 int pciehp_poll_mode;
48 int pciehp_poll_time;
49 struct controller *pciehp_ctrl_list;
50 struct pci_func *pciehp_slot_list[256];
51 
52 #define DRIVER_VERSION	"0.4"
53 #define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
54 #define DRIVER_DESC	"PCI Express Hot Plug Controller Driver"
55 
56 MODULE_AUTHOR(DRIVER_AUTHOR);
57 MODULE_DESCRIPTION(DRIVER_DESC);
58 MODULE_LICENSE("GPL");
59 
60 module_param(pciehp_debug, bool, 0644);
61 module_param(pciehp_poll_mode, bool, 0644);
62 module_param(pciehp_poll_time, int, 0644);
63 MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not");
64 MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not");
65 MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds");
66 
67 #define PCIE_MODULE_NAME "pciehp"
68 
69 static int pcie_start_thread (void);
70 static int set_attention_status (struct hotplug_slot *slot, u8 value);
71 static int enable_slot		(struct hotplug_slot *slot);
72 static int disable_slot		(struct hotplug_slot *slot);
73 static int get_power_status	(struct hotplug_slot *slot, u8 *value);
74 static int get_attention_status	(struct hotplug_slot *slot, u8 *value);
75 static int get_latch_status	(struct hotplug_slot *slot, u8 *value);
76 static int get_adapter_status	(struct hotplug_slot *slot, u8 *value);
77 static int get_max_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
78 static int get_cur_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
79 
80 static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
81 	.owner =		THIS_MODULE,
82 	.set_attention_status =	set_attention_status,
83 	.enable_slot =		enable_slot,
84 	.disable_slot =		disable_slot,
85 	.get_power_status =	get_power_status,
86 	.get_attention_status =	get_attention_status,
87 	.get_latch_status =	get_latch_status,
88 	.get_adapter_status =	get_adapter_status,
89   	.get_max_bus_speed =	get_max_bus_speed,
90   	.get_cur_bus_speed =	get_cur_bus_speed,
91 };
92 
93 /**
94  * release_slot - free up the memory used by a slot
95  * @hotplug_slot: slot to free
96  */
97 static void release_slot(struct hotplug_slot *hotplug_slot)
98 {
99 	struct slot *slot = hotplug_slot->private;
100 
101 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
102 
103 	kfree(slot->hotplug_slot->info);
104 	kfree(slot->hotplug_slot->name);
105 	kfree(slot->hotplug_slot);
106 	kfree(slot);
107 }
108 
109 static int init_slots(struct controller *ctrl)
110 {
111 	struct slot *new_slot;
112 	u8 number_of_slots;
113 	u8 slot_device;
114 	u32 slot_number;
115 	int result = -ENOMEM;
116 
117 	dbg("%s\n",__FUNCTION__);
118 
119 	number_of_slots = ctrl->num_slots;
120 	slot_device = ctrl->slot_device_offset;
121 	slot_number = ctrl->first_slot;
122 
123 	while (number_of_slots) {
124 		new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL);
125 		if (!new_slot)
126 			goto error;
127 
128 		memset(new_slot, 0, sizeof(struct slot));
129 		new_slot->hotplug_slot =
130 				kmalloc(sizeof(*(new_slot->hotplug_slot)),
131 						GFP_KERNEL);
132 		if (!new_slot->hotplug_slot)
133 			goto error_slot;
134 		memset(new_slot->hotplug_slot, 0, sizeof(struct hotplug_slot));
135 
136 		new_slot->hotplug_slot->info =
137 			kmalloc(sizeof(*(new_slot->hotplug_slot->info)),
138 						GFP_KERNEL);
139 		if (!new_slot->hotplug_slot->info)
140 			goto error_hpslot;
141 		memset(new_slot->hotplug_slot->info, 0,
142 					sizeof(struct hotplug_slot_info));
143 		new_slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE,
144 						GFP_KERNEL);
145 		if (!new_slot->hotplug_slot->name)
146 			goto error_info;
147 
148 		new_slot->ctrl = ctrl;
149 		new_slot->bus = ctrl->slot_bus;
150 		new_slot->device = slot_device;
151 		new_slot->hpc_ops = ctrl->hpc_ops;
152 
153 		new_slot->number = ctrl->first_slot;
154 		new_slot->hp_slot = slot_device - ctrl->slot_device_offset;
155 
156 		/* register this slot with the hotplug pci core */
157 		new_slot->hotplug_slot->private = new_slot;
158 		new_slot->hotplug_slot->release = &release_slot;
159 		make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot);
160 		new_slot->hotplug_slot->ops = &pciehp_hotplug_slot_ops;
161 
162 		new_slot->hpc_ops->get_power_status(new_slot, &(new_slot->hotplug_slot->info->power_status));
163 		new_slot->hpc_ops->get_attention_status(new_slot, &(new_slot->hotplug_slot->info->attention_status));
164 		new_slot->hpc_ops->get_latch_status(new_slot, &(new_slot->hotplug_slot->info->latch_status));
165 		new_slot->hpc_ops->get_adapter_status(new_slot, &(new_slot->hotplug_slot->info->adapter_status));
166 
167 		dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x slot_device_offset=%x\n",
168 			new_slot->bus, new_slot->device, new_slot->hp_slot, new_slot->number, ctrl->slot_device_offset);
169 		result = pci_hp_register (new_slot->hotplug_slot);
170 		if (result) {
171 			err ("pci_hp_register failed with error %d\n", result);
172 			goto error_name;
173 		}
174 
175 		new_slot->next = ctrl->slot;
176 		ctrl->slot = new_slot;
177 
178 		number_of_slots--;
179 		slot_device++;
180 		slot_number += ctrl->slot_num_inc;
181 	}
182 
183 	return 0;
184 
185 error_name:
186 	kfree(new_slot->hotplug_slot->name);
187 error_info:
188 	kfree(new_slot->hotplug_slot->info);
189 error_hpslot:
190 	kfree(new_slot->hotplug_slot);
191 error_slot:
192 	kfree(new_slot);
193 error:
194 	return result;
195 }
196 
197 
198 static int cleanup_slots (struct controller * ctrl)
199 {
200 	struct slot *old_slot, *next_slot;
201 
202 	old_slot = ctrl->slot;
203 	ctrl->slot = NULL;
204 
205 	while (old_slot) {
206 		next_slot = old_slot->next;
207 		pci_hp_deregister (old_slot->hotplug_slot);
208 		old_slot = next_slot;
209 	}
210 
211 
212 	return(0);
213 }
214 
215 static int get_ctlr_slot_config(struct controller *ctrl)
216 {
217 	int num_ctlr_slots;		/* Not needed; PCI Express has 1 slot per port*/
218 	int first_device_num;		/* Not needed */
219 	int physical_slot_num;
220 	u8 ctrlcap;
221 	int rc;
222 
223 	rc = pcie_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &ctrlcap);
224 	if (rc) {
225 		err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device);
226 		return (-1);
227 	}
228 
229 	ctrl->num_slots = num_ctlr_slots;	/* PCI Express has 1 slot per port */
230 	ctrl->slot_device_offset = first_device_num;
231 	ctrl->first_slot = physical_slot_num;
232 	ctrl->ctrlcap = ctrlcap;
233 
234 	dbg("%s: bus(0x%x) num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) ctrlcap(%x) for b:d (%x:%x)\n",
235 		__FUNCTION__, ctrl->slot_bus, num_ctlr_slots, first_device_num, physical_slot_num, ctrlcap,
236 		ctrl->bus, ctrl->device);
237 
238 	return (0);
239 }
240 
241 
242 /*
243  * set_attention_status - Turns the Amber LED for a slot on, off or blink
244  */
245 static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
246 {
247 	struct slot *slot = hotplug_slot->private;
248 
249 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
250 
251 	hotplug_slot->info->attention_status = status;
252 
253 	if (ATTN_LED(slot->ctrl->ctrlcap))
254 		slot->hpc_ops->set_attention_status(slot, status);
255 
256 	return 0;
257 }
258 
259 
260 static int enable_slot(struct hotplug_slot *hotplug_slot)
261 {
262 	struct slot *slot = hotplug_slot->private;
263 
264 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
265 
266 	return pciehp_enable_slot(slot);
267 }
268 
269 
270 static int disable_slot(struct hotplug_slot *hotplug_slot)
271 {
272 	struct slot *slot = hotplug_slot->private;
273 
274 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
275 
276 	return pciehp_disable_slot(slot);
277 }
278 
279 static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
280 {
281 	struct slot *slot = hotplug_slot->private;
282 	int retval;
283 
284 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
285 
286 	retval = slot->hpc_ops->get_power_status(slot, value);
287 	if (retval < 0)
288 		*value = hotplug_slot->info->power_status;
289 
290 	return 0;
291 }
292 
293 static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
294 {
295 	struct slot *slot = hotplug_slot->private;
296 	int retval;
297 
298 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
299 
300 	retval = slot->hpc_ops->get_attention_status(slot, value);
301 	if (retval < 0)
302 		*value = hotplug_slot->info->attention_status;
303 
304 	return 0;
305 }
306 
307 static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
308 {
309 	struct slot *slot = hotplug_slot->private;
310 	int retval;
311 
312 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
313 
314 	retval = slot->hpc_ops->get_latch_status(slot, value);
315 	if (retval < 0)
316 		*value = hotplug_slot->info->latch_status;
317 
318 	return 0;
319 }
320 
321 static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
322 {
323 	struct slot *slot = hotplug_slot->private;
324 	int retval;
325 
326 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
327 
328 	retval = slot->hpc_ops->get_adapter_status(slot, value);
329 	if (retval < 0)
330 		*value = hotplug_slot->info->adapter_status;
331 
332 	return 0;
333 }
334 
335 static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
336 {
337 	struct slot *slot = hotplug_slot->private;
338 	int retval;
339 
340 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
341 
342 	retval = slot->hpc_ops->get_max_bus_speed(slot, value);
343 	if (retval < 0)
344 		*value = PCI_SPEED_UNKNOWN;
345 
346 	return 0;
347 }
348 
349 static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
350 {
351 	struct slot *slot = hotplug_slot->private;
352 	int retval;
353 
354 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
355 
356 	retval = slot->hpc_ops->get_cur_bus_speed(slot, value);
357 	if (retval < 0)
358 		*value = PCI_SPEED_UNKNOWN;
359 
360 	return 0;
361 }
362 
363 static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_id *id)
364 {
365 	int rc;
366 	struct controller *ctrl;
367 	struct slot *t_slot;
368 	int first_device_num = 0 ;	/* first PCI device number supported by this PCIE */
369 	int num_ctlr_slots;		/* number of slots supported by this HPC */
370 	u8 value;
371 	struct pci_dev *pdev;
372 
373 	dbg("%s: Called by hp_drv\n", __FUNCTION__);
374 	ctrl = kmalloc(sizeof(*ctrl), GFP_KERNEL);
375 	if (!ctrl) {
376 		err("%s : out of memory\n", __FUNCTION__);
377 		goto err_out_none;
378 	}
379 	memset(ctrl, 0, sizeof(struct controller));
380 
381 	dbg("%s: DRV_thread pid = %d\n", __FUNCTION__, current->pid);
382 
383 	pdev = dev->port;
384 
385 	rc = pcie_init(ctrl, dev,
386 		(php_intr_callback_t) pciehp_handle_attention_button,
387 		(php_intr_callback_t) pciehp_handle_switch_change,
388 		(php_intr_callback_t) pciehp_handle_presence_change,
389 		(php_intr_callback_t) pciehp_handle_power_fault);
390 	if (rc) {
391 		dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME);
392 		goto err_out_free_ctrl;
393 	}
394 
395 	ctrl->pci_dev = pdev;
396 
397 	pci_set_drvdata(pdev, ctrl);
398 
399 	ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL);
400 	if (!ctrl->pci_bus) {
401 		err("%s: out of memory\n", __FUNCTION__);
402 		rc = -ENOMEM;
403 		goto err_out_unmap_mmio_region;
404 	}
405 	dbg("%s: ctrl->pci_bus %p\n", __FUNCTION__, ctrl->pci_bus);
406 	memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus));
407 	ctrl->bus = pdev->bus->number;  /* ctrl bus */
408 	ctrl->slot_bus = pdev->subordinate->number;  /* bus controlled by this HPC */
409 
410 	ctrl->device = PCI_SLOT(pdev->devfn);
411 	ctrl->function = PCI_FUNC(pdev->devfn);
412 	dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", __FUNCTION__,
413 		ctrl->bus, ctrl->device, ctrl->function, pdev->irq);
414 
415 	/*
416 	 *	Save configuration headers for this and subordinate PCI buses
417 	 */
418 
419 	rc = get_ctlr_slot_config(ctrl);
420 	if (rc) {
421 		err(msg_initialization_err, rc);
422 		goto err_out_free_ctrl_bus;
423 	}
424 	first_device_num = ctrl->slot_device_offset;
425 	num_ctlr_slots = ctrl->num_slots;
426 
427 	/* Store PCI Config Space for all devices on this bus */
428 	dbg("%s: Before calling pciehp_save_config, ctrl->bus %x,ctrl->slot_bus %x\n",
429 		__FUNCTION__,ctrl->bus, ctrl->slot_bus);
430 	rc = pciehp_save_config(ctrl, ctrl->slot_bus, num_ctlr_slots, first_device_num);
431 	if (rc) {
432 		err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc);
433 		goto err_out_free_ctrl_bus;
434 	}
435 
436 	/* Get IO, memory, and IRQ resources for new devices */
437 	rc = pciehprm_find_available_resources(ctrl);
438 	ctrl->add_support = !rc;
439 
440 	if (rc) {
441 		dbg("pciehprm_find_available_resources = %#x\n", rc);
442 		err("unable to locate PCI configuration resources for hot plug add.\n");
443 		goto err_out_free_ctrl_bus;
444 	}
445 
446 	/* Setup the slot information structures */
447 	rc = init_slots(ctrl);
448 	if (rc) {
449 		err(msg_initialization_err, 6);
450 		goto err_out_free_ctrl_slot;
451 	}
452 
453 	t_slot = pciehp_find_slot(ctrl, first_device_num);
454 	dbg("%s: t_slot %p\n", __FUNCTION__, t_slot);
455 
456 	/*	Finish setting up the hot plug ctrl device */
457 	ctrl->next_event = 0;
458 
459 	if (!pciehp_ctrl_list) {
460 		pciehp_ctrl_list = ctrl;
461 		ctrl->next = NULL;
462 	} else {
463 		ctrl->next = pciehp_ctrl_list;
464 		pciehp_ctrl_list = ctrl;
465 	}
466 
467 	/* Wait for exclusive access to hardware */
468 	down(&ctrl->crit_sect);
469 
470 	t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
471 	dbg("%s: adpater value %x\n", __FUNCTION__, value);
472 
473 	if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
474 		rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
475 		if (rc) {
476 			/* Done with exclusive hardware access */
477 			up(&ctrl->crit_sect);
478 			goto err_out_free_ctrl_slot;
479 		} else
480 			/* Wait for the command to complete */
481 			wait_for_ctrl_irq (ctrl);
482 	}
483 
484 	/* Done with exclusive hardware access */
485 	up(&ctrl->crit_sect);
486 
487 	return 0;
488 
489 err_out_free_ctrl_slot:
490 	cleanup_slots(ctrl);
491 err_out_free_ctrl_bus:
492 	kfree(ctrl->pci_bus);
493 err_out_unmap_mmio_region:
494 	ctrl->hpc_ops->release_ctlr(ctrl);
495 err_out_free_ctrl:
496 	kfree(ctrl);
497 err_out_none:
498 	return -ENODEV;
499 }
500 
501 
502 static int pcie_start_thread(void)
503 {
504 	int loop;
505 	int retval = 0;
506 
507 	dbg("Initialize + Start the notification/polling mechanism \n");
508 
509 	retval = pciehp_event_start_thread();
510 	if (retval) {
511 		dbg("pciehp_event_start_thread() failed\n");
512 		return retval;
513 	}
514 
515 	dbg("Initialize slot lists\n");
516 	/* One slot list for each bus in the system */
517 	for (loop = 0; loop < 256; loop++) {
518 		pciehp_slot_list[loop] = NULL;
519 	}
520 
521 	return retval;
522 }
523 
524 static inline void __exit
525 free_pciehp_res(struct pci_resource *res)
526 {
527 	struct pci_resource *tres;
528 
529 	while (res) {
530 		tres = res;
531 		res = res->next;
532 		kfree(tres);
533 	}
534 }
535 
536 static void __exit unload_pciehpd(void)
537 {
538 	struct pci_func *next;
539 	struct pci_func *TempSlot;
540 	int loop;
541 	struct controller *ctrl;
542 	struct controller *tctrl;
543 
544 	ctrl = pciehp_ctrl_list;
545 
546 	while (ctrl) {
547 		cleanup_slots(ctrl);
548 
549 		free_pciehp_res(ctrl->io_head);
550 		free_pciehp_res(ctrl->mem_head);
551 		free_pciehp_res(ctrl->p_mem_head);
552 		free_pciehp_res(ctrl->bus_head);
553 
554 		kfree (ctrl->pci_bus);
555 
556 		ctrl->hpc_ops->release_ctlr(ctrl);
557 
558 		tctrl = ctrl;
559 		ctrl = ctrl->next;
560 
561 		kfree(tctrl);
562 	}
563 
564 	for (loop = 0; loop < 256; loop++) {
565 		next = pciehp_slot_list[loop];
566 		while (next != NULL) {
567 			free_pciehp_res(next->io_head);
568 			free_pciehp_res(next->mem_head);
569 			free_pciehp_res(next->p_mem_head);
570 			free_pciehp_res(next->bus_head);
571 
572 			TempSlot = next;
573 			next = next->next;
574 			kfree(TempSlot);
575 		}
576 	}
577 
578 	/* Stop the notification mechanism */
579 	pciehp_event_stop_thread();
580 
581 }
582 
583 int hpdriver_context = 0;
584 
585 static void pciehp_remove (struct pcie_device *device)
586 {
587 	printk("%s ENTRY\n", __FUNCTION__);
588 	printk("%s -> Call free_irq for irq = %d\n",
589 		__FUNCTION__, device->irq);
590 	free_irq(device->irq, &hpdriver_context);
591 }
592 
593 #ifdef CONFIG_PM
594 static int pciehp_suspend (struct pcie_device *dev, pm_message_t state)
595 {
596 	printk("%s ENTRY\n", __FUNCTION__);
597 	return 0;
598 }
599 
600 static int pciehp_resume (struct pcie_device *dev)
601 {
602 	printk("%s ENTRY\n", __FUNCTION__);
603 	return 0;
604 }
605 #endif
606 
607 static struct pcie_port_service_id port_pci_ids[] = { {
608 	.vendor = PCI_ANY_ID,
609 	.device = PCI_ANY_ID,
610 	.port_type = PCIE_ANY_PORT,
611 	.service_type = PCIE_PORT_SERVICE_HP,
612 	.driver_data =	0,
613 	}, { /* end: all zeroes */ }
614 };
615 static const char device_name[] = "hpdriver";
616 
617 static struct pcie_port_service_driver hpdriver_portdrv = {
618 	.name		= (char *)device_name,
619 	.id_table	= &port_pci_ids[0],
620 
621 	.probe		= pciehp_probe,
622 	.remove		= pciehp_remove,
623 
624 #ifdef	CONFIG_PM
625 	.suspend	= pciehp_suspend,
626 	.resume		= pciehp_resume,
627 #endif	/* PM */
628 };
629 
630 static int __init pcied_init(void)
631 {
632 	int retval = 0;
633 
634 #ifdef CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE
635 	pciehp_poll_mode = 1;
636 #endif
637 
638 	retval = pcie_start_thread();
639 	if (retval)
640 		goto error_hpc_init;
641 
642 	retval = pciehprm_init(PCI);
643 	if (!retval) {
644  		retval = pcie_port_service_register(&hpdriver_portdrv);
645  		dbg("pcie_port_service_register = %d\n", retval);
646   		info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
647  		if (retval)
648  		   dbg("%s: Failure to register service\n", __FUNCTION__);
649 	}
650 
651 error_hpc_init:
652 	if (retval) {
653 		pciehprm_cleanup();
654 		pciehp_event_stop_thread();
655 	} else
656 		pciehprm_print_pirt();
657 
658 	return retval;
659 }
660 
661 static void __exit pcied_cleanup(void)
662 {
663 	dbg("unload_pciehpd()\n");
664 	unload_pciehpd();
665 
666 	pciehprm_cleanup();
667 
668 	dbg("pcie_port_service_unregister\n");
669 	pcie_port_service_unregister(&hpdriver_portdrv);
670 
671 	info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
672 }
673 
674 module_init(pcied_init);
675 module_exit(pcied_cleanup);
676