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.
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
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"
46 #define MY_NAME THIS_MODULE->name
49 #define dbg(format, arg...) \
52 printk (KERN_DEBUG "%s: " format "\n", \
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)
60 static spinlock_t list_lock;
61 static LIST_HEAD(slot_list);
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 = {
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 */
91 slot_paranoia_check(struct slot *slot, const char *function)
94 dbg("%s - slot == NULL", function);
97 if(slot->magic != SLOT_MAGIC) {
98 dbg("%s - bad magic number for slot", function);
101 if(!slot->hotplug_slot) {
102 dbg("%s - slot->hotplug_slot == NULL!", function);
108 static inline struct slot *
109 get_slot(struct hotplug_slot *hotplug_slot, const char *function)
114 dbg("%s - hotplug_slot == NULL", function);
118 slot = (struct slot *) hotplug_slot->private;
119 if(slot_paranoia_check(slot, function))
125 update_latch_status(struct hotplug_slot *hotplug_slot, u8 value)
127 struct hotplug_slot_info info;
129 if(!(hotplug_slot && hotplug_slot->info))
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);
137 update_adapter_status(struct hotplug_slot *hotplug_slot, u8 value)
139 struct hotplug_slot_info info;
141 if(!(hotplug_slot && hotplug_slot->info))
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);
149 enable_slot(struct hotplug_slot *hotplug_slot)
151 struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
157 dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
159 if(controller->ops->set_power) {
160 retval = controller->ops->set_power(slot, 1);
167 disable_slot(struct hotplug_slot *hotplug_slot)
169 struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
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);
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);
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;
210 cpci_get_power_status(struct slot *slot)
214 if(controller->ops->get_power) {
215 power = controller->ops->get_power(slot);
221 get_power_status(struct hotplug_slot *hotplug_slot, u8 * value)
223 struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
227 *value = cpci_get_power_status(slot);
232 get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value)
234 struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
238 *value = cpci_get_attention_status(slot);
243 set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
245 struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
251 cpci_set_attention_status(slot, 0);
256 cpci_set_attention_status(slot, 1);
264 get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value)
266 if(hotplug_slot == NULL || hotplug_slot->info == NULL)
268 *value = hotplug_slot->info->latch_status;
273 get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value)
275 if(hotplug_slot == NULL || hotplug_slot->info == NULL)
277 *value = hotplug_slot->info->adapter_status;
281 static void release_slot(struct hotplug_slot *hotplug_slot)
283 struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
288 kfree(slot->hotplug_slot->info);
289 kfree(slot->hotplug_slot->name);
290 kfree(slot->hotplug_slot);
294 #define SLOT_NAME_SIZE 6
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)
306 struct hotplug_slot *hotplug_slot;
307 struct hotplug_slot_info *info;
312 if(!(controller && bus)) {
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);
327 memset(slot, 0, sizeof (struct slot));
330 kmalloc(sizeof (struct hotplug_slot), GFP_KERNEL);
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);
344 memset(info, 0, sizeof (struct hotplug_slot_info));
345 hotplug_slot->info = info;
347 name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
354 hotplug_slot->name = name;
356 slot->magic = SLOT_MAGIC;
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
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);
377 err("pci_hp_register failed with error %d", status);
385 /* Add slot to our internal list */
386 spin_lock(&list_lock);
387 list_add(&slot->slot_list, &slot_list);
389 spin_unlock(&list_lock);
395 cpci_hp_unregister_bus(struct pci_bus *bus)
398 struct list_head *tmp;
399 struct list_head *next;
406 spin_lock(&list_lock);
408 spin_unlock(&list_lock);
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);
417 err("pci_hp_deregister failed with error %d",
422 list_del(&slot->slot_list);
426 spin_unlock(&list_lock);
430 /* This is the interrupt mode interrupt handler */
432 cpci_hp_intr(int irq, void *data, struct pt_regs *regs)
434 dbg("entered cpci_hp_intr");
436 /* Check to see if it was our interrupt */
437 if((controller->irq_flags & SA_SHIRQ) &&
438 !controller->ops->check_irq(controller->dev_id)) {
439 dbg("exited cpci_hp_intr, not our interrupt");
443 /* Disable ENUM interrupt */
444 controller->ops->disable_irq();
446 /* Trigger processing by the event thread */
447 dbg("Signal event_semaphore");
448 up(&event_semaphore);
449 dbg("exited cpci_hp_intr");
454 * According to PICMG 2.12 R2.0, section 6.3.2, upon
455 * initialization, the system driver shall clear the
456 * INS bits of the cold-inserted devices.
462 struct list_head *tmp;
465 dbg("%s - enter", __FUNCTION__);
466 spin_lock(&list_lock);
468 spin_unlock(&list_lock);
471 list_for_each(tmp, &slot_list) {
472 slot = list_entry(tmp, struct slot, slot_list);
473 dbg("%s - looking at slot %s",
474 __FUNCTION__, slot->hotplug_slot->name);
475 if(cpci_check_and_clear_ins(slot)) {
476 dbg("%s - cleared INS for slot %s",
477 __FUNCTION__, slot->hotplug_slot->name);
478 dev = pci_find_slot(slot->bus->number, PCI_DEVFN(slot->number, 0));
480 if(update_adapter_status(slot->hotplug_slot, 1)) {
481 warn("failure to update adapter file");
483 if(update_latch_status(slot->hotplug_slot, 1)) {
484 warn("failure to update latch file");
488 err("%s - no driver attached to device in slot %s",
489 __FUNCTION__, slot->hotplug_slot->name);
493 spin_unlock(&list_lock);
494 dbg("%s - exit", __FUNCTION__);
502 struct list_head *tmp;
506 spin_lock(&list_lock);
508 spin_unlock(&list_lock);
509 err("no slots registered, shutting down");
512 extracted = inserted = 0;
513 list_for_each(tmp, &slot_list) {
514 slot = list_entry(tmp, struct slot, slot_list);
515 dbg("%s - looking at slot %s",
516 __FUNCTION__, slot->hotplug_slot->name);
517 if(cpci_check_and_clear_ins(slot)) {
520 /* Some broken hardware (e.g. PLX 9054AB) asserts ENUM# twice... */
522 warn("slot %s already inserted", slot->hotplug_slot->name);
527 /* Process insertion */
528 dbg("%s - slot %s inserted",
529 __FUNCTION__, slot->hotplug_slot->name);
532 hs_csr = cpci_get_hs_csr(slot);
533 dbg("%s - slot %s HS_CSR (1) = %04x",
534 __FUNCTION__, slot->hotplug_slot->name, hs_csr);
536 /* Configure device */
537 dbg("%s - configuring slot %s",
538 __FUNCTION__, slot->hotplug_slot->name);
539 if(cpci_configure_slot(slot)) {
540 err("%s - could not configure slot %s",
541 __FUNCTION__, slot->hotplug_slot->name);
544 dbg("%s - finished configuring slot %s",
545 __FUNCTION__, slot->hotplug_slot->name);
548 hs_csr = cpci_get_hs_csr(slot);
549 dbg("%s - slot %s HS_CSR (2) = %04x",
550 __FUNCTION__, slot->hotplug_slot->name, hs_csr);
552 if(update_latch_status(slot->hotplug_slot, 1)) {
553 warn("failure to update latch file");
556 if(update_adapter_status(slot->hotplug_slot, 1)) {
557 warn("failure to update adapter file");
563 hs_csr = cpci_get_hs_csr(slot);
564 dbg("%s - slot %s HS_CSR (3) = %04x",
565 __FUNCTION__, slot->hotplug_slot->name, hs_csr);
568 } else if(cpci_check_ext(slot)) {
571 /* Process extraction request */
572 dbg("%s - slot %s extracted",
573 __FUNCTION__, slot->hotplug_slot->name);
576 hs_csr = cpci_get_hs_csr(slot);
577 dbg("%s - slot %s HS_CSR = %04x",
578 __FUNCTION__, slot->hotplug_slot->name, hs_csr);
580 if(!slot->extracting) {
581 if(update_latch_status(slot->hotplug_slot, 0)) {
582 warn("failure to update latch file");
584 slot->extracting = 1;
589 spin_unlock(&list_lock);
590 if(inserted || extracted) {
594 err("cannot find ENUM# source, shutting down");
599 /* This is the interrupt mode worker thread body */
601 event_thread(void *data)
605 struct list_head *tmp;
608 daemonize("cpci_hp_eventd");
611 dbg("%s - event thread started", __FUNCTION__);
613 dbg("event thread sleeping");
614 down_interruptible(&event_semaphore);
615 dbg("event thread woken, thread_finished = %d",
617 if(thread_finished || signal_pending(current))
619 while(controller->ops->query_enum()) {
622 /* Give userspace a chance to handle extraction */
623 set_current_state(TASK_INTERRUPTIBLE);
624 schedule_timeout(HZ / 2);
626 dbg("%s - error checking slots", __FUNCTION__);
631 /* Check for someone yanking out a board */
632 list_for_each(tmp, &slot_list) {
633 slot = list_entry(tmp, struct slot, slot_list);
634 if(slot->extracting) {
636 * Hmmm, we're likely hosed at this point, should we
637 * bother trying to tell the driver or not?
639 err("card in slot %s was improperly removed",
640 slot->hotplug_slot->name);
641 if(update_adapter_status(slot->hotplug_slot, 0)) {
642 warn("failure to update adapter file");
644 slot->extracting = 0;
648 /* Re-enable ENUM# interrupt */
649 dbg("%s - re-enabling irq", __FUNCTION__);
650 controller->ops->enable_irq();
653 dbg("%s - event thread signals exit", __FUNCTION__);
658 /* This is the polling mode worker thread body */
660 poll_thread(void *data)
664 struct list_head *tmp;
667 daemonize("cpci_hp_polld");
671 if(thread_finished || signal_pending(current))
674 while(controller->ops->query_enum()) {
677 /* Give userspace a chance to handle extraction */
678 set_current_state(TASK_INTERRUPTIBLE);
679 schedule_timeout(HZ / 2);
681 dbg("%s - error checking slots", __FUNCTION__);
686 /* Check for someone yanking out a board */
687 list_for_each(tmp, &slot_list) {
688 slot = list_entry(tmp, struct slot, slot_list);
689 if(slot->extracting) {
691 * Hmmm, we're likely hosed at this point, should we
692 * bother trying to tell the driver or not?
694 err("card in slot %s was improperly removed",
695 slot->hotplug_slot->name);
696 if(update_adapter_status(slot->hotplug_slot, 0)) {
697 warn("failure to update adapter file");
699 slot->extracting = 0;
703 set_current_state(TASK_INTERRUPTIBLE);
704 schedule_timeout(HZ / 10);
706 dbg("poll thread signals exit");
712 cpci_start_thread(void)
716 /* initialize our semaphores */
717 init_MUTEX_LOCKED(&event_semaphore);
718 init_MUTEX_LOCKED(&thread_exit);
721 if(controller->irq) {
722 pid = kernel_thread(event_thread, 0, 0);
724 pid = kernel_thread(poll_thread, 0, 0);
727 err("Can't start up our thread");
730 dbg("Our thread pid = %d", pid);
735 cpci_stop_thread(void)
738 dbg("thread finish command given");
739 if(controller->irq) {
740 up(&event_semaphore);
742 dbg("wait for thread to exit");
747 cpci_hp_register_controller(struct cpci_hp_controller *new_controller)
752 controller = new_controller;
753 if(controller->irq) {
754 if(request_irq(controller->irq,
756 controller->irq_flags,
757 MY_NAME, controller->dev_id)) {
758 err("Can't get irq %d for the hotplug cPCI controller", controller->irq);
761 dbg("%s - acquired controller irq %d", __FUNCTION__,
765 err("cPCI hotplug controller already registered");
772 cpci_hp_unregister_controller(struct cpci_hp_controller *old_controller)
777 if(!thread_finished) {
780 if(controller->irq) {
781 free_irq(controller->irq, controller->dev_id);
793 static int first = 1;
796 dbg("%s - enter", __FUNCTION__);
801 spin_lock(&list_lock);
803 spin_unlock(&list_lock);
806 spin_unlock(&list_lock);
809 status = init_slots();
816 status = cpci_start_thread();
820 dbg("%s - thread started", __FUNCTION__);
822 if(controller->irq) {
823 /* Start enum interrupt processing */
824 dbg("%s - enabling irq", __FUNCTION__);
825 controller->ops->enable_irq();
827 dbg("%s - exit", __FUNCTION__);
838 if(controller->irq) {
839 /* Stop enum interrupt processing */
840 dbg("%s - disabling irq", __FUNCTION__);
841 controller->ops->disable_irq();
850 struct list_head *tmp;
854 * Unregister all of our slots with the pci_hotplug subsystem,
855 * and free up all memory that we had allocated.
857 spin_lock(&list_lock);
861 list_for_each(tmp, &slot_list) {
862 slot = list_entry(tmp, struct slot, slot_list);
863 list_del(&slot->slot_list);
864 pci_hp_deregister(slot->hotplug_slot);
865 kfree(slot->hotplug_slot->info);
866 kfree(slot->hotplug_slot->name);
867 kfree(slot->hotplug_slot);
871 spin_unlock(&list_lock);
876 cpci_hotplug_init(int debug)
878 spin_lock_init(&list_lock);
881 info(DRIVER_DESC " version: " DRIVER_VERSION);
886 cpci_hotplug_exit(void)
889 * Clean everything up.
895 EXPORT_SYMBOL_GPL(cpci_hp_register_controller);
896 EXPORT_SYMBOL_GPL(cpci_hp_unregister_controller);
897 EXPORT_SYMBOL_GPL(cpci_hp_register_bus);
898 EXPORT_SYMBOL_GPL(cpci_hp_unregister_bus);
899 EXPORT_SYMBOL_GPL(cpci_hp_start);
900 EXPORT_SYMBOL_GPL(cpci_hp_stop);