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

📄 viopath.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		return;	if (hvlpevent_is_int(event)) {		printk(VIOPATH_KERN_WARN		       "unexpected config request from partition %d",		       event->xSourceLp);		if (hvlpevent_need_ack(event)) {			event->xRc = HvLpEvent_Rc_InvalidSubtype;			HvCallEvent_ackLpEvent(event);		}		return;	}	complete((struct completion *)event->xCorrelationToken);}/* * Initialization of the hosting partition */void vio_set_hostlp(void){	/*	 * If this has already been set then we DON'T want to either change	 * it or re-register the proc file system	 */	if (viopath_hostLp != HvLpIndexInvalid)		return;	/*	 * Figure out our hosting partition.  This isn't allowed to change	 * while we're active	 */	viopath_ourLp = HvLpConfig_getLpIndex();	viopath_hostLp = HvLpConfig_getHostingLpIndex(viopath_ourLp);	if (viopath_hostLp != HvLpIndexInvalid)		vio_setHandler(viomajorsubtype_config, handleConfig);}EXPORT_SYMBOL(vio_set_hostlp);static void vio_handleEvent(struct HvLpEvent *event){	HvLpIndex remoteLp;	int subtype = (event->xSubtype & VIOMAJOR_SUBTYPE_MASK)		>> VIOMAJOR_SUBTYPE_SHIFT;	if (hvlpevent_is_int(event)) {		remoteLp = event->xSourceLp;		/*		 * The isActive is checked because if the hosting partition		 * went down and came back up it would not be active but it		 * would have different source and target instances, in which		 * case we'd want to reset them.  This case really protects		 * against an unauthorized active partition sending interrupts		 * or acks to this linux partition.		 */		if (viopathStatus[remoteLp].isActive		    && (event->xSourceInstanceId !=			viopathStatus[remoteLp].mTargetInst)) {			printk(VIOPATH_KERN_WARN			       "message from invalid partition. "			       "int msg rcvd, source inst (%d) doesnt match (%d)\n",			       viopathStatus[remoteLp].mTargetInst,			       event->xSourceInstanceId);			return;		}		if (viopathStatus[remoteLp].isActive		    && (event->xTargetInstanceId !=			viopathStatus[remoteLp].mSourceInst)) {			printk(VIOPATH_KERN_WARN			       "message from invalid partition. "			       "int msg rcvd, target inst (%d) doesnt match (%d)\n",			       viopathStatus[remoteLp].mSourceInst,			       event->xTargetInstanceId);			return;		}	} else {		remoteLp = event->xTargetLp;		if (event->xSourceInstanceId !=		    viopathStatus[remoteLp].mSourceInst) {			printk(VIOPATH_KERN_WARN			       "message from invalid partition. "			       "ack msg rcvd, source inst (%d) doesnt match (%d)\n",			       viopathStatus[remoteLp].mSourceInst,			       event->xSourceInstanceId);			return;		}		if (event->xTargetInstanceId !=		    viopathStatus[remoteLp].mTargetInst) {			printk(VIOPATH_KERN_WARN			       "message from invalid partition. "			       "viopath: ack msg rcvd, target inst (%d) doesnt match (%d)\n",			       viopathStatus[remoteLp].mTargetInst,			       event->xTargetInstanceId);			return;		}	}	if (vio_handler[subtype] == NULL) {		printk(VIOPATH_KERN_WARN		       "unexpected virtual io event subtype %d from partition %d\n",		       event->xSubtype, remoteLp);		/* No handler.  Ack if necessary */		if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) {			event->xRc = HvLpEvent_Rc_InvalidSubtype;			HvCallEvent_ackLpEvent(event);		}		return;	}	/* This innocuous little line is where all the real work happens */	(*vio_handler[subtype])(event);}static void viopath_donealloc(void *parm, int number){	struct alloc_parms *parmsp = parm;	parmsp->number = number;	if (parmsp->used_wait_atomic)		atomic_set(&parmsp->wait_atomic, 0);	else		complete(&parmsp->done);}static int allocateEvents(HvLpIndex remoteLp, int numEvents){	struct alloc_parms parms;	if (system_state != SYSTEM_RUNNING) {		parms.used_wait_atomic = 1;		atomic_set(&parms.wait_atomic, 1);	} else {		parms.used_wait_atomic = 0;		init_completion(&parms.done);	}	mf_allocate_lp_events(remoteLp, HvLpEvent_Type_VirtualIo, 250,	/* It would be nice to put a real number here! */			    numEvents, &viopath_donealloc, &parms);	if (system_state != SYSTEM_RUNNING) {		while (atomic_read(&parms.wait_atomic))			mb();	} else		wait_for_completion(&parms.done);	return parms.number;}int viopath_open(HvLpIndex remoteLp, int subtype, int numReq){	int i;	unsigned long flags;	int tempNumAllocated;	if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid))		return -EINVAL;	subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;	if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES))		return -EINVAL;	spin_lock_irqsave(&statuslock, flags);	if (!event_buffer_initialised) {		for (i = 0; i < VIO_MAX_SUBTYPES; i++)			atomic_set(&event_buffer_available[i], 1);		event_buffer_initialised = 1;	}	viopathStatus[remoteLp].users[subtype]++;	if (!viopathStatus[remoteLp].isOpen) {		viopathStatus[remoteLp].isOpen = 1;		HvCallEvent_openLpEventPath(remoteLp, HvLpEvent_Type_VirtualIo);		/*		 * Don't hold the spinlock during an operation that		 * can sleep.		 */		spin_unlock_irqrestore(&statuslock, flags);		tempNumAllocated = allocateEvents(remoteLp, 1);		spin_lock_irqsave(&statuslock, flags);		viopathStatus[remoteLp].numberAllocated += tempNumAllocated;		if (viopathStatus[remoteLp].numberAllocated == 0) {			HvCallEvent_closeLpEventPath(remoteLp,					HvLpEvent_Type_VirtualIo);			spin_unlock_irqrestore(&statuslock, flags);			return -ENOMEM;		}		viopathStatus[remoteLp].mSourceInst =			HvCallEvent_getSourceLpInstanceId(remoteLp,					HvLpEvent_Type_VirtualIo);		viopathStatus[remoteLp].mTargetInst =			HvCallEvent_getTargetLpInstanceId(remoteLp,					HvLpEvent_Type_VirtualIo);		HvLpEvent_registerHandler(HvLpEvent_Type_VirtualIo,					  &vio_handleEvent);		sendMonMsg(remoteLp);		printk(VIOPATH_KERN_INFO "opening connection to partition %d, "				"setting sinst %d, tinst %d\n",				remoteLp, viopathStatus[remoteLp].mSourceInst,				viopathStatus[remoteLp].mTargetInst);	}	spin_unlock_irqrestore(&statuslock, flags);	tempNumAllocated = allocateEvents(remoteLp, numReq);	spin_lock_irqsave(&statuslock, flags);	viopathStatus[remoteLp].numberAllocated += tempNumAllocated;	spin_unlock_irqrestore(&statuslock, flags);	return 0;}EXPORT_SYMBOL(viopath_open);int viopath_close(HvLpIndex remoteLp, int subtype, int numReq){	unsigned long flags;	int i;	int numOpen;	struct alloc_parms parms;	if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid))		return -EINVAL;	subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;	if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES))		return -EINVAL;	spin_lock_irqsave(&statuslock, flags);	/*	 * If the viopath_close somehow gets called before a	 * viopath_open it could decrement to -1 which is a non	 * recoverable state so we'll prevent this from	 * happening.	 */	if (viopathStatus[remoteLp].users[subtype] > 0)		viopathStatus[remoteLp].users[subtype]--;	spin_unlock_irqrestore(&statuslock, flags);	parms.used_wait_atomic = 0;	init_completion(&parms.done);	mf_deallocate_lp_events(remoteLp, HvLpEvent_Type_VirtualIo,			      numReq, &viopath_donealloc, &parms);	wait_for_completion(&parms.done);	spin_lock_irqsave(&statuslock, flags);	for (i = 0, numOpen = 0; i < VIO_MAX_SUBTYPES; i++)		numOpen += viopathStatus[remoteLp].users[i];	if ((viopathStatus[remoteLp].isOpen) && (numOpen == 0)) {		printk(VIOPATH_KERN_INFO "closing connection to partition %d\n",				remoteLp);		HvCallEvent_closeLpEventPath(remoteLp,					     HvLpEvent_Type_VirtualIo);		viopathStatus[remoteLp].isOpen = 0;		viopathStatus[remoteLp].isActive = 0;		for (i = 0; i < VIO_MAX_SUBTYPES; i++)			atomic_set(&event_buffer_available[i], 0);		event_buffer_initialised = 0;	}	spin_unlock_irqrestore(&statuslock, flags);	return 0;}EXPORT_SYMBOL(viopath_close);void *vio_get_event_buffer(int subtype){	subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;	if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES))		return NULL;	if (atomic_dec_if_positive(&event_buffer_available[subtype]) == 0)		return &event_buffer[subtype * 256];	else		return NULL;}EXPORT_SYMBOL(vio_get_event_buffer);void vio_free_event_buffer(int subtype, void *buffer){	subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;	if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) {		printk(VIOPATH_KERN_WARN		       "unexpected subtype %d freeing event buffer\n", subtype);		return;	}	if (atomic_read(&event_buffer_available[subtype]) != 0) {		printk(VIOPATH_KERN_WARN		       "freeing unallocated event buffer, subtype %d\n",		       subtype);		return;	}	if (buffer != &event_buffer[subtype * 256]) {		printk(VIOPATH_KERN_WARN		       "freeing invalid event buffer, subtype %d\n", subtype);	}	atomic_set(&event_buffer_available[subtype], 1);}EXPORT_SYMBOL(vio_free_event_buffer);static const struct vio_error_entry vio_no_error =    { 0, 0, "Non-VIO Error" };static const struct vio_error_entry vio_unknown_error =    { 0, EIO, "Unknown Error" };static const struct vio_error_entry vio_default_errors[] = {	{0x0001, EIO, "No Connection"},	{0x0002, EIO, "No Receiver"},	{0x0003, EIO, "No Buffer Available"},	{0x0004, EBADRQC, "Invalid Message Type"},	{0x0000, 0, NULL},};const struct vio_error_entry *vio_lookup_rc(		const struct vio_error_entry *local_table, u16 rc){	const struct vio_error_entry *cur;	if (!rc)		return &vio_no_error;	if (local_table)		for (cur = local_table; cur->rc; ++cur)			if (cur->rc == rc)				return cur;	for (cur = vio_default_errors; cur->rc; ++cur)		if (cur->rc == rc)			return cur;	return &vio_unknown_error;}EXPORT_SYMBOL(vio_lookup_rc);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -