/*++

Name:	netvsc_drv_init()

Desc:	NetVsc driver initialization

--*/
int netvsc_drv_init(PFN_DRIVERINITIALIZE pfn_drv_init)
{
	int ret = 0;
	NETVSC_DRIVER_OBJECT *net_drv_obj=&g_netvsc_drv.drv_obj;
	struct driver_context *drv_ctx=&g_netvsc_drv.drv_ctx;

	DPRINT_ENTER(NETVSC_DRV);

	vmbus_get_interface(&net_drv_obj->Base.VmbusChannelInterface);

	net_drv_obj->RingBufferSize = netvsc_ringbuffer_size;
	/* Fixme:  warning: assignment from incompatible pointer type */
	net_drv_obj->OnReceiveCallback = netvsc_recv_callback;
	net_drv_obj->OnLinkStatusChanged = netvsc_linkstatus_callback;

	// Callback to client driver to complete the initialization
	pfn_drv_init(&net_drv_obj->Base);

	memcpy(&drv_ctx->class_id, &net_drv_obj->Base.deviceType, sizeof(GUID));

	// The driver belongs to vmbus
	vmbus_child_driver_register(drv_ctx);

	DPRINT_EXIT(NETVSC_DRV);

	return ret;
}
예제 #2
0
static int BlkVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo)
{
	struct storvsc_device_info *deviceInfo;
	int ret = 0;

	DPRINT_ENTER(BLKVSC);

	deviceInfo = (struct storvsc_device_info *)AdditionalInfo;

	ret = StorVscOnDeviceAdd(Device, AdditionalInfo);
	if (ret != 0) {
		DPRINT_EXIT(BLKVSC);
		return ret;
	}

	/*
	 * We need to use the device instance guid to set the path and target
	 * id. For IDE devices, the device instance id is formatted as
	 * <bus id> * - <device id> - 8899 - 000000000000.
	 */
	deviceInfo->PathId = Device->deviceInstance.data[3] << 24 |
			     Device->deviceInstance.data[2] << 16 |
			     Device->deviceInstance.data[1] << 8  |
			     Device->deviceInstance.data[0];

	deviceInfo->TargetId = Device->deviceInstance.data[5] << 8 |
			       Device->deviceInstance.data[4];

	DPRINT_EXIT(BLKVSC);

	return ret;
}
예제 #3
0
static int NetVscDestroyReceiveBuffer(struct netvsc_device *NetDevice)
{
	struct nvsp_message *revokePacket;
	int ret = 0;

	DPRINT_ENTER(NETVSC);

	
	if (NetDevice->ReceiveSectionCount) {
		DPRINT_INFO(NETVSC,
			    "Sending NvspMessage1TypeRevokeReceiveBuffer...");

		
		revokePacket = &NetDevice->RevokePacket;
		memset(revokePacket, 0, sizeof(struct nvsp_message));

		revokePacket->Header.MessageType = NvspMessage1TypeRevokeReceiveBuffer;
		revokePacket->Messages.Version1Messages.RevokeReceiveBuffer.Id = NETVSC_RECEIVE_BUFFER_ID;

		ret = NetDevice->Device->Driver->VmbusChannelInterface.SendPacket(
						NetDevice->Device,
						revokePacket,
						sizeof(struct nvsp_message),
						(unsigned long)revokePacket,
						VmbusPacketTypeDataInBand, 0);
		
		if (ret != 0) {
			DPRINT_ERR(NETVSC, "unable to send revoke receive "
				   "buffer to netvsp");
			DPRINT_EXIT(NETVSC);
			return -1;
		}
	}

	
	if (NetDevice->ReceiveBufferGpadlHandle) {
		DPRINT_INFO(NETVSC, "Tearing down receive buffer's GPADL...");

		ret = NetDevice->Device->Driver->VmbusChannelInterface.TeardownGpadl(
					NetDevice->Device,
					NetDevice->ReceiveBufferGpadlHandle);

		
		if (ret != 0) {
			DPRINT_ERR(NETVSC,
				   "unable to teardown receive buffer's gpadl");
			DPRINT_EXIT(NETVSC);
			return -1;
		}
		NetDevice->ReceiveBufferGpadlHandle = 0;
	}

	if (NetDevice->ReceiveBuffer) {
		DPRINT_INFO(NETVSC, "Freeing up receive buffer...");

		
		osd_PageFree(NetDevice->ReceiveBuffer,
			     NetDevice->ReceiveBufferSize >> PAGE_SHIFT);
		NetDevice->ReceiveBuffer = NULL;
	}
예제 #4
0
static int VmbusOnDeviceAdd(struct hv_device *dev, void *AdditionalInfo)
{
	u32 *irqvector = AdditionalInfo;
	int ret;

	DPRINT_ENTER(VMBUS);

	gDevice = dev;

	memcpy(&gDevice->deviceType, &gVmbusDeviceType, sizeof(struct hv_guid));
	memcpy(&gDevice->deviceInstance, &gVmbusDeviceId,
	       sizeof(struct hv_guid));

	/* strcpy(dev->name, "vmbus"); */
	/* SynIC setup... */
	on_each_cpu(HvSynicInit, (void *)irqvector, 1);

	/* Connect to VMBus in the root partition */
	ret = VmbusConnect();

	/* VmbusSendEvent(device->localPortId+1); */
	DPRINT_EXIT(VMBUS);

	return ret;
}
예제 #5
0
static int netvsc_drv_init(int (*drv_init)(struct hv_driver *drv))
{
	struct netvsc_driver *net_drv_obj = &g_netvsc_drv.drv_obj;
	struct driver_context *drv_ctx = &g_netvsc_drv.drv_ctx;
	int ret;

	DPRINT_ENTER(NETVSC_DRV);

	vmbus_get_interface(&net_drv_obj->Base.VmbusChannelInterface);

	net_drv_obj->RingBufferSize = ring_size * PAGE_SIZE;
	net_drv_obj->OnReceiveCallback = netvsc_recv_callback;
	net_drv_obj->OnLinkStatusChanged = netvsc_linkstatus_callback;

	/* Callback to client driver to complete the initialization */
	drv_init(&net_drv_obj->Base);

	drv_ctx->driver.name = net_drv_obj->Base.name;
	memcpy(&drv_ctx->class_id, &net_drv_obj->Base.deviceType,
	       sizeof(struct hv_guid));

	drv_ctx->probe = netvsc_probe;
	drv_ctx->remove = netvsc_remove;

	/* The driver belongs to vmbus */
	ret = vmbus_child_driver_register(drv_ctx);

	DPRINT_EXIT(NETVSC_DRV);

	return ret;
}
예제 #6
0
static int VmbusOnISR(struct hv_driver *drv)
{
	int ret = 0;
	int cpu = smp_processor_id();
	void *page_addr;
	struct hv_message *msg;
	union hv_synic_event_flags *event;

	page_addr = gHvContext.synICMessagePage[cpu];
	msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;

	DPRINT_ENTER(VMBUS);

	/* Check if there are actual msgs to be process */
	if (msg->Header.MessageType != HvMessageTypeNone) {
		DPRINT_DBG(VMBUS, "received msg type %d size %d",
				msg->Header.MessageType,
				msg->Header.PayloadSize);
		ret |= 0x1;
	}

	/* TODO: Check if there are events to be process */
	page_addr = gHvContext.synICEventPage[cpu];
	event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;

	/* Since we are a child, we only need to check bit 0 */
	if (test_and_clear_bit(0, (unsigned long *) &event->Flags32[0])) {
		DPRINT_DBG(VMBUS, "received event %d", event->Flags32[0]);
		ret |= 0x2;
	}

	DPRINT_EXIT(VMBUS);
	return ret;
}
/*
 * netvsc_linkstatus_callback - Link up/down notification
 */
static void netvsc_linkstatus_callback(struct hv_device *device_obj,
				       unsigned int status)
{
	struct vm_device *device_ctx = to_vm_device(device_obj);
	struct net_device *net = dev_get_drvdata(&device_ctx->device);
	struct net_device_context *ndev_ctx;

	DPRINT_ENTER(NETVSC_DRV);

	if (!net) {
		DPRINT_ERR(NETVSC_DRV, "got link status but net device "
				"not initialized yet");
		return;
	}

	if (status == 1) {
		netif_carrier_on(net);
		netif_wake_queue(net);
		netif_notify_peers(net);
		ndev_ctx = netdev_priv(net);
		schedule_work(&ndev_ctx->work);
	} else {
		netif_carrier_off(net);
		netif_stop_queue(net);
	}
	DPRINT_EXIT(NETVSC_DRV);
}
예제 #8
0
static int netvsc_open(struct net_device *net)
{
	struct net_device_context *net_device_ctx = netdev_priv(net);
	struct driver_context *driver_ctx =
	    driver_to_driver_context(net_device_ctx->device_ctx->device.driver);
	struct netvsc_driver_context *net_drv_ctx =
		(struct netvsc_driver_context *)driver_ctx;
	struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
	struct hv_device *device_obj = &net_device_ctx->device_ctx->device_obj;
	int ret = 0;

	DPRINT_ENTER(NETVSC_DRV);

	if (netif_carrier_ok(net)) {
		memset(&net_device_ctx->stats, 0,
		       sizeof(struct net_device_stats));

		/* Open up the device */
		ret = net_drv_obj->OnOpen(device_obj);
		if (ret != 0) {
			DPRINT_ERR(NETVSC_DRV,
				   "unable to open device (ret %d).", ret);
			return ret;
		}

		netif_start_queue(net);
	} else {
		DPRINT_ERR(NETVSC_DRV, "unable to open device...link is down.");
	}

	DPRINT_EXIT(NETVSC_DRV);
	return ret;
}
예제 #9
0
static int netvsc_open(struct net_device *net)
{
	struct net_device_context *net_device_ctx = netdev_priv(net);
	struct hv_device *device_obj = &net_device_ctx->device_ctx->device_obj;
	int ret = 0;

	DPRINT_ENTER(NETVSC_DRV);

	if (netif_carrier_ok(net)) {
		/* Open up the device */
		ret = RndisFilterOnOpen(device_obj);
		if (ret != 0) {
			DPRINT_ERR(NETVSC_DRV,
				   "unable to open device (ret %d).", ret);
			return ret;
		}

		netif_start_queue(net);
	} else {
		DPRINT_ERR(NETVSC_DRV, "unable to open device...link is down.");
	}

	DPRINT_EXIT(NETVSC_DRV);
	return ret;
}
예제 #10
0
static void netvsc_xmit_completion(void *context)
{
	struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context;
	struct sk_buff *skb = (struct sk_buff *)
		(unsigned long)packet->Completion.Send.SendCompletionTid;
	struct net_device *net;

	DPRINT_ENTER(NETVSC_DRV);

	kfree(packet);

	if (skb) {
		net = skb->dev;
		dev_kfree_skb_any(skb);

		if (netif_queue_stopped(net)) {
			DPRINT_INFO(NETVSC_DRV, "net device (%p) waking up...",
				    net);

			netif_wake_queue(net);
		}
	}

	DPRINT_EXIT(NETVSC_DRV);
}
예제 #11
0
int RingBufferWrite(RING_BUFFER_INFO *OutRingInfo,
		    struct scatterlist *sglist, u32 sgcount)
{
	int i = 0;
	u32 byteAvailToWrite;
	u32 byteAvailToRead;
	u32 totalBytesToWrite = 0;

	struct scatterlist *sg;
	volatile u32 nextWriteLocation;
	u64 prevIndices = 0;
	unsigned long flags;

	DPRINT_ENTER(VMBUS);

	for_each_sg(sglist, sg, sgcount, i)
	{
		totalBytesToWrite += sg->length;
	}

	totalBytesToWrite += sizeof(u64);

	spin_lock_irqsave(&OutRingInfo->ring_lock, flags);

	GetRingBufferAvailBytes(OutRingInfo,
				&byteAvailToRead,
				&byteAvailToWrite);

	DPRINT_DBG(VMBUS, "Writing %u bytes...", totalBytesToWrite);

	/* DumpRingInfo(OutRingInfo, "BEFORE "); */

	/* If there is only room for the packet, assume it is full. */
	/* Otherwise, the next time around, we think the ring buffer */
	/* is empty since the read index == write index */
	if (byteAvailToWrite <= totalBytesToWrite) {
		DPRINT_DBG(VMBUS,
			"No more space left on outbound ring buffer "
			"(needed %u, avail %u)",
			totalBytesToWrite,
			byteAvailToWrite);

		spin_unlock_irqrestore(&OutRingInfo->ring_lock, flags);

		DPRINT_EXIT(VMBUS);

		return -1;
	}

	/* Write to the ring buffer */
	nextWriteLocation = GetNextWriteLocation(OutRingInfo);

	for_each_sg(sglist, sg, sgcount, i)
	{
		nextWriteLocation = CopyToRingBuffer(OutRingInfo,
						     nextWriteLocation,
						     sg_virt(sg),
						     sg->length);
	}
예제 #12
0
static void VmbusOnCleanup(struct hv_driver *drv)
{
	/* struct vmbus_driver *driver = (struct vmbus_driver *)drv; */

	DPRINT_ENTER(VMBUS);
	HvCleanup();
	DPRINT_EXIT(VMBUS);
}
static void netvsc_init(void)
{
	DPRINT_ENTER(NETVSC_DRV);
	printf("Netvsc initializing....");

	netvsc_drv_init(NetVscInitialize);

	DPRINT_EXIT(NETVSC_DRV);
}
예제 #14
0
static int VmbusOnDeviceRemove(struct hv_device *dev)
{
	int ret = 0;

	DPRINT_ENTER(VMBUS);
	VmbusChannelReleaseUnattachedChannels();
	VmbusDisconnect();
	on_each_cpu(HvSynicCleanup, NULL, 1);
	DPRINT_EXIT(VMBUS);

	return ret;
}
예제 #15
0
int RingBufferWrite(RING_BUFFER_INFO *OutRingInfo,
		    struct scatterlist *sglist, u32 sgcount)
{
	int i=0;
	u32 byteAvailToWrite;
	u32 byteAvailToRead;
	u32 totalBytesToWrite=0;

	struct scatterlist *sg;
	volatile u32 nextWriteLocation;
	u64 prevIndices=0;
	unsigned long flags;

	DPRINT_ENTER(VMBUS);

	for_each_sg(sglist, sg, sgcount, i)
	{
		totalBytesToWrite += sg->length;
	}

	totalBytesToWrite += sizeof(u64);

	spin_lock_irqsave(&OutRingInfo->ring_lock, flags);

	GetRingBufferAvailBytes(OutRingInfo, &byteAvailToRead, &byteAvailToWrite);

	DPRINT_DBG(VMBUS, "Writing %u bytes...", totalBytesToWrite);

	

	
	
	if (byteAvailToWrite <= totalBytesToWrite)
	{
		DPRINT_DBG(VMBUS, "No more space left on outbound ring buffer (needed %u, avail %u)", totalBytesToWrite, byteAvailToWrite);

		spin_unlock_irqrestore(&OutRingInfo->ring_lock, flags);

		DPRINT_EXIT(VMBUS);

		return -1;
	}

	
	nextWriteLocation = GetNextWriteLocation(OutRingInfo);

	for_each_sg(sglist, sg, sgcount, i)
	{
		nextWriteLocation = CopyToRingBuffer(OutRingInfo,
						     nextWriteLocation,
						     sg_virt(sg),
						     sg->length);
	}
예제 #16
0
static int __init netvsc_init(void)
{
	int ret;

	DPRINT_ENTER(NETVSC_DRV);
	DPRINT_INFO(NETVSC_DRV, "Netvsc initializing....");

	ret = netvsc_drv_init(NetVscInitialize);

	DPRINT_EXIT(NETVSC_DRV);

	return ret;
}
예제 #17
0
/*
 * Heartbeat functionality.
 * Every two seconds, Hyper-V send us a heartbeat request message.
 * we respond to this message, and Hyper-V knows we are alive.
 */
static void heartbeat_onchannelcallback(void *context)
{
	struct vmbus_channel *channel = context;
	u8 *buf;
	u32 buflen, recvlen;
	u64 requestid;
	struct icmsg_hdr *icmsghdrp;
	struct heartbeat_msg_data *heartbeat_msg;

	DPRINT_ENTER(VMBUS);

	buflen = PAGE_SIZE;
	buf = kmalloc(buflen, GFP_ATOMIC);

	VmbusChannelRecvPacket(channel, buf, buflen, &recvlen, &requestid);

	if (recvlen > 0) {
		DPRINT_DBG(VMBUS, "heartbeat packet: len=%d, requestid=%lld",
			   recvlen, requestid);

		icmsghdrp = (struct icmsg_hdr *)&buf[
			sizeof(struct vmbuspipe_hdr)];

		icmsghdrp = (struct icmsg_hdr *)&buf[
				sizeof(struct vmbuspipe_hdr)];

		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
			prep_negotiate_resp(icmsghdrp, NULL, buf);
		} else {
			heartbeat_msg = (struct heartbeat_msg_data *)&buf[
				sizeof(struct vmbuspipe_hdr) +
				sizeof(struct icmsg_hdr)];

			DPRINT_DBG(VMBUS, "heartbeat seq = %lld",
				   heartbeat_msg->seq_num);

			heartbeat_msg->seq_num += 1;
		}

		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
			| ICMSGHDRFLAG_RESPONSE;

		VmbusChannelSendPacket(channel, buf,
				       recvlen, requestid,
				       VmbusPacketTypeDataInBand, 0);
	}

	kfree(buf);

	DPRINT_EXIT(VMBUS);
}
예제 #18
0
static int __init netvsc_init(void)
{
	int ret;

	DPRINT_ENTER(NETVSC_DRV);
	DPRINT_INFO(NETVSC_DRV, "Netvsc initializing....");

	if (!dmi_check_system(hv_netvsc_dmi_table))
		return -ENODEV;

	ret = netvsc_drv_init(NetVscInitialize);

	DPRINT_EXIT(NETVSC_DRV);

	return ret;
}
예제 #19
0
/**
 * VmbusInitialize - Main entry point
 */
int VmbusInitialize(struct hv_driver *drv)
{
	struct vmbus_driver *driver = (struct vmbus_driver *)drv;
	int ret;

	DPRINT_ENTER(VMBUS);

	DPRINT_INFO(VMBUS, "+++++++ Build Date=%s %s +++++++",
			VersionDate, VersionTime);
	DPRINT_INFO(VMBUS, "+++++++ Build Description=%s +++++++",
			VersionDesc);
	DPRINT_INFO(VMBUS, "+++++++ Vmbus supported version = %d +++++++",
			VMBUS_REVISION_NUMBER);
	DPRINT_INFO(VMBUS, "+++++++ Vmbus using SINT %d +++++++",
			VMBUS_MESSAGE_SINT);
	DPRINT_DBG(VMBUS, "sizeof(VMBUS_CHANNEL_PACKET_PAGE_BUFFER)=%zd, "
			"sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER)=%zd",
			sizeof(struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER),
			sizeof(struct VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER));

	drv->name = gDriverName;
	memcpy(&drv->deviceType, &gVmbusDeviceType, sizeof(struct hv_guid));

	/* Setup dispatch table */
	driver->Base.OnDeviceAdd	= VmbusOnDeviceAdd;
	driver->Base.OnDeviceRemove	= VmbusOnDeviceRemove;
	driver->Base.OnCleanup		= VmbusOnCleanup;
	driver->OnIsr			= VmbusOnISR;
	driver->OnMsgDpc		= VmbusOnMsgDPC;
	driver->OnEventDpc		= VmbusOnEventDPC;
	driver->GetChannelOffers	= VmbusGetChannelOffers;
	driver->GetChannelInterface	= VmbusGetChannelInterface;
	driver->GetChannelInfo		= VmbusGetChannelInfo;

	/* Hypervisor initialization...setup hypercall page..etc */
	ret = HvInit();
	if (ret != 0)
		DPRINT_ERR(VMBUS, "Unable to initialize the hypervisor - 0x%x",
				ret);
	gDriver = drv;

	DPRINT_EXIT(VMBUS);

	return ret;
}
예제 #20
0
static int netvsc_remove(struct device *device)
{
	struct driver_context *driver_ctx =
		driver_to_driver_context(device->driver);
	struct netvsc_driver_context *net_drv_ctx =
		(struct netvsc_driver_context *)driver_ctx;
	struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
	struct vm_device *device_ctx = device_to_vm_device(device);
	struct net_device *net = dev_get_drvdata(&device_ctx->device);
	struct hv_device *device_obj = &device_ctx->device_obj;
	int ret;

	DPRINT_ENTER(NETVSC_DRV);

	if (net == NULL) {
		DPRINT_INFO(NETVSC, "no net device to remove");
		DPRINT_EXIT(NETVSC_DRV);
		return 0;
	}

	if (!net_drv_obj->Base.OnDeviceRemove) {
		DPRINT_EXIT(NETVSC_DRV);
		return -1;
	}

	/* Stop outbound asap */
	netif_stop_queue(net);
	/* netif_carrier_off(net); */

	unregister_netdev(net);

	/*
	 * Call to the vsc driver to let it know that the device is being
	 * removed
	 */
	ret = net_drv_obj->Base.OnDeviceRemove(device_obj);
	if (ret != 0) {
		/* TODO: */
		DPRINT_ERR(NETVSC, "unable to remove vsc device (ret %d)", ret);
	}

	free_netdev(net);
	DPRINT_EXIT(NETVSC_DRV);
	return ret;
}
예제 #21
0
static int netvsc_close(struct net_device *net)
{
	struct net_device_context *net_device_ctx = netdev_priv(net);
	struct hv_device *device_obj = &net_device_ctx->device_ctx->device_obj;
	int ret;

	DPRINT_ENTER(NETVSC_DRV);

	netif_stop_queue(net);

	ret = RndisFilterOnClose(device_obj);
	if (ret != 0)
		DPRINT_ERR(NETVSC_DRV, "unable to close device (ret %d).", ret);

	DPRINT_EXIT(NETVSC_DRV);

	return ret;
}
예제 #22
0
/*
 * Time Sync Channel message handler.
 */
static void timesync_onchannelcallback(void *context)
{
	struct vmbus_channel *channel = context;
	u8 *buf;
	u32 buflen, recvlen;
	u64 requestid;
	struct icmsg_hdr *icmsghdrp;
	struct ictimesync_data *timedatap;

	DPRINT_ENTER(VMBUS);

	buflen = PAGE_SIZE;
	buf = kmalloc(buflen, GFP_ATOMIC);

	VmbusChannelRecvPacket(channel, buf, buflen, &recvlen, &requestid);

	if (recvlen > 0) {
		DPRINT_DBG(VMBUS, "timesync packet: recvlen=%d, requestid=%lld",
			recvlen, requestid);

		icmsghdrp = (struct icmsg_hdr *)&buf[
				sizeof(struct vmbuspipe_hdr)];

		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
			prep_negotiate_resp(icmsghdrp, NULL, buf);
		} else {
			timedatap = (struct ictimesync_data *)&buf[
				sizeof(struct vmbuspipe_hdr) +
				sizeof(struct icmsg_hdr)];
			adj_guesttime(timedatap->parenttime, timedatap->flags);
		}

		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
			| ICMSGHDRFLAG_RESPONSE;

		VmbusChannelSendPacket(channel, buf,
				recvlen, requestid,
				VmbusPacketTypeDataInBand, 0);
	}

	kfree(buf);

	DPRINT_EXIT(VMBUS);
}
예제 #23
0
int BlkVscInitialize(struct hv_driver *Driver)
{
	struct storvsc_driver_object *storDriver;
	int ret = 0;

	DPRINT_ENTER(BLKVSC);

	storDriver = (struct storvsc_driver_object *)Driver;

	/* Make sure we are at least 2 pages since 1 page is used for control */
	ASSERT(storDriver->RingBufferSize >= (PAGE_SIZE << 1));

	Driver->name = gBlkDriverName;
	memcpy(&Driver->deviceType, &gBlkVscDeviceType, sizeof(struct hv_guid));

	storDriver->RequestExtSize = sizeof(struct storvsc_request_extension);

	/*
	 * Divide the ring buffer data size (which is 1 page less than the ring
	 * buffer size since that page is reserved for the ring buffer indices)
	 * by the max request size (which is
	 * VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER + struct vstor_packet + u64)
	 */
	storDriver->MaxOutstandingRequestsPerChannel =
		((storDriver->RingBufferSize - PAGE_SIZE) /
		  ALIGN_UP(MAX_MULTIPAGE_BUFFER_PACKET +
			   sizeof(struct vstor_packet) + sizeof(u64),
			   sizeof(u64)));

	DPRINT_INFO(BLKVSC, "max io outstd %u",
		    storDriver->MaxOutstandingRequestsPerChannel);

	/* Setup the dispatch table */
	storDriver->Base.OnDeviceAdd = BlkVscOnDeviceAdd;
	storDriver->Base.OnDeviceRemove = StorVscOnDeviceRemove;
	storDriver->Base.OnCleanup = StorVscOnCleanup;
	storDriver->OnIORequest	= StorVscOnIORequest;

	DPRINT_EXIT(BLKVSC);

	return ret;
}
예제 #24
0
/**
 * VmbusChannelSetEvent - Trigger an event notification on the specified channel.
 */
static void VmbusChannelSetEvent(struct vmbus_channel *Channel)
{
	struct hv_monitor_page *monitorPage;

	DPRINT_ENTER(VMBUS);

	if (Channel->OfferMsg.MonitorAllocated) {
		/* Each u32 represents 32 channels */
		set_bit(Channel->OfferMsg.ChildRelId & 31,
			(unsigned long *) gVmbusConnection.SendInterruptPage +
			(Channel->OfferMsg.ChildRelId >> 5));

		monitorPage = gVmbusConnection.MonitorPages;
		monitorPage++; /* Get the child to parent monitor page */

		set_bit(Channel->MonitorBit,
			(unsigned long *)&monitorPage->TriggerGroup
					[Channel->MonitorGroup].Pending);

	} else {
void netvsc_xmit_completion(void *context)
{
	NETVSC_PACKET *packet = (NETVSC_PACKET *)context;
	struct mbuf *m;
	unsigned char *buf;
	void *sc;

	DPRINT_ENTER(NETVSC_DRV);

	m = (struct mbuf *)(ULONG_PTR)packet->Completion.Send.SendCompletionTid;
	buf = ((unsigned char *)packet) - 16;
	sc = (void  *)(*(vm_offset_t *)buf);

	free(buf, M_DEVBUF);

	if (m) {
		m_freem(m);
	}

	DPRINT_EXIT(NETVSC_DRV);
}
예제 #26
0
static void netvsc_drv_exit(void)
{
	struct netvsc_driver *netvsc_drv_obj = &g_netvsc_drv.drv_obj;
	struct driver_context *drv_ctx = &g_netvsc_drv.drv_ctx;
	struct device *current_dev;
	int ret;

	DPRINT_ENTER(NETVSC_DRV);

	while (1) {
		current_dev = NULL;

		/* Get the device */
		ret = driver_for_each_device(&drv_ctx->driver, NULL,
					     &current_dev, netvsc_drv_exit_cb);
		if (ret)
			DPRINT_WARN(NETVSC_DRV,
				    "driver_for_each_device returned %d", ret);

		if (current_dev == NULL)
			break;

		/* Initiate removal from the top-down */
		DPRINT_INFO(NETVSC_DRV, "unregistering device (%p)...",
			    current_dev);

		device_unregister(current_dev);
	}

	if (netvsc_drv_obj->Base.OnCleanup)
		netvsc_drv_obj->Base.OnCleanup(&netvsc_drv_obj->Base);

	vmbus_child_driver_unregister(drv_ctx);

	DPRINT_EXIT(NETVSC_DRV);

	return;
}
예제 #27
0
static int netvsc_close(struct net_device *net)
{
	struct net_device_context *net_device_ctx = netdev_priv(net);
	struct driver_context *driver_ctx =
	    driver_to_driver_context(net_device_ctx->device_ctx->device.driver);
	struct netvsc_driver_context *net_drv_ctx =
		(struct netvsc_driver_context *)driver_ctx;
	struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
	struct hv_device *device_obj = &net_device_ctx->device_ctx->device_obj;
	int ret;

	DPRINT_ENTER(NETVSC_DRV);

	netif_stop_queue(net);

	ret = net_drv_obj->OnClose(device_obj);
	if (ret != 0)
		DPRINT_ERR(NETVSC_DRV, "unable to close device (ret %d).", ret);

	DPRINT_EXIT(NETVSC_DRV);

	return ret;
}
예제 #28
0
static void netvsc_xmit_completion(void *context)
{
	struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context;
	struct sk_buff *skb = (struct sk_buff *)
		(unsigned long)packet->Completion.Send.SendCompletionTid;

	DPRINT_ENTER(NETVSC_DRV);

	kfree(packet);

	if (skb) {
		struct net_device *net = skb->dev;
		struct net_device_context *net_device_ctx = netdev_priv(net);
		unsigned int num_pages = skb_shinfo(skb)->nr_frags + 2;

		dev_kfree_skb_any(skb);

		if ((net_device_ctx->avail += num_pages) >= PACKET_PAGES_HIWATER)
 			netif_wake_queue(net);
	}

	DPRINT_EXIT(NETVSC_DRV);
}
예제 #29
0
/**
 * NetVscInitialize - Main entry point
 */
int NetVscInitialize(struct hv_driver *drv)
{
	struct netvsc_driver *driver = (struct netvsc_driver *)drv;

	DPRINT_ENTER(NETVSC);

	DPRINT_DBG(NETVSC, "sizeof(struct hv_netvsc_packet)=%zd, "
		   "sizeof(struct nvsp_message)=%zd, "
		   "sizeof(struct vmtransfer_page_packet_header)=%zd",
		   sizeof(struct hv_netvsc_packet),
		   sizeof(struct nvsp_message),
		   sizeof(struct vmtransfer_page_packet_header));

	/* Make sure we are at least 2 pages since 1 page is used for control */
	ASSERT(driver->RingBufferSize >= (PAGE_SIZE << 1));

	drv->name = gDriverName;
	memcpy(&drv->deviceType, &gNetVscDeviceType, sizeof(struct hv_guid));

	/* Make sure it is set by the caller */
	ASSERT(driver->OnReceiveCallback);
	ASSERT(driver->OnLinkStatusChanged);

	/* Setup the dispatch table */
	driver->Base.OnDeviceAdd	= NetVscOnDeviceAdd;
	driver->Base.OnDeviceRemove	= NetVscOnDeviceRemove;
	driver->Base.OnCleanup		= NetVscOnCleanup;

	driver->OnSend			= NetVscOnSend;

	RndisFilterInit(driver);

	DPRINT_EXIT(NETVSC);

	return 0;
}
예제 #30
0
int NetVscInitialize(struct hv_driver *drv)
{
	struct netvsc_driver *driver = (struct netvsc_driver *)drv;

	DPRINT_ENTER(NETVSC);

	DPRINT_DBG(NETVSC, "sizeof(struct hv_netvsc_packet)=%zd, "
		   "sizeof(struct nvsp_message)=%zd, "
		   "sizeof(struct vmtransfer_page_packet_header)=%zd",
		   sizeof(struct hv_netvsc_packet),
		   sizeof(struct nvsp_message),
		   sizeof(struct vmtransfer_page_packet_header));

	
	ASSERT(driver->RingBufferSize >= (PAGE_SIZE << 1));

	drv->name = gDriverName;
	memcpy(&drv->deviceType, &gNetVscDeviceType, sizeof(struct hv_guid));

	
	ASSERT(driver->OnReceiveCallback);
	ASSERT(driver->OnLinkStatusChanged);

	
	driver->Base.OnDeviceAdd	= NetVscOnDeviceAdd;
	driver->Base.OnDeviceRemove	= NetVscOnDeviceRemove;
	driver->Base.OnCleanup		= NetVscOnCleanup;

	driver->OnSend			= NetVscOnSend;

	RndisFilterInit(driver);

	DPRINT_EXIT(NETVSC);

	return 0;
}