📄 cpci_hotplug_core.c
字号:
list_for_each_entry(slot, &slot_list, slot_list) { dbg("%s - looking at slot %s", __FUNCTION__, slot->hotplug_slot->name); if (clear_ins && cpci_check_and_clear_ins(slot)) dbg("%s - cleared INS for slot %s", __FUNCTION__, slot->hotplug_slot->name); dev = pci_get_slot(slot->bus, PCI_DEVFN(slot->number, 0)); if (dev) { if (update_adapter_status(slot->hotplug_slot, 1)) warn("failure to update adapter file"); if (update_latch_status(slot->hotplug_slot, 1)) warn("failure to update latch file"); slot->dev = dev; } } up_read(&list_rwsem); dbg("%s - exit", __FUNCTION__); return 0;}static intcheck_slots(void){ struct slot *slot; int extracted; int inserted; u16 hs_csr; down_read(&list_rwsem); if (!slots) { up_read(&list_rwsem); err("no slots registered, shutting down"); return -1; } extracted = inserted = 0; list_for_each_entry(slot, &slot_list, slot_list) { dbg("%s - looking at slot %s", __FUNCTION__, slot->hotplug_slot->name); if (cpci_check_and_clear_ins(slot)) { /* * 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)) { /* 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; atomic_inc(&extracting); } extracted++; } else if (slot->extracting) { hs_csr = cpci_get_hs_csr(slot); if (hs_csr == 0xffff) { /* * 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; atomic_dec(&extracting); } } } up_read(&list_rwsem); dbg("inserted=%d, extracted=%d, extracting=%d", inserted, extracted, atomic_read(&extracting)); if (inserted || extracted) return extracted; else if (!atomic_read(&extracting)) { err("cannot find ENUM# source, shutting down"); return -1; } return 0;}/* This is the interrupt mode worker thread body */static intevent_thread(void *data){ int rc; 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; do { rc = check_slots(); if (rc > 0) { /* Give userspace a chance to handle extraction */ msleep(500); } else if (rc < 0) { dbg("%s - error checking slots", __FUNCTION__); thread_finished = 1; break; } } while (atomic_read(&extracting) && !thread_finished); if (thread_finished) break; /* 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; lock_kernel(); daemonize("cpci_hp_polld"); unlock_kernel(); while (1) { if (thread_finished || signal_pending(current)) break; if (controller->ops->query_enum()) { do { rc = check_slots(); if (rc > 0) { /* Give userspace a chance to handle extraction */ msleep(500); } else if (rc < 0) { dbg("%s - error checking slots", __FUNCTION__); thread_finished = 1; break; } } while (atomic_read(&extracting) && !thread_finished); } msleep(100); } 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) return -1; if (!(new_controller && new_controller->ops)) return -EINVAL; if (new_controller->irq) { if (!(new_controller->ops->enable_irq && new_controller->ops->disable_irq)) status = -EINVAL; if (request_irq(new_controller->irq, cpci_hp_intr, new_controller->irq_flags, MY_NAME, new_controller->dev_id)) { err("Can't get irq %d for the hotplug cPCI controller", new_controller->irq); status = -ENODEV; } dbg("%s - acquired controller irq %d", __FUNCTION__, new_controller->irq); } if (!status) controller = new_controller; return status;}static voidcleanup_slots(void){ struct slot *slot; struct slot *tmp; /* * Unregister all of our slots with the pci_hotplug subsystem, * and free up all memory that we had allocated. */ down_write(&list_rwsem); if (!slots) goto cleanup_null; list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) { list_del(&slot->slot_list); pci_hp_deregister(slot->hotplug_slot); }cleanup_null: up_write(&list_rwsem); return;}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; cleanup_slots(); } else status = -ENODEV; return status;}intcpci_hp_start(void){ static int first = 1; int status; dbg("%s - enter", __FUNCTION__); if (!controller) return -ENODEV; down_read(&list_rwsem); if (list_empty(&slot_list)) { up_read(&list_rwsem); return -ENODEV; } up_read(&list_rwsem); status = init_slots(first); if (first) first = 0; if (status) return status; 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;}int __initcpci_hotplug_init(int debug){ cpci_debug = debug; return 0;}void __exitcpci_hotplug_exit(void){ /* * Clean everything up. */ cpci_hp_stop(); cpci_hp_unregister_controller(controller);}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 + -