Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

hyperv: Add support for physically discontinuous receive buffer

This will allow us to use bigger receive buffer, and prevent allocation failure
due to fragmented memory.

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Haiyang Zhang and committed by
David S. Miller
b679ef73 731073b9

+11 -12
+8 -6
drivers/hv/channel.c
··· 209 209 { 210 210 int i; 211 211 int pagecount; 212 - unsigned long long pfn; 213 212 struct vmbus_channel_gpadl_header *gpadl_header; 214 213 struct vmbus_channel_gpadl_body *gpadl_body; 215 214 struct vmbus_channel_msginfo *msgheader; ··· 218 219 int pfnsum, pfncount, pfnleft, pfncurr, pfnsize; 219 220 220 221 pagecount = size >> PAGE_SHIFT; 221 - pfn = virt_to_phys(kbuffer) >> PAGE_SHIFT; 222 222 223 223 /* do we need a gpadl body msg */ 224 224 pfnsize = MAX_SIZE_CHANNEL_MESSAGE - ··· 246 248 gpadl_header->range[0].byte_offset = 0; 247 249 gpadl_header->range[0].byte_count = size; 248 250 for (i = 0; i < pfncount; i++) 249 - gpadl_header->range[0].pfn_array[i] = pfn+i; 251 + gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys( 252 + kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT; 250 253 *msginfo = msgheader; 251 254 *messagecount = 1; 252 255 ··· 300 301 * so the hypervisor gurantees that this is ok. 301 302 */ 302 303 for (i = 0; i < pfncurr; i++) 303 - gpadl_body->pfn[i] = pfn + pfnsum + i; 304 + gpadl_body->pfn[i] = slow_virt_to_phys( 305 + kbuffer + PAGE_SIZE * (pfnsum + i)) >> 306 + PAGE_SHIFT; 304 307 305 308 /* add to msg header */ 306 309 list_add_tail(&msgbody->msglistentry, ··· 328 327 gpadl_header->range[0].byte_offset = 0; 329 328 gpadl_header->range[0].byte_count = size; 330 329 for (i = 0; i < pagecount; i++) 331 - gpadl_header->range[0].pfn_array[i] = pfn+i; 330 + gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys( 331 + kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT; 332 332 333 333 *msginfo = msgheader; 334 334 *messagecount = 1; ··· 346 344 * vmbus_establish_gpadl - Estabish a GPADL for the specified buffer 347 345 * 348 346 * @channel: a channel 349 - * @kbuffer: from kmalloc 347 + * @kbuffer: from kmalloc or vmalloc 350 348 * @size: page-size multiple 351 349 * @gpadl_handle: some funky thing 352 350 */
+1 -1
drivers/net/hyperv/hyperv_net.h
··· 462 462 463 463 #define NETVSC_MTU 65536 464 464 465 - #define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024*2) /* 2MB */ 465 + #define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024*16) /* 16MB */ 466 466 467 467 #define NETVSC_RECEIVE_BUFFER_ID 0xcafe 468 468
+2 -5
drivers/net/hyperv/netvsc.c
··· 136 136 137 137 if (net_device->recv_buf) { 138 138 /* Free up the receive buffer */ 139 - free_pages((unsigned long)net_device->recv_buf, 140 - get_order(net_device->recv_buf_size)); 139 + vfree(net_device->recv_buf); 141 140 net_device->recv_buf = NULL; 142 141 } 143 142 ··· 162 163 return -ENODEV; 163 164 ndev = net_device->ndev; 164 165 165 - net_device->recv_buf = 166 - (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, 167 - get_order(net_device->recv_buf_size)); 166 + net_device->recv_buf = vzalloc(net_device->recv_buf_size); 168 167 if (!net_device->recv_buf) { 169 168 netdev_err(ndev, "unable to allocate receive " 170 169 "buffer of size %d\n", net_device->recv_buf_size);