📄 cpci_hotplug_core.c
字号:
int inserted; spin_lock(&list_lock); if(!slots) { spin_unlock(&list_lock); err("no slots registered, shutting down"); return -1; } extracted = inserted = 0; list_for_each(tmp, &slot_list) { slot = list_entry(tmp, struct slot, slot_list); dbg("%s - looking at slot %s", __FUNCTION__, slot->hotplug_slot->name); if(cpci_check_and_clear_ins(slot)) { u16 hs_csr; /* Some broken hardware (e.g. PLX 9054AB) asserts ENUM# twice... */ if(slot->dev) { warn("slot %s already inserted", slot->hotplug_slot->name); inserted++; continue; } /* Process insertion */ dbg("%s - slot %s inserted", __FUNCTION__, slot->hotplug_slot->name); /* GSM, debug */ hs_csr = cpci_get_hs_csr(slot); dbg("%s - slot %s HS_CSR (1) = %04x", __FUNCTION__, slot->hotplug_slot->name, hs_csr); /* Configure device */ dbg("%s - configuring slot %s", __FUNCTION__, slot->hotplug_slot->name); if(cpci_configure_slot(slot)) { err("%s - could not configure slot %s", __FUNCTION__, slot->hotplug_slot->name); continue; } dbg("%s - finished configuring slot %s", __FUNCTION__, slot->hotplug_slot->name); /* GSM, debug */ hs_csr = cpci_get_hs_csr(slot); dbg("%s - slot %s HS_CSR (2) = %04x", __FUNCTION__, slot->hotplug_slot->name, hs_csr); if(update_latch_status(slot->hotplug_slot, 1)) { warn("failure to update latch file"); } if(update_adapter_status(slot->hotplug_slot, 1)) { warn("failure to update adapter file"); } cpci_led_off(slot); /* GSM, debug */ hs_csr = cpci_get_hs_csr(slot); dbg("%s - slot %s HS_CSR (3) = %04x", __FUNCTION__, slot->hotplug_slot->name, hs_csr); inserted++; } else if(cpci_check_ext(slot)) { u16 hs_csr; /* Process extraction request */ dbg("%s - slot %s extracted", __FUNCTION__, slot->hotplug_slot->name); /* GSM, debug */ hs_csr = cpci_get_hs_csr(slot); dbg("%s - slot %s HS_CSR = %04x", __FUNCTION__, slot->hotplug_slot->name, hs_csr); if(!slot->extracting) { if(update_latch_status(slot->hotplug_slot, 0)) { warn("failure to update latch file"); } slot->extracting = 1; } extracted++; } } spin_unlock(&list_lock); if(inserted || extracted) { return extracted; } else { err("cannot find ENUM# source, shutting down"); return -1; }}/* This is the interrupt mode worker thread body */static intevent_thread(void *data){ int rc; struct slot *slot; struct list_head *tmp; lock_kernel(); daemonize("cpci_hp_eventd"); unlock_kernel(); dbg("%s - event thread started", __FUNCTION__); while(1) { dbg("event thread sleeping"); down_interruptible(&event_semaphore); dbg("event thread woken, thread_finished = %d", thread_finished); if(thread_finished || signal_pending(current)) break; while(controller->ops->query_enum()) { rc = check_slots(); if(rc > 0) { /* Give userspace a chance to handle extraction */ set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ / 2); } else if(rc < 0) { dbg("%s - error checking slots", __FUNCTION__); thread_finished = 1; break; } } /* Check for someone yanking out a board */ list_for_each(tmp, &slot_list) { slot = list_entry(tmp, struct slot, slot_list); if(slot->extracting) { /* * Hmmm, we're likely hosed at this point, should we * bother trying to tell the driver or not? */ err("card in slot %s was improperly removed", slot->hotplug_slot->name); if(update_adapter_status(slot->hotplug_slot, 0)) { warn("failure to update adapter file"); } slot->extracting = 0; } } /* Re-enable ENUM# interrupt */ dbg("%s - re-enabling irq", __FUNCTION__); controller->ops->enable_irq(); } dbg("%s - event thread signals exit", __FUNCTION__); up(&thread_exit); return 0;}/* This is the polling mode worker thread body */static intpoll_thread(void *data){ int rc; struct slot *slot; struct list_head *tmp; lock_kernel(); daemonize("cpci_hp_polld"); unlock_kernel(); while(1) { if(thread_finished || signal_pending(current)) break; while(controller->ops->query_enum()) { rc = check_slots(); if(rc > 0) { /* Give userspace a chance to handle extraction */ set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ / 2); } else if(rc < 0) { dbg("%s - error checking slots", __FUNCTION__); thread_finished = 1; break; } } /* Check for someone yanking out a board */ list_for_each(tmp, &slot_list) { slot = list_entry(tmp, struct slot, slot_list); if(slot->extracting) { /* * Hmmm, we're likely hosed at this point, should we * bother trying to tell the driver or not? */ err("card in slot %s was improperly removed", slot->hotplug_slot->name); if(update_adapter_status(slot->hotplug_slot, 0)) { warn("failure to update adapter file"); } slot->extracting = 0; } } set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ / 10); } dbg("poll thread signals exit"); up(&thread_exit); return 0;}static intcpci_start_thread(void){ int pid; /* initialize our semaphores */ init_MUTEX_LOCKED(&event_semaphore); init_MUTEX_LOCKED(&thread_exit); thread_finished = 0; if(controller->irq) { pid = kernel_thread(event_thread, NULL, 0); } else { pid = kernel_thread(poll_thread, NULL, 0); } if(pid < 0) { err("Can't start up our thread"); return -1; } dbg("Our thread pid = %d", pid); return 0;}static voidcpci_stop_thread(void){ thread_finished = 1; dbg("thread finish command given"); if(controller->irq) { up(&event_semaphore); } dbg("wait for thread to exit"); down(&thread_exit);}intcpci_hp_register_controller(struct cpci_hp_controller *new_controller){ int status = 0; if(!controller) { controller = new_controller; if(controller->irq) { if(request_irq(controller->irq, cpci_hp_intr, controller->irq_flags, MY_NAME, controller->dev_id)) { err("Can't get irq %d for the hotplug cPCI controller", controller->irq); status = -ENODEV; } dbg("%s - acquired controller irq %d", __FUNCTION__, controller->irq); } } else { err("cPCI hotplug controller already registered"); status = -1; } return status;}intcpci_hp_unregister_controller(struct cpci_hp_controller *old_controller){ int status = 0; if(controller) { if(!thread_finished) { cpci_stop_thread(); } if(controller->irq) { free_irq(controller->irq, controller->dev_id); } controller = NULL; } else { status = -ENODEV; } return status;}intcpci_hp_start(void){ static int first = 1; int status; dbg("%s - enter", __FUNCTION__); if(!controller) { return -ENODEV; } spin_lock(&list_lock); if(!slots) { spin_unlock(&list_lock); return -ENODEV; } spin_unlock(&list_lock); if(first) { status = init_slots(); if(status) { return status; } first = 0; } status = cpci_start_thread(); if(status) { return status; } dbg("%s - thread started", __FUNCTION__); if(controller->irq) { /* Start enum interrupt processing */ dbg("%s - enabling irq", __FUNCTION__); controller->ops->enable_irq(); } dbg("%s - exit", __FUNCTION__); return 0;}intcpci_hp_stop(void){ if(!controller) { return -ENODEV; } if(controller->irq) { /* Stop enum interrupt processing */ dbg("%s - disabling irq", __FUNCTION__); controller->ops->disable_irq(); } cpci_stop_thread(); return 0;}static void __exitcleanup_slots(void){ struct list_head *tmp; struct slot *slot; /* * Unregister all of our slots with the pci_hotplug subsystem, * and free up all memory that we had allocated. */ spin_lock(&list_lock); if(!slots) { goto null_cleanup; } list_for_each(tmp, &slot_list) { slot = list_entry(tmp, struct slot, slot_list); list_del(&slot->slot_list); pci_hp_deregister(slot->hotplug_slot); kfree(slot->hotplug_slot->info); kfree(slot->hotplug_slot->name); kfree(slot->hotplug_slot); kfree(slot); } null_cleanup: spin_unlock(&list_lock); return;}int __initcpci_hotplug_init(int debug){ spin_lock_init(&list_lock); cpci_debug = debug; info(DRIVER_DESC " version: " DRIVER_VERSION); return 0;}void __exitcpci_hotplug_exit(void){ /* * Clean everything up. */ cleanup_slots();}EXPORT_SYMBOL_GPL(cpci_hp_register_controller);EXPORT_SYMBOL_GPL(cpci_hp_unregister_controller);EXPORT_SYMBOL_GPL(cpci_hp_register_bus);EXPORT_SYMBOL_GPL(cpci_hp_unregister_bus);EXPORT_SYMBOL_GPL(cpci_hp_start);EXPORT_SYMBOL_GPL(cpci_hp_stop);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -