⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpci_hotplug_core.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -