aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHaiyang Zhang <haiyangz@microsoft.com>2014-01-27 18:03:42 -0500
committerDavid S. Miller <davem@davemloft.net>2014-01-27 19:40:45 -0500
commitb679ef73edc251f6d200a7dd2396e9fef9e36fc3 (patch)
treeb04daa074ce7083d763eea8daaf4e7d88a61c320
parent731073b9c99d46c6b6c01184f67ee6f75fd7a163 (diff)
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>
-rw-r--r--drivers/hv/channel.c14
-rw-r--r--drivers/net/hyperv/hyperv_net.h2
-rw-r--r--drivers/net/hyperv/netvsc.c7
3 files changed, 11 insertions, 12 deletions
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index cea623c36ae2..69ea36f07b4d 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -209,7 +209,6 @@ static int create_gpadl_header(void *kbuffer, u32 size,
209{ 209{
210 int i; 210 int i;
211 int pagecount; 211 int pagecount;
212 unsigned long long pfn;
213 struct vmbus_channel_gpadl_header *gpadl_header; 212 struct vmbus_channel_gpadl_header *gpadl_header;
214 struct vmbus_channel_gpadl_body *gpadl_body; 213 struct vmbus_channel_gpadl_body *gpadl_body;
215 struct vmbus_channel_msginfo *msgheader; 214 struct vmbus_channel_msginfo *msgheader;
@@ -219,7 +218,6 @@ static int create_gpadl_header(void *kbuffer, u32 size,
219 int pfnsum, pfncount, pfnleft, pfncurr, pfnsize; 218 int pfnsum, pfncount, pfnleft, pfncurr, pfnsize;
220 219
221 pagecount = size >> PAGE_SHIFT; 220 pagecount = size >> PAGE_SHIFT;
222 pfn = virt_to_phys(kbuffer) >> PAGE_SHIFT;
223 221
224 /* do we need a gpadl body msg */ 222 /* do we need a gpadl body msg */
225 pfnsize = MAX_SIZE_CHANNEL_MESSAGE - 223 pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
@@ -248,7 +246,8 @@ static int create_gpadl_header(void *kbuffer, u32 size,
248 gpadl_header->range[0].byte_offset = 0; 246 gpadl_header->range[0].byte_offset = 0;
249 gpadl_header->range[0].byte_count = size; 247 gpadl_header->range[0].byte_count = size;
250 for (i = 0; i < pfncount; i++) 248 for (i = 0; i < pfncount; i++)
251 gpadl_header->range[0].pfn_array[i] = pfn+i; 249 gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys(
250 kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT;
252 *msginfo = msgheader; 251 *msginfo = msgheader;
253 *messagecount = 1; 252 *messagecount = 1;
254 253
@@ -301,7 +300,9 @@ static int create_gpadl_header(void *kbuffer, u32 size,
301 * so the hypervisor gurantees that this is ok. 300 * so the hypervisor gurantees that this is ok.
302 */ 301 */
303 for (i = 0; i < pfncurr; i++) 302 for (i = 0; i < pfncurr; i++)
304 gpadl_body->pfn[i] = pfn + pfnsum + i; 303 gpadl_body->pfn[i] = slow_virt_to_phys(
304 kbuffer + PAGE_SIZE * (pfnsum + i)) >>
305 PAGE_SHIFT;
305 306
306 /* add to msg header */ 307 /* add to msg header */
307 list_add_tail(&msgbody->msglistentry, 308 list_add_tail(&msgbody->msglistentry,
@@ -327,7 +328,8 @@ static int create_gpadl_header(void *kbuffer, u32 size,
327 gpadl_header->range[0].byte_offset = 0; 328 gpadl_header->range[0].byte_offset = 0;
328 gpadl_header->range[0].byte_count = size; 329 gpadl_header->range[0].byte_count = size;
329 for (i = 0; i < pagecount; i++) 330 for (i = 0; i < pagecount; i++)
330 gpadl_header->range[0].pfn_array[i] = pfn+i; 331 gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys(
332 kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT;
331 333
332 *msginfo = msgheader; 334 *msginfo = msgheader;
333 *messagecount = 1; 335 *messagecount = 1;
@@ -344,7 +346,7 @@ nomem:
344 * vmbus_establish_gpadl - Estabish a GPADL for the specified buffer 346 * vmbus_establish_gpadl - Estabish a GPADL for the specified buffer
345 * 347 *
346 * @channel: a channel 348 * @channel: a channel
347 * @kbuffer: from kmalloc 349 * @kbuffer: from kmalloc or vmalloc
348 * @size: page-size multiple 350 * @size: page-size multiple
349 * @gpadl_handle: some funky thing 351 * @gpadl_handle: some funky thing
350 */ 352 */
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index a26eecb1212c..7b594ce3f21d 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -462,7 +462,7 @@ struct nvsp_message {
462 462
463#define NETVSC_MTU 65536 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#define NETVSC_RECEIVE_BUFFER_ID 0xcafe 467#define NETVSC_RECEIVE_BUFFER_ID 0xcafe
468 468
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 93b485b96249..03a2c6e17158 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -136,8 +136,7 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device)
136 136
137 if (net_device->recv_buf) { 137 if (net_device->recv_buf) {
138 /* Free up the receive buffer */ 138 /* Free up the receive buffer */
139 free_pages((unsigned long)net_device->recv_buf, 139 vfree(net_device->recv_buf);
140 get_order(net_device->recv_buf_size));
141 net_device->recv_buf = NULL; 140 net_device->recv_buf = NULL;
142 } 141 }
143 142
@@ -163,9 +162,7 @@ static int netvsc_init_recv_buf(struct hv_device *device)
163 return -ENODEV; 162 return -ENODEV;
164 ndev = net_device->ndev; 163 ndev = net_device->ndev;
165 164
166 net_device->recv_buf = 165 net_device->recv_buf = vzalloc(net_device->recv_buf_size);
167 (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
168 get_order(net_device->recv_buf_size));
169 if (!net_device->recv_buf) { 166 if (!net_device->recv_buf) {
170 netdev_err(ndev, "unable to allocate receive " 167 netdev_err(ndev, "unable to allocate receive "
171 "buffer of size %d\n", net_device->recv_buf_size); 168 "buffer of size %d\n", net_device->recv_buf_size);