diff options
-rw-r--r-- | drivers/virt/vboxguest/vboxguest_linux.c | 19 | ||||
-rw-r--r-- | drivers/virt/vboxguest/vboxguest_utils.c | 5 |
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 | ||
134 | out: | 144 | out: |
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); | |||
65 | void *vbg_req_alloc(size_t len, enum vmmdev_request_type req_type) | 65 | void *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!! */ |