Merge with Linux 2.5.74.
[linux-2.6/linux-mips.git] / drivers / pci / hotplug / cpci_hotplug_core.c
blob13a99b029cdf6f45b2b16e1cbcc186f255787bc9
1 /*
2 * CompactPCI Hot Plug Driver
4 * Copyright (c) 2002 SOMA Networks, Inc.
5 * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
6 * Copyright (c) 2001 IBM Corp.
8 * All rights reserved.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or (at
13 * your option) any later version.
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
18 * NON INFRINGEMENT. See the GNU General Public License for more
19 * details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 * Send feedback to <scottm@somanetworks.com>
28 #include <linux/config.h>
29 #include <linux/module.h>
30 #include <linux/kernel.h>
31 #include <linux/slab.h>
32 #include <linux/pci.h>
33 #include <linux/init.h>
34 #include <linux/interrupt.h>
35 #include <linux/smp_lock.h>
36 #include "pci_hotplug.h"
37 #include "cpci_hotplug.h"
39 #define DRIVER_VERSION "0.2"
40 #define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>"
41 #define DRIVER_DESC "CompactPCI Hot Plug Core"
43 #if !defined(CONFIG_HOTPLUG_CPCI_MODULE)
44 #define MY_NAME "cpci_hotplug"
45 #else
46 #define MY_NAME THIS_MODULE->name
47 #endif
49 #define dbg(format, arg...) \
50 do { \
51 if(cpci_debug) \
52 printk (KERN_DEBUG "%s: " format "\n", \
53 MY_NAME , ## arg); \
54 } while(0)
55 #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
56 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
57 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
59 /* local variables */
60 static spinlock_t list_lock;
61 static LIST_HEAD(slot_list);
62 static int slots;
63 int cpci_debug;
64 static struct cpci_hp_controller *controller;
65 static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */
66 static struct semaphore thread_exit; /* guard ensure thread has exited before calling it quits */
67 static int thread_finished = 1;
69 static int enable_slot(struct hotplug_slot *slot);
70 static int disable_slot(struct hotplug_slot *slot);
71 static int set_attention_status(struct hotplug_slot *slot, u8 value);
72 static int get_power_status(struct hotplug_slot *slot, u8 * value);
73 static int get_attention_status(struct hotplug_slot *slot, u8 * value);
74 static int get_latch_status(struct hotplug_slot *slot, u8 * value);
75 static int get_adapter_status(struct hotplug_slot *slot, u8 * value);
77 static struct hotplug_slot_ops cpci_hotplug_slot_ops = {
78 .owner = THIS_MODULE,
79 .enable_slot = enable_slot,
80 .disable_slot = disable_slot,
81 .set_attention_status = set_attention_status,
82 .hardware_test = NULL,
83 .get_power_status = get_power_status,
84 .get_attention_status = get_attention_status,
85 .get_latch_status = get_latch_status,
86 .get_adapter_status = get_adapter_status,
89 /* Inline functions to check the sanity of a pointer that is passed to us */
90 static inline int
91 slot_paranoia_check(struct slot *slot, const char *function)
93 if(!slot) {
94 dbg("%s - slot == NULL", function);
95 return -1;
97 if(slot->magic != SLOT_MAGIC) {
98 dbg("%s - bad magic number for slot", function);
99 return -1;
101 if(!slot->hotplug_slot) {
102 dbg("%s - slot->hotplug_slot == NULL!", function);
103 return -1;
105 return 0;
108 static inline struct slot *
109 get_slot(struct hotplug_slot *hotplug_slot, const char *function)
111 struct slot *slot;
113 if(!hotplug_slot) {
114 dbg("%s - hotplug_slot == NULL", function);
115 return NULL;
118 slot = (struct slot *) hotplug_slot->private;
119 if(slot_paranoia_check(slot, function))
120 return NULL;
121 return slot;
124 static int
125 update_latch_status(struct hotplug_slot *hotplug_slot, u8 value)
127 struct hotplug_slot_info info;
129 if(!(hotplug_slot && hotplug_slot->info))
130 return -EINVAL;
131 memcpy(&info, hotplug_slot->info, sizeof(struct hotplug_slot_info));
132 info.latch_status = value;
133 return pci_hp_change_slot_info(hotplug_slot, &info);
136 static int
137 update_adapter_status(struct hotplug_slot *hotplug_slot, u8 value)
139 struct hotplug_slot_info info;
141 if(!(hotplug_slot && hotplug_slot->info))
142 return -EINVAL;
143 memcpy(&info, hotplug_slot->info, sizeof(struct hotplug_slot_info));
144 info.adapter_status = value;
145 return pci_hp_change_slot_info(hotplug_slot, &info);
148 static int
149 enable_slot(struct hotplug_slot *hotplug_slot)
151 struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
152 int retval = 0;
154 if(slot == NULL)
155 return -ENODEV;
157 dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
159 if(controller->ops->set_power) {
160 retval = controller->ops->set_power(slot, 1);
163 return retval;
166 static int
167 disable_slot(struct hotplug_slot *hotplug_slot)
169 struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
170 int retval = 0;
172 if(slot == NULL)
173 return -ENODEV;
175 dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
177 /* Unconfigure device */
178 dbg("%s - unconfiguring slot %s",
179 __FUNCTION__, slot->hotplug_slot->name);
180 if((retval = cpci_unconfigure_slot(slot))) {
181 err("%s - could not unconfigure slot %s",
182 __FUNCTION__, slot->hotplug_slot->name);
183 return retval;
185 dbg("%s - finished unconfiguring slot %s",
186 __FUNCTION__, slot->hotplug_slot->name);
188 /* Clear EXT (by setting it) */
189 if(cpci_clear_ext(slot)) {
190 err("%s - could not clear EXT for slot %s",
191 __FUNCTION__, slot->hotplug_slot->name);
192 retval = -ENODEV;
194 cpci_led_on(slot);
196 if(controller->ops->set_power) {
197 retval = controller->ops->set_power(slot, 0);
200 if(update_adapter_status(slot->hotplug_slot, 0)) {
201 warn("failure to update adapter file");
204 slot->extracting = 0;
206 return retval;
209 static u8
210 cpci_get_power_status(struct slot *slot)
212 u8 power = 1;
214 if(controller->ops->get_power) {
215 power = controller->ops->get_power(slot);
217 return power;
220 static int
221 get_power_status(struct hotplug_slot *hotplug_slot, u8 * value)
223 struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
225 if(slot == NULL)
226 return -ENODEV;
227 *value = cpci_get_power_status(slot);
228 return 0;
231 static int
232 get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value)
234 struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
236 if(slot == NULL)
237 return -ENODEV;
238 *value = cpci_get_attention_status(slot);
239 return 0;
242 static int
243 set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
245 struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
247 if(slot == NULL)
248 return -ENODEV;
249 switch (status) {
250 case 0:
251 cpci_set_attention_status(slot, 0);
252 break;
254 case 1:
255 default:
256 cpci_set_attention_status(slot, 1);
257 break;
260 return 0;
263 static int
264 get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value)
266 if(hotplug_slot == NULL || hotplug_slot->info == NULL)
267 return -ENODEV;
268 *value = hotplug_slot->info->latch_status;
269 return 0;
272 static int
273 get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value)
275 if(hotplug_slot == NULL || hotplug_slot->info == NULL)
276 return -ENODEV;
277 *value = hotplug_slot->info->adapter_status;
278 return 0;
281 static void release_slot(struct hotplug_slot *hotplug_slot)
283 struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
285 if(slot == NULL)
286 return;
288 kfree(slot->hotplug_slot->info);
289 kfree(slot->hotplug_slot->name);
290 kfree(slot->hotplug_slot);
291 kfree(slot);
294 #define SLOT_NAME_SIZE 6
295 static void
296 make_slot_name(struct slot *slot)
298 snprintf(slot->hotplug_slot->name,
299 SLOT_NAME_SIZE, "%02x:%02x", slot->bus->number, slot->number);
303 cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
305 struct slot *slot;
306 struct hotplug_slot *hotplug_slot;
307 struct hotplug_slot_info *info;
308 char *name;
309 int status = 0;
310 int i;
312 if(!(controller && bus)) {
313 return -ENODEV;
315 if(last < first) {
316 return -EINVAL;
320 * Create a structure for each slot, and register that slot
321 * with the pci_hotplug subsystem.
323 for (i = first; i <= last; ++i) {
324 slot = kmalloc(sizeof (struct slot), GFP_KERNEL);
325 if(!slot)
326 return -ENOMEM;
327 memset(slot, 0, sizeof (struct slot));
329 hotplug_slot =
330 kmalloc(sizeof (struct hotplug_slot), GFP_KERNEL);
331 if(!hotplug_slot) {
332 kfree(slot);
333 return -ENOMEM;
335 memset(hotplug_slot, 0, sizeof (struct hotplug_slot));
336 slot->hotplug_slot = hotplug_slot;
338 info = kmalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL);
339 if(!info) {
340 kfree(hotplug_slot);
341 kfree(slot);
342 return -ENOMEM;
344 memset(info, 0, sizeof (struct hotplug_slot_info));
345 hotplug_slot->info = info;
347 name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
348 if(!name) {
349 kfree(info);
350 kfree(hotplug_slot);
351 kfree(slot);
352 return -ENOMEM;
354 hotplug_slot->name = name;
356 slot->magic = SLOT_MAGIC;
357 slot->bus = bus;
358 slot->number = i;
359 slot->devfn = PCI_DEVFN(i, 0);
361 hotplug_slot->private = slot;
362 hotplug_slot->release = &release_slot;
363 make_slot_name(slot);
364 hotplug_slot->ops = &cpci_hotplug_slot_ops;
367 * Initialize the slot info structure with some known
368 * good values.
370 dbg("initializing slot %s", slot->hotplug_slot->name);
371 info->power_status = cpci_get_power_status(slot);
372 info->attention_status = cpci_get_attention_status(slot);
374 dbg("registering slot %s", slot->hotplug_slot->name);
375 status = pci_hp_register(slot->hotplug_slot);
376 if(status) {
377 err("pci_hp_register failed with error %d", status);
378 kfree(info);
379 kfree(name);
380 kfree(hotplug_slot);
381 kfree(slot);
382 return status;
385 /* Add slot to our internal list */
386 spin_lock(&list_lock);
387 list_add(&slot->slot_list, &slot_list);
388 slots++;
389 spin_unlock(&list_lock);
391 return status;
395 cpci_hp_unregister_bus(struct pci_bus *bus)
397 struct slot *slot;
398 struct list_head *tmp;
399 struct list_head *next;
400 int status;
402 if(!bus) {
403 return -ENODEV;
406 spin_lock(&list_lock);
407 if(!slots) {
408 spin_unlock(&list_lock);
409 return -1;
411 list_for_each_safe(tmp, next, &slot_list) {
412 slot = list_entry(tmp, struct slot, slot_list);
413 if(slot->bus == bus) {
414 dbg("deregistering slot %s", slot->hotplug_slot->name);
415 status = pci_hp_deregister(slot->hotplug_slot);
416 if(status) {
417 err("pci_hp_deregister failed with error %d",
418 status);
419 return status;
422 list_del(&slot->slot_list);
423 slots--;
426 spin_unlock(&list_lock);
427 return 0;
430 struct slot *
431 cpci_find_slot(struct pci_bus *bus, unsigned int devfn)
433 struct slot *slot;
434 struct slot *found;
435 struct list_head *tmp;
437 if(!bus) {
438 return NULL;
441 spin_lock(&list_lock);
442 if(!slots) {
443 spin_unlock(&list_lock);
444 return NULL;
446 found = NULL;
447 list_for_each(tmp, &slot_list) {
448 slot = list_entry(tmp, struct slot, slot_list);
449 if(slot->bus == bus && slot->devfn == devfn) {
450 found = slot;
451 break;
454 spin_unlock(&list_lock);
455 return found;
458 /* This is the interrupt mode interrupt handler */
459 irqreturn_t
460 cpci_hp_intr(int irq, void *data, struct pt_regs *regs)
462 dbg("entered cpci_hp_intr");
464 /* Check to see if it was our interrupt */
465 if((controller->irq_flags & SA_SHIRQ) &&
466 !controller->ops->check_irq(controller->dev_id)) {
467 dbg("exited cpci_hp_intr, not our interrupt");
468 return IRQ_NONE;
471 /* Disable ENUM interrupt */
472 controller->ops->disable_irq();
474 /* Trigger processing by the event thread */
475 dbg("Signal event_semaphore");
476 up(&event_semaphore);
477 dbg("exited cpci_hp_intr");
478 return IRQ_HANDLED;
482 * According to PICMG 2.12 R2.0, section 6.3.2, upon
483 * initialization, the system driver shall clear the
484 * INS bits of the cold-inserted devices.
486 static int
487 init_slots(void)
489 struct slot *slot;
490 struct list_head *tmp;
491 struct pci_dev* dev;
493 dbg("%s - enter", __FUNCTION__);
494 spin_lock(&list_lock);
495 if(!slots) {
496 spin_unlock(&list_lock);
497 return -1;
499 list_for_each(tmp, &slot_list) {
500 slot = list_entry(tmp, struct slot, slot_list);
501 dbg("%s - looking at slot %s",
502 __FUNCTION__, slot->hotplug_slot->name);
503 if(cpci_check_and_clear_ins(slot)) {
504 dbg("%s - cleared INS for slot %s",
505 __FUNCTION__, slot->hotplug_slot->name);
506 dev = pci_find_slot(slot->bus->number, PCI_DEVFN(slot->number, 0));
507 if(dev) {
508 if(update_adapter_status(slot->hotplug_slot, 1)) {
509 warn("failure to update adapter file");
511 if(update_latch_status(slot->hotplug_slot, 1)) {
512 warn("failure to update latch file");
514 slot->dev = dev;
515 } else {
516 err("%s - no driver attached to device in slot %s",
517 __FUNCTION__, slot->hotplug_slot->name);
521 spin_unlock(&list_lock);
522 dbg("%s - exit", __FUNCTION__);
523 return 0;
526 static int
527 check_slots(void)
529 struct slot *slot;
530 struct list_head *tmp;
531 int extracted;
532 int inserted;
534 spin_lock(&list_lock);
535 if(!slots) {
536 spin_unlock(&list_lock);
537 err("no slots registered, shutting down");
538 return -1;
540 extracted = inserted = 0;
541 list_for_each(tmp, &slot_list) {
542 slot = list_entry(tmp, struct slot, slot_list);
543 dbg("%s - looking at slot %s",
544 __FUNCTION__, slot->hotplug_slot->name);
545 if(cpci_check_and_clear_ins(slot)) {
546 u16 hs_csr;
548 /* Some broken hardware (e.g. PLX 9054AB) asserts ENUM# twice... */
549 if(slot->dev) {
550 warn("slot %s already inserted", slot->hotplug_slot->name);
551 inserted++;
552 continue;
555 /* Process insertion */
556 dbg("%s - slot %s inserted",
557 __FUNCTION__, slot->hotplug_slot->name);
559 /* GSM, debug */
560 hs_csr = cpci_get_hs_csr(slot);
561 dbg("%s - slot %s HS_CSR (1) = %04x",
562 __FUNCTION__, slot->hotplug_slot->name, hs_csr);
564 /* Configure device */
565 dbg("%s - configuring slot %s",
566 __FUNCTION__, slot->hotplug_slot->name);
567 if(cpci_configure_slot(slot)) {
568 err("%s - could not configure slot %s",
569 __FUNCTION__, slot->hotplug_slot->name);
570 continue;
572 dbg("%s - finished configuring slot %s",
573 __FUNCTION__, slot->hotplug_slot->name);
575 /* GSM, debug */
576 hs_csr = cpci_get_hs_csr(slot);
577 dbg("%s - slot %s HS_CSR (2) = %04x",
578 __FUNCTION__, slot->hotplug_slot->name, hs_csr);
580 if(update_latch_status(slot->hotplug_slot, 1)) {
581 warn("failure to update latch file");
584 if(update_adapter_status(slot->hotplug_slot, 1)) {
585 warn("failure to update adapter file");
588 cpci_led_off(slot);
590 /* GSM, debug */
591 hs_csr = cpci_get_hs_csr(slot);
592 dbg("%s - slot %s HS_CSR (3) = %04x",
593 __FUNCTION__, slot->hotplug_slot->name, hs_csr);
595 inserted++;
596 } else if(cpci_check_ext(slot)) {
597 u16 hs_csr;
599 /* Process extraction request */
600 dbg("%s - slot %s extracted",
601 __FUNCTION__, slot->hotplug_slot->name);
603 /* GSM, debug */
604 hs_csr = cpci_get_hs_csr(slot);
605 dbg("%s - slot %s HS_CSR = %04x",
606 __FUNCTION__, slot->hotplug_slot->name, hs_csr);
608 if(!slot->extracting) {
609 if(update_latch_status(slot->hotplug_slot, 0)) {
610 warn("failure to update latch file");
612 slot->extracting = 1;
614 extracted++;
617 spin_unlock(&list_lock);
618 if(inserted || extracted) {
619 return extracted;
621 else {
622 err("cannot find ENUM# source, shutting down");
623 return -1;
627 /* This is the interrupt mode worker thread body */
628 static int
629 event_thread(void *data)
631 int rc;
632 struct slot *slot;
633 struct list_head *tmp;
635 lock_kernel();
636 daemonize("cpci_hp_eventd");
637 unlock_kernel();
639 dbg("%s - event thread started", __FUNCTION__);
640 while(1) {
641 dbg("event thread sleeping");
642 down_interruptible(&event_semaphore);
643 dbg("event thread woken, thread_finished = %d",
644 thread_finished);
645 if(thread_finished || signal_pending(current))
646 break;
647 while(controller->ops->query_enum()) {
648 rc = check_slots();
649 if(rc > 0) {
650 /* Give userspace a chance to handle extraction */
651 set_current_state(TASK_INTERRUPTIBLE);
652 schedule_timeout(HZ / 2);
653 } else if(rc < 0) {
654 dbg("%s - error checking slots", __FUNCTION__);
655 thread_finished = 1;
656 break;
659 /* Check for someone yanking out a board */
660 list_for_each(tmp, &slot_list) {
661 slot = list_entry(tmp, struct slot, slot_list);
662 if(slot->extracting) {
664 * Hmmm, we're likely hosed at this point, should we
665 * bother trying to tell the driver or not?
667 err("card in slot %s was improperly removed",
668 slot->hotplug_slot->name);
669 if(update_adapter_status(slot->hotplug_slot, 0)) {
670 warn("failure to update adapter file");
672 slot->extracting = 0;
676 /* Re-enable ENUM# interrupt */
677 dbg("%s - re-enabling irq", __FUNCTION__);
678 controller->ops->enable_irq();
681 dbg("%s - event thread signals exit", __FUNCTION__);
682 up(&thread_exit);
683 return 0;
686 /* This is the polling mode worker thread body */
687 static int
688 poll_thread(void *data)
690 int rc;
691 struct slot *slot;
692 struct list_head *tmp;
694 lock_kernel();
695 daemonize("cpci_hp_polld");
696 unlock_kernel();
698 while(1) {
699 if(thread_finished || signal_pending(current))
700 break;
702 while(controller->ops->query_enum()) {
703 rc = check_slots();
704 if(rc > 0) {
705 /* Give userspace a chance to handle extraction */
706 set_current_state(TASK_INTERRUPTIBLE);
707 schedule_timeout(HZ / 2);
708 } else if(rc < 0) {
709 dbg("%s - error checking slots", __FUNCTION__);
710 thread_finished = 1;
711 break;
714 /* Check for someone yanking out a board */
715 list_for_each(tmp, &slot_list) {
716 slot = list_entry(tmp, struct slot, slot_list);
717 if(slot->extracting) {
719 * Hmmm, we're likely hosed at this point, should we
720 * bother trying to tell the driver or not?
722 err("card in slot %s was improperly removed",
723 slot->hotplug_slot->name);
724 if(update_adapter_status(slot->hotplug_slot, 0)) {
725 warn("failure to update adapter file");
727 slot->extracting = 0;
731 set_current_state(TASK_INTERRUPTIBLE);
732 schedule_timeout(HZ / 10);
734 dbg("poll thread signals exit");
735 up(&thread_exit);
736 return 0;
739 static int
740 cpci_start_thread(void)
742 int pid;
744 /* initialize our semaphores */
745 init_MUTEX_LOCKED(&event_semaphore);
746 init_MUTEX_LOCKED(&thread_exit);
747 thread_finished = 0;
749 if(controller->irq) {
750 pid = kernel_thread(event_thread, 0, 0);
751 } else {
752 pid = kernel_thread(poll_thread, 0, 0);
754 if(pid < 0) {
755 err("Can't start up our thread");
756 return -1;
758 dbg("Our thread pid = %d", pid);
759 return 0;
762 static void
763 cpci_stop_thread(void)
765 thread_finished = 1;
766 dbg("thread finish command given");
767 if(controller->irq) {
768 up(&event_semaphore);
770 dbg("wait for thread to exit");
771 down(&thread_exit);
775 cpci_hp_register_controller(struct cpci_hp_controller *new_controller)
777 int status = 0;
779 if(!controller) {
780 controller = new_controller;
781 if(controller->irq) {
782 if(request_irq(controller->irq,
783 cpci_hp_intr,
784 controller->irq_flags,
785 MY_NAME, controller->dev_id)) {
786 err("Can't get irq %d for the hotplug cPCI controller", controller->irq);
787 status = -ENODEV;
789 dbg("%s - acquired controller irq %d", __FUNCTION__,
790 controller->irq);
792 } else {
793 err("cPCI hotplug controller already registered");
794 status = -1;
796 return status;
800 cpci_hp_unregister_controller(struct cpci_hp_controller *old_controller)
802 int status = 0;
804 if(controller) {
805 if(!thread_finished) {
806 cpci_stop_thread();
808 if(controller->irq) {
809 free_irq(controller->irq, controller->dev_id);
811 controller = NULL;
812 } else {
813 status = -ENODEV;
815 return status;
819 cpci_hp_start(void)
821 static int first = 1;
822 int status;
824 dbg("%s - enter", __FUNCTION__);
825 if(!controller) {
826 return -ENODEV;
829 spin_lock(&list_lock);
830 if(!slots) {
831 spin_unlock(&list_lock);
832 return -ENODEV;
834 spin_unlock(&list_lock);
836 if(first) {
837 status = init_slots();
838 if(status) {
839 return status;
841 first = 0;
844 status = cpci_start_thread();
845 if(status) {
846 return status;
848 dbg("%s - thread started", __FUNCTION__);
850 if(controller->irq) {
851 /* Start enum interrupt processing */
852 dbg("%s - enabling irq", __FUNCTION__);
853 controller->ops->enable_irq();
855 dbg("%s - exit", __FUNCTION__);
856 return 0;
860 cpci_hp_stop(void)
862 if(!controller) {
863 return -ENODEV;
866 if(controller->irq) {
867 /* Stop enum interrupt processing */
868 dbg("%s - disabling irq", __FUNCTION__);
869 controller->ops->disable_irq();
871 cpci_stop_thread();
872 return 0;
875 static void __exit
876 cleanup_slots(void)
878 struct list_head *tmp;
879 struct slot *slot;
882 * Unregister all of our slots with the pci_hotplug subsystem,
883 * and free up all memory that we had allocated.
885 spin_lock(&list_lock);
886 if(!slots) {
887 goto null_cleanup;
889 list_for_each(tmp, &slot_list) {
890 slot = list_entry(tmp, struct slot, slot_list);
891 list_del(&slot->slot_list);
892 pci_hp_deregister(slot->hotplug_slot);
893 kfree(slot->hotplug_slot->info);
894 kfree(slot->hotplug_slot->name);
895 kfree(slot->hotplug_slot);
896 kfree(slot);
898 null_cleanup:
899 spin_unlock(&list_lock);
900 return;
903 int __init
904 cpci_hotplug_init(int debug)
906 spin_lock_init(&list_lock);
907 cpci_debug = debug;
909 info(DRIVER_DESC " version: " DRIVER_VERSION);
910 return 0;
913 void __exit
914 cpci_hotplug_exit(void)
917 * Clean everything up.
919 cleanup_slots();
923 EXPORT_SYMBOL_GPL(cpci_hp_register_controller);
924 EXPORT_SYMBOL_GPL(cpci_hp_unregister_controller);
925 EXPORT_SYMBOL_GPL(cpci_hp_register_bus);
926 EXPORT_SYMBOL_GPL(cpci_hp_unregister_bus);
927 EXPORT_SYMBOL_GPL(cpci_find_slot);
928 EXPORT_SYMBOL_GPL(cpci_hp_start);
929 EXPORT_SYMBOL_GPL(cpci_hp_stop);