diff options
Diffstat (limited to 'drivers/hv/channel.c')
| -rw-r--r-- | drivers/hv/channel.c | 125 | 
1 files changed, 47 insertions, 78 deletions
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 6de6c98ce6e..284cf66489f 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -27,6 +27,7 @@  #include <linux/slab.h>  #include <linux/module.h>  #include <linux/hyperv.h> +#include <linux/uio.h>  #include "hyperv_vmbus.h" @@ -47,8 +48,8 @@ static void vmbus_setevent(struct vmbus_channel *channel)  			(unsigned long *) vmbus_connection.send_int_page +  			(channel->offermsg.child_relid >> 5)); -		monitorpage = vmbus_connection.monitor_pages; -		monitorpage++; /* Get the child to parent monitor page */ +		/* Get the child to parent monitor page */ +		monitorpage = vmbus_connection.monitor_pages[1];  		sync_set_bit(channel->monitor_bit,  			(unsigned long *)&monitorpage->trigger_group @@ -60,50 +61,6 @@ static void vmbus_setevent(struct vmbus_channel *channel)  }  /* - * vmbus_get_debug_info -Retrieve various channel debug info - */ -void vmbus_get_debug_info(struct vmbus_channel *channel, -			      struct vmbus_channel_debug_info *debuginfo) -{ -	struct hv_monitor_page *monitorpage; -	u8 monitor_group = (u8)channel->offermsg.monitorid / 32; -	u8 monitor_offset = (u8)channel->offermsg.monitorid % 32; - -	debuginfo->relid = channel->offermsg.child_relid; -	debuginfo->state = channel->state; -	memcpy(&debuginfo->interfacetype, -	       &channel->offermsg.offer.if_type, sizeof(uuid_le)); -	memcpy(&debuginfo->interface_instance, -	       &channel->offermsg.offer.if_instance, -	       sizeof(uuid_le)); - -	monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages; - -	debuginfo->monitorid = channel->offermsg.monitorid; - -	debuginfo->servermonitor_pending = -			monitorpage->trigger_group[monitor_group].pending; -	debuginfo->servermonitor_latency = -			monitorpage->latency[monitor_group][monitor_offset]; -	debuginfo->servermonitor_connectionid = -			monitorpage->parameter[monitor_group] -					[monitor_offset].connectionid.u.id; - -	monitorpage++; - -	debuginfo->clientmonitor_pending = -			monitorpage->trigger_group[monitor_group].pending; -	debuginfo->clientmonitor_latency = -			monitorpage->latency[monitor_group][monitor_offset]; -	debuginfo->clientmonitor_connectionid = -			monitorpage->parameter[monitor_group] -					[monitor_offset].connectionid.u.id; - -	hv_ringbuffer_get_debuginfo(&channel->inbound, &debuginfo->inbound); -	hv_ringbuffer_get_debuginfo(&channel->outbound, &debuginfo->outbound); -} - -/*   * vmbus_open - Open the specified channel.   */  int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, @@ -253,7 +210,6 @@ static int create_gpadl_header(void *kbuffer, u32 size,  {  	int i;  	int pagecount; -	unsigned long long pfn;  	struct vmbus_channel_gpadl_header *gpadl_header;  	struct vmbus_channel_gpadl_body *gpadl_body;  	struct vmbus_channel_msginfo *msgheader; @@ -263,7 +219,6 @@ static int create_gpadl_header(void *kbuffer, u32 size,  	int pfnsum, pfncount, pfnleft, pfncurr, pfnsize;  	pagecount = size >> PAGE_SHIFT; -	pfn = virt_to_phys(kbuffer) >> PAGE_SHIFT;  	/* do we need a gpadl body msg */  	pfnsize = MAX_SIZE_CHANNEL_MESSAGE - @@ -292,7 +247,8 @@ static int create_gpadl_header(void *kbuffer, u32 size,  		gpadl_header->range[0].byte_offset = 0;  		gpadl_header->range[0].byte_count = size;  		for (i = 0; i < pfncount; i++) -			gpadl_header->range[0].pfn_array[i] = pfn+i; +			gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys( +				kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT;  		*msginfo = msgheader;  		*messagecount = 1; @@ -345,7 +301,9 @@ static int create_gpadl_header(void *kbuffer, u32 size,  			 * so the hypervisor gurantees that this is ok.  			 */  			for (i = 0; i < pfncurr; i++) -				gpadl_body->pfn[i] = pfn + pfnsum + i; +				gpadl_body->pfn[i] = slow_virt_to_phys( +					kbuffer + PAGE_SIZE * (pfnsum + i)) >> +					PAGE_SHIFT;  			/* add to msg header */  			list_add_tail(&msgbody->msglistentry, @@ -371,7 +329,8 @@ static int create_gpadl_header(void *kbuffer, u32 size,  		gpadl_header->range[0].byte_offset = 0;  		gpadl_header->range[0].byte_count = size;  		for (i = 0; i < pagecount; i++) -			gpadl_header->range[0].pfn_array[i] = pfn+i; +			gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys( +				kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT;  		*msginfo = msgheader;  		*messagecount = 1; @@ -388,7 +347,7 @@ nomem:   * vmbus_establish_gpadl - Estabish a GPADL for the specified buffer   *   * @channel: a channel - * @kbuffer: from kmalloc + * @kbuffer: from kmalloc or vmalloc   * @size: page-size multiple   * @gpadl_handle: some funky thing   */ @@ -512,18 +471,26 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)  }  EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl); +static void reset_channel_cb(void *arg) +{ +	struct vmbus_channel *channel = arg; + +	channel->onchannel_callback = NULL; +} +  static void vmbus_close_internal(struct vmbus_channel *channel)  {  	struct vmbus_channel_close_channel *msg;  	int ret; -	unsigned long flags;  	channel->state = CHANNEL_OPEN_STATE;  	channel->sc_creation_callback = NULL;  	/* Stop callback and cancel the timer asap */ -	spin_lock_irqsave(&channel->inbound_lock, flags); -	channel->onchannel_callback = NULL; -	spin_unlock_irqrestore(&channel->inbound_lock, flags); +	if (channel->target_cpu != smp_processor_id()) +		smp_call_function_single(channel->target_cpu, reset_channel_cb, +					 channel, true); +	else +		reset_channel_cb(channel);  	/* Send a closing message */ @@ -596,14 +563,14 @@ EXPORT_SYMBOL_GPL(vmbus_close);   *   * Mainly used by Hyper-V drivers.   */ -int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer, +int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,  			   u32 bufferlen, u64 requestid,  			   enum vmbus_packet_type type, u32 flags)  {  	struct vmpacket_descriptor desc;  	u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;  	u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64)); -	struct scatterlist bufferlist[3]; +	struct kvec bufferlist[3];  	u64 aligned_data = 0;  	int ret;  	bool signal = false; @@ -617,11 +584,12 @@ int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer,  	desc.len8 = (u16)(packetlen_aligned >> 3);  	desc.trans_id = requestid; -	sg_init_table(bufferlist, 3); -	sg_set_buf(&bufferlist[0], &desc, sizeof(struct vmpacket_descriptor)); -	sg_set_buf(&bufferlist[1], buffer, bufferlen); -	sg_set_buf(&bufferlist[2], &aligned_data, -		   packetlen_aligned - packetlen); +	bufferlist[0].iov_base = &desc; +	bufferlist[0].iov_len = sizeof(struct vmpacket_descriptor); +	bufferlist[1].iov_base = buffer; +	bufferlist[1].iov_len = bufferlen; +	bufferlist[2].iov_base = &aligned_data; +	bufferlist[2].iov_len = (packetlen_aligned - packetlen);  	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal); @@ -647,7 +615,7 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,  	u32 descsize;  	u32 packetlen;  	u32 packetlen_aligned; -	struct scatterlist bufferlist[3]; +	struct kvec bufferlist[3];  	u64 aligned_data = 0;  	bool signal = false; @@ -679,11 +647,12 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,  		desc.range[i].pfn	 = pagebuffers[i].pfn;  	} -	sg_init_table(bufferlist, 3); -	sg_set_buf(&bufferlist[0], &desc, descsize); -	sg_set_buf(&bufferlist[1], buffer, bufferlen); -	sg_set_buf(&bufferlist[2], &aligned_data, -		packetlen_aligned - packetlen); +	bufferlist[0].iov_base = &desc; +	bufferlist[0].iov_len = descsize; +	bufferlist[1].iov_base = buffer; +	bufferlist[1].iov_len = bufferlen; +	bufferlist[2].iov_base = &aligned_data; +	bufferlist[2].iov_len = (packetlen_aligned - packetlen);  	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal); @@ -707,14 +676,13 @@ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,  	u32 descsize;  	u32 packetlen;  	u32 packetlen_aligned; -	struct scatterlist bufferlist[3]; +	struct kvec bufferlist[3];  	u64 aligned_data = 0;  	bool signal = false;  	u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,  					 multi_pagebuffer->len); - -	if ((pfncount < 0) || (pfncount > MAX_MULTIPAGE_BUFFER_COUNT)) +	if (pfncount > MAX_MULTIPAGE_BUFFER_COUNT)  		return -EINVAL;  	/* @@ -742,11 +710,12 @@ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,  	memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array,  	       pfncount * sizeof(u64)); -	sg_init_table(bufferlist, 3); -	sg_set_buf(&bufferlist[0], &desc, descsize); -	sg_set_buf(&bufferlist[1], buffer, bufferlen); -	sg_set_buf(&bufferlist[2], &aligned_data, -		packetlen_aligned - packetlen); +	bufferlist[0].iov_base = &desc; +	bufferlist[0].iov_len = descsize; +	bufferlist[1].iov_base = buffer; +	bufferlist[1].iov_len = bufferlen; +	bufferlist[2].iov_base = &aligned_data; +	bufferlist[2].iov_len = (packetlen_aligned - packetlen);  	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal); @@ -855,6 +824,6 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,  	if (signal)  		vmbus_setevent(channel); -	return 0; +	return ret;  }  EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);  | 
