Drivers: hv: vmbus: Support a vmbus API for efficiently sending page arrays
PATCH 1/1 Drivers: hv: vmbus: Support a vmbus API for efficiently sending page arrays
Currently, the API for sending a multi-page buffer over VMBUS is limited to a maximum pfn array of MAX_MULTIPAGE_BUFFER_COUNT. This limitation is not imposed by the host and unnecessarily limits the maximum payload that can be sent. Implement an API that does not have this restriction.
--- drivers/hv/channel.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/hyperv.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 0 deletions(-)
drivers/hv/channel.c +44 -0
@@ -686,6 +686,50 @@ EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);/* * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet * using a GPADL Direct packet type. +* The buffer includes the vmbus descriptor. +*/ +int vmbus_sendpacket_mpb_desc (struct vmbus_channel *channel, +struct vmbus_packet_mpb_array *desc, +u32 desc_size, +void *buffer,u32 bufferlen,u64 requestid) +{ +int ret; +u32 packetlen; +u32 packetlen_aligned; +struct kvec bufferlist[3 ]; +u64 aligned_data =0 ; +bool signal = false; + + packetlen = desc_size + bufferlen; + packetlen_aligned =ALIGN (packetlen,sizeof (u64)); + +/* Setup the descriptor */ + desc->type =VM_PKT_DATA_USING_GPA_DIRECT ; + desc->flags =VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED ; + desc->dataoffset8 = desc_size >>3 ;/* in 8-bytes grandularity */ + desc->length8 = (u16)(packetlen_aligned >>3 ); + desc->transactionid = requestid; + desc->rangecount =1 ; + + bufferlist[0 ].iov_base = desc; + bufferlist[0 ].iov_len = desc_size; + 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); + +if (ret ==0 && signal) +vmbus_setevent (channel); + +return ret; +} +EXPORT_SYMBOL_GPL (vmbus_sendpacket_mpb_desc); + +/* +* vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet +* using a GPADL Direct packet type. */ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel, struct hv_multipage_buffer *multi_pagebuffer,
include/linux/hyperv.h +31 -0
@@ -57,6 +57,18 @@ struct hv_multipage_buffer {u64 pfn_array[MAX_MULTIPAGE_BUFFER_COUNT ]; }; +/* +* Multiple-page buffer array; the pfn array is variable size: +* The number of entries in the PFN array is determined by +* "len" and "offset". +*/ +struct hv_mpb_array { +/* Length and Offset determines the # of pfns in the array */ +u32 len; +u32 offset; +u64 pfn_array[]; +}; +/* 0x18 includes the proprietary packet header */ #define MAX_PAGE_BUFFER_PACKET (0x18 + \ (sizeof(struct hv_page_buffer) * \
@@ -812,6 +824,18 @@ struct vmbus_channel_packet_multipage_buffer {struct hv_multipage_buffer range; } __packed; +/* The format must be the same as struct vmdata_gpa_direct */ +struct vmbus_packet_mpb_array { +u16 type; +u16 dataoffset8; +u16 length8; +u16 flags; +u64 transactionid; +u32 reserved; +u32 rangecount;/* Always 1 in this case */ +struct hv_mpb_array range; +} __packed; + extern int vmbus_open(struct vmbus_channel *channel, u32 send_ringbuffersize,
@@ -843,6 +867,13 @@ extern int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,u32 bufferlen, u64 requestid); +extern int vmbus_sendpacket_mpb_desc (struct vmbus_channel *channel, +struct vmbus_packet_mpb_array *mpb, +u32 desc_size, +void *buffer, +u32 bufferlen, +u64 requestid); + extern int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, u32 size,
Signature · 1 line
1.7.4.1
Quoted 75 lines · K. Y. Srinivasan
Currently, the API for sending a multi-page buffer over VMBUS is limited to a maximum pfn array of
MAX_MULTIPAGE_BUFFER_COUNT. This limitation is not imposed by the host and unnecessarily limits the maximum payload that can be sent. Implement an API that does not have this restriction.Signed-off-by K. Y. Srinivasan <[email protected]>--- drivers/hv/channel.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/hyperv.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 0 deletions(-)drivers/hv/channel.c +44
-0@@ -686,6 +686,50 @@ EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);/* * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet * using a GPADL Direct packet type. +* The buffer includes the vmbus descriptor. +*/ +int vmbus_sendpacket_mpb_desc (struct vmbus_channel *channel, +struct vmbus_packet_mpb_array *desc, +u32 desc_size, +void *buffer,u32 bufferlen,u64 requestid) +{ +int ret; +u32 packetlen; +u32 packetlen_aligned; +struct kvec bufferlist[3 ]; +u64 aligned_data =0 ; +bool signal = false; + + packetlen = desc_size + bufferlen; + packetlen_aligned =ALIGN (packetlen,sizeof (u64)); + +/* Setup the descriptor */ + desc->type =VM_PKT_DATA_USING_GPA_DIRECT ; + desc->flags =VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED ; + desc->dataoffset8 = desc_size >>3 ;/* in 8-bytes grandularity */ + desc->length8 = (u16)(packetlen_aligned >>3 ); + desc->transactionid = requestid; + desc->rangecount =1 ; + + bufferlist[0 ].iov_base = desc; + bufferlist[0 ].iov_len = desc_size; + 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); + +if (ret ==0 && signal) +vmbus_setevent (channel); + +return ret; +} +EXPORT_SYMBOL_GPL (vmbus_sendpacket_mpb_desc); + +/* +* vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet +* using a GPADL Direct packet type. */ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel, struct hv_multipage_buffer *multi_pagebuffer,include/linux/hyperv.h +1
-0@@ -57,6 +57,18 @@ struct hv_multipage_buffer {u64 pfn_array[MAX_MULTIPAGE_BUFFER_COUNT ]; }; +/*
include/linux/hyperv.h struct hv_multipage_buffer { · line 70
Quoted 10 lines
include/linux/hyperv.h +10
-0+* Multiple-page buffer array; the pfn array is variable size: +* The number of entries in the PFN array is determined by +* "len" and "offset". +*/ +struct hv_mpb_array { +/* Length and Offset determines the # of pfns in the array */ +u32 len; +u32 offset; +u64 pfn_array[]; +};
Does this cross the user/kernel boundry? If so, they need to be __u32 and __u64 variables.
Quoted 9 lines
include/linux/hyperv.h +2
-0+/* 0x18 includes the proprietary packet header */ #define MAX_PAGE_BUFFER_PACKET (0x18 + \ (sizeof(struct hv_page_buffer) * \@@ -812,6 +824,18 @@ struct vmbus_channel_packet_multipage_buffer {struct hv_multipage_buffer range; } __packed; +/* The format must be the same as struct vmdata_gpa_direct */
include/linux/hyperv.h struct vmbus_channel_packet_multipage_buffer { · line 837
Quoted 10 lines
include/linux/hyperv.h +10
-0+struct vmbus_packet_mpb_array { +u16 type; +u16 dataoffset8; +u16 length8; +u16 flags; +u64 transactionid; +u32 reserved; +u32 rangecount;/* Always 1 in this case */ +struct hv_mpb_array range; +} __packed;
Same here.
thanks,
greg k-h
Quoted 92 lines
-----Original Message-----
From: Greg KH [mailto:[email protected]]
Sent: Monday, December 15, 2014 11:34 AM
To: KY Srinivasan
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]
Subject: Re: [PATCH 1/1] Drivers: hv: vmbus: Support a vmbus API for efficiently sending page arraysQuoted 2 lines · K. Y. Srinivasan
Currently, the API for sending a multi-page buffer over VMBUS is limited to a maximum pfn array of
MAX_MULTIPAGE_BUFFER_COUNT.This
Quoted 2 lines
limitation is not imposed by the host and unnecessarily limits the maximum payload that can be sent. Implement an API that does not have
this restriction.
Quoted 4 lines
Signed-off-by K. Y. Srinivasan <[email protected]>--- drivers/hv/channel.c | 44++++++++++++++++++++++++++++++++++++++++++++
drivers/hv/channel.c
Quoted 8 lines
include/linux/hyperv.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 0 deletions(-)drivers/hv/channel.c index renamed from drivers/hv/channel.c +0
-0c76ffbe..18c4f23 100644
drivers/hv/channel.c +0
-0@@ -686,6 +686,50 @@
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);Quoted 12 lines
drivers/hv/channel.c +9
-0/* * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet * using a GPADL Direct packet type. +* The buffer includes the vmbus descriptor. +*/ +int vmbus_sendpacket_mpb_desc (struct vmbus_channel *channel, +struct vmbus_packet_mpb_array *desc, +u32 desc_size, +void *buffer,u32 bufferlen,u64 requestid) { +int ret; +u32 packetlen; +u32 packetlen_aligned;drivers/hv/channel.c EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
Quoted 10 lines
drivers/hv/channel.c +10
-0+struct kvec bufferlist[3 ]; +u64 aligned_data =0 ; +bool signal = false; + + packetlen = desc_size + bufferlen; + packetlen_aligned =ALIGN (packetlen,sizeof (u64)); + +/* Setup the descriptor */ + desc->type =VM_PKT_DATA_USING_GPA_DIRECT ; + desc->flags =
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;Quoted 18 lines
drivers/hv/channel.c +18
-0+ desc->dataoffset8 = desc_size >>3 ;/* in 8-bytes grandularity */ + desc->length8 = (u16)(packetlen_aligned >>3 ); + desc->transactionid = requestid; + desc->rangecount =1 ; + + bufferlist[0 ].iov_base = desc; + bufferlist[0 ].iov_len = desc_size; + 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); + +if (ret ==0 && signal) +vmbus_setevent (channel); +drivers/hv/channel.c EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
Quoted 10 lines
drivers/hv/channel.c +7
-0+return ret; +} +EXPORT_SYMBOL_GPL (vmbus_sendpacket_mpb_desc); + +/* +* vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet +* using a GPADL Direct packet type. */ int vmbus_sendpacket_multipagebuffer (struct vmbus_channel *channel, struct hv_multipage_buffer
*multi_pagebuffer, diff --gitQuoted 8 lines
a/include/linux/hyperv.hb/include/linux/hyperv.hindex 08cfaff..8615b0d 100644include/linux/hyperv.h +0
-0@@ -57,6 +57,18 @@ struct hv_multipage_buffer {u64 pfn_array[MAX_MULTIPAGE_BUFFER_COUNT ]; };
Quoted 14 lines
include/linux/hyperv.h struct hv_multipage_buffer { · line 70
Quoted 11 lines
include/linux/hyperv.h +11
-0+/* +* Multiple-page buffer array; the pfn array is variable size: +* The number of entries in the PFN array is determined by +* "len" and "offset". +*/ +struct hv_mpb_array { +/* Length and Offset determines the # of pfns in the array */ +u32 len; +u32 offset; +u64 pfn_array[]; +};Does this cross the user/kernel boundry? If so, they need to be
__u32and__u64variables.
This does not cross user/kernel boundry.
Quoted 11 lines
include/linux/hyperv.h struct hv_multipage_buffer {
Quoted 4 lines
include/linux/hyperv.h +1
-0+/* 0x18 includes the proprietary packet header */ #define MAX_PAGE_BUFFER_PACKET (0x18 +\Quoted 1 line
include/linux/hyperv.h +0
-0(sizeof(struct hv_page_buffer) * \(quoted diff) +0
-0@@ -812,6 +824,18 @@ struct > vmbus_channel_packet_multipage_buffer { > struct hv_multipage_buffer range; > } __packed;Quoted 1 line
Quoted 13 lines
include/linux/hyperv.h struct vmbus_channel_packet_multipage_buffer { · line 837
Quoted 11 lines
include/linux/hyperv.h +11
-0+/* The format must be the same as struct vmdata_gpa_direct */ struct +vmbus_packet_mpb_array { +u16 type; +u16 dataoffset8; +u16 length8; +u16 flags; +u64 transactionid; +u32 reserved; +u32 rangecount;/* Always 1 in this case */ +struct hv_mpb_array range; +} __packed;Same here.
This is completely internal to the kernel.
Regards,
K. Y
Quoted 4 lines
thanks,
greg k-h