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

📄 cpci_hotplug_core.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -