summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/virt/vboxguest/vboxguest_linux.c19
-rw-r--r--drivers/virt/vboxguest/vboxguest_utils.c5
2 files changed, 19 insertions, 5 deletions
diff --git a/drivers/virt/vboxguest/vboxguest_linux.c b/drivers/virt/vboxguest/vboxguest_linux.c
index 82e280d38cc2..398d22693234 100644
--- a/drivers/virt/vboxguest/vboxguest_linux.c
+++ b/drivers/virt/vboxguest/vboxguest_linux.c
@@ -87,6 +87,7 @@ static long vbg_misc_device_ioctl(struct file *filp, unsigned int req,
87 struct vbg_session *session = filp->private_data; 87 struct vbg_session *session = filp->private_data;
88 size_t returned_size, size; 88 size_t returned_size, size;
89 struct vbg_ioctl_hdr hdr; 89 struct vbg_ioctl_hdr hdr;
90 bool is_vmmdev_req;
90 int ret = 0; 91 int ret = 0;
91 void *buf; 92 void *buf;
92 93
@@ -106,8 +107,17 @@ static long vbg_misc_device_ioctl(struct file *filp, unsigned int req,
106 if (size > SZ_16M) 107 if (size > SZ_16M)
107 return -E2BIG; 108 return -E2BIG;
108 109
109 /* __GFP_DMA32 because IOCTL_VMMDEV_REQUEST passes this to the host */ 110 /*
110 buf = kmalloc(size, GFP_KERNEL | __GFP_DMA32); 111 * IOCTL_VMMDEV_REQUEST needs the buffer to be below 4G to avoid
112 * the need for a bounce-buffer and another copy later on.
113 */
114 is_vmmdev_req = (req & ~IOCSIZE_MASK) == VBG_IOCTL_VMMDEV_REQUEST(0) ||
115 req == VBG_IOCTL_VMMDEV_REQUEST_BIG;
116
117 if (is_vmmdev_req)
118 buf = vbg_req_alloc(size, VBG_IOCTL_HDR_TYPE_DEFAULT);
119 else
120 buf = kmalloc(size, GFP_KERNEL);
111 if (!buf) 121 if (!buf)
112 return -ENOMEM; 122 return -ENOMEM;
113 123
@@ -132,7 +142,10 @@ static long vbg_misc_device_ioctl(struct file *filp, unsigned int req,
132 ret = -EFAULT; 142 ret = -EFAULT;
133 143
134out: 144out:
135 kfree(buf); 145 if (is_vmmdev_req)
146 vbg_req_free(buf, size);
147 else
148 kfree(buf);
136 149
137 return ret; 150 return ret;
138} 151}
diff --git a/drivers/virt/vboxguest/vboxguest_utils.c b/drivers/virt/vboxguest/vboxguest_utils.c
index bad915463359..bf4474214b4d 100644
--- a/drivers/virt/vboxguest/vboxguest_utils.c
+++ b/drivers/virt/vboxguest/vboxguest_utils.c
@@ -65,8 +65,9 @@ VBG_LOG(vbg_debug, pr_debug);
65void *vbg_req_alloc(size_t len, enum vmmdev_request_type req_type) 65void *vbg_req_alloc(size_t len, enum vmmdev_request_type req_type)
66{ 66{
67 struct vmmdev_request_header *req; 67 struct vmmdev_request_header *req;
68 int order = get_order(PAGE_ALIGN(len));
68 69
69 req = kmalloc(len, GFP_KERNEL | __GFP_DMA32); 70 req = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA32, order);
70 if (!req) 71 if (!req)
71 return NULL; 72 return NULL;
72 73
@@ -87,7 +88,7 @@ void vbg_req_free(void *req, size_t len)
87 if (!req) 88 if (!req)
88 return; 89 return;
89 90
90 kfree(req); 91 free_pages((unsigned long)req, get_order(PAGE_ALIGN(len)));
91} 92}
92 93
93/* Note this function returns a VBox status code, not a negative errno!! */ 94/* Note this function returns a VBox status code, not a negative errno!! */