VirtualBox

source: vbox/trunk/src/VBox/Additions/linux/drm/vbox_drv.c@ 75837

最後變更 在這個檔案從75837是 74963,由 vboxsync 提交於 6 年 前

Additions/linux/vboxvideo: really disable the resize capability on master drop.
bugref:9253: Enabling 2nd virtual screen results in an assert.
The previous change for this bug, by preventing disabling and re-enabling of
acceleration in the device, accidentally prevented propagation of disabling
the resize capability which should happen at the same time, when ownership
of master in the driver changes. This change explicitly propagates it to the
device. It fixes a problem whereby the size of the boot splash screen on
shutdown was wrongly remembered as the last size for the virtual machine. As
the boot splash screen cannot handle dynamic resizing we should ignore any
size it may set for that purpose.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 9.0 KB
 
1/* $Id: vbox_drv.c 74963 2018-10-22 08:39:34Z vboxsync $ */
2/** @file
3 * VirtualBox Additions Linux kernel video driver
4 */
5
6/*
7 * Copyright (C) 2013-2017 Oracle Corporation
8 * This file is based on ast_drv.c
9 * Copyright 2012 Red Hat Inc.
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the
13 * "Software"), to deal in the Software without restriction, including
14 * without limitation the rights to use, copy, modify, merge, publish,
15 * distribute, sub license, and/or sell copies of the Software, and to
16 * permit persons to whom the Software is furnished to do so, subject to
17 * the following conditions:
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 * USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * The above copyright notice and this permission notice (including the
28 * next paragraph) shall be included in all copies or substantial portions
29 * of the Software.
30 *
31 * Authors: Dave Airlie <[email protected]>
32 * Michael Thayer <[email protected],
33 * Hans de Goede <[email protected]>
34 */
35#include <linux/module.h>
36#include <linux/console.h>
37#include <linux/vt_kern.h>
38
39#include <drm/drmP.h>
40#include <drm/drm_crtc_helper.h>
41
42#include "vbox_drv.h"
43
44#include "version-generated.h"
45#include "revision-generated.h"
46
47static int vbox_modeset = -1;
48
49MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
50module_param_named(modeset, vbox_modeset, int, 0400);
51
52static struct drm_driver driver;
53
54static const struct pci_device_id pciidlist[] = {
55 { 0x80ee, 0xbeef, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
56 { 0, 0, 0},
57};
58MODULE_DEVICE_TABLE(pci, pciidlist);
59
60static int vbox_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
61{
62 return drm_get_pci_dev(pdev, ent, &driver);
63}
64
65static void vbox_pci_remove(struct pci_dev *pdev)
66{
67 struct drm_device *dev = pci_get_drvdata(pdev);
68
69 drm_put_dev(dev);
70}
71
72#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) && !defined(RHEL_74)
73static void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
74 bool suspend)
75{
76 if (!fb_helper || !fb_helper->fbdev)
77 return;
78
79 console_lock();
80 fb_set_suspend(fb_helper->fbdev, suspend);
81 console_unlock();
82}
83#endif
84
85static int vbox_drm_freeze(struct drm_device *dev)
86{
87 struct vbox_private *vbox = dev->dev_private;
88
89 drm_kms_helper_poll_disable(dev);
90
91 pci_save_state(dev->pdev);
92
93 drm_fb_helper_set_suspend_unlocked(&vbox->fbdev->helper, true);
94
95 return 0;
96}
97
98static int vbox_drm_thaw(struct drm_device *dev)
99{
100 struct vbox_private *vbox = dev->dev_private;
101
102 drm_mode_config_reset(dev);
103 drm_helper_resume_force_mode(dev);
104 drm_fb_helper_set_suspend_unlocked(&vbox->fbdev->helper, false);
105
106 return 0;
107}
108
109static int vbox_drm_resume(struct drm_device *dev)
110{
111 int ret;
112
113 if (pci_enable_device(dev->pdev))
114 return -EIO;
115
116 ret = vbox_drm_thaw(dev);
117 if (ret)
118 return ret;
119
120 drm_kms_helper_poll_enable(dev);
121
122 return 0;
123}
124
125static int vbox_pm_suspend(struct device *dev)
126{
127 struct pci_dev *pdev = to_pci_dev(dev);
128 struct drm_device *ddev = pci_get_drvdata(pdev);
129 int error;
130
131 error = vbox_drm_freeze(ddev);
132 if (error)
133 return error;
134
135 pci_disable_device(pdev);
136 pci_set_power_state(pdev, PCI_D3hot);
137
138 return 0;
139}
140
141static int vbox_pm_resume(struct device *dev)
142{
143 struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
144
145 return vbox_drm_resume(ddev);
146}
147
148static int vbox_pm_freeze(struct device *dev)
149{
150 struct pci_dev *pdev = to_pci_dev(dev);
151 struct drm_device *ddev = pci_get_drvdata(pdev);
152
153 if (!ddev || !ddev->dev_private)
154 return -ENODEV;
155
156 return vbox_drm_freeze(ddev);
157}
158
159static int vbox_pm_thaw(struct device *dev)
160{
161 struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
162
163 return vbox_drm_thaw(ddev);
164}
165
166static int vbox_pm_poweroff(struct device *dev)
167{
168 struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
169
170 return vbox_drm_freeze(ddev);
171}
172
173static const struct dev_pm_ops vbox_pm_ops = {
174 .suspend = vbox_pm_suspend,
175 .resume = vbox_pm_resume,
176 .freeze = vbox_pm_freeze,
177 .thaw = vbox_pm_thaw,
178 .poweroff = vbox_pm_poweroff,
179 .restore = vbox_pm_resume,
180};
181
182static struct pci_driver vbox_pci_driver = {
183 .name = DRIVER_NAME,
184 .id_table = pciidlist,
185 .probe = vbox_pci_probe,
186 .remove = vbox_pci_remove,
187 .driver.pm = &vbox_pm_ops,
188};
189
190#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) && !defined(RHEL_74)
191/* This works around a bug in X servers prior to 1.18.4, which sometimes
192 * submit more dirty rectangles than the kernel is willing to handle and
193 * then disable dirty rectangle handling altogether when they see the
194 * EINVAL error. I do not want the code to hang around forever, which is
195 * why I am limiting it to certain kernel versions. We can increase the
196 * limit if some distributions uses old X servers with new kernels. */
197long vbox_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
198{
199 long rc = drm_ioctl(filp, cmd, arg);
200
201 if (cmd == DRM_IOCTL_MODE_DIRTYFB && rc == -EINVAL)
202 return -EOVERFLOW;
203
204 return rc;
205}
206#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) && !RHEL_74 */
207
208static const struct file_operations vbox_fops = {
209 .owner = THIS_MODULE,
210 .open = drm_open,
211 .release = drm_release,
212#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) && !defined(RHEL_74)
213 .unlocked_ioctl = vbox_ioctl,
214#else
215 .unlocked_ioctl = drm_ioctl,
216#endif
217 .mmap = vbox_mmap,
218 .poll = drm_poll,
219#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) && !defined(RHEL_70)
220 .fasync = drm_fasync,
221#endif
222#ifdef CONFIG_COMPAT
223 .compat_ioctl = drm_compat_ioctl,
224#endif
225 .read = drm_read,
226};
227
228static int vbox_master_set(struct drm_device *dev,
229 struct drm_file *file_priv, bool from_open)
230{
231 struct vbox_private *vbox = dev->dev_private;
232
233 /*
234 * We do not yet know whether the new owner can handle hotplug, so we
235 * do not advertise dynamic modes on the first query and send a
236 * tentative hotplug notification after that to see if they query again.
237 */
238 vbox->initial_mode_queried = false;
239
240 mutex_lock(&vbox->hw_mutex);
241 /* Start the refresh timer in case the user does not provide dirty
242 * rectangles. */
243 vbox->need_refresh_timer = true;
244 schedule_delayed_work(&vbox->refresh_work, VBOX_REFRESH_PERIOD);
245 mutex_unlock(&vbox->hw_mutex);
246
247 return 0;
248}
249
250#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) && !defined(RHEL_74)
251static void vbox_master_drop(struct drm_device *dev,
252 struct drm_file *file_priv, bool from_release)
253#else
254static void vbox_master_drop(struct drm_device *dev, struct drm_file *file_priv)
255#endif
256{
257 struct vbox_private *vbox = dev->dev_private;
258
259 /* See vbox_master_set() */
260 vbox->initial_mode_queried = false;
261 vbox_report_caps(vbox);
262
263 mutex_lock(&vbox->hw_mutex);
264 vbox->need_refresh_timer = false;
265 mutex_unlock(&vbox->hw_mutex);
266}
267
268static struct drm_driver driver = {
269 .driver_features =
270 DRIVER_MODESET | DRIVER_GEM | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
271 DRIVER_PRIME,
272 .dev_priv_size = 0,
273
274 .load = vbox_driver_load,
275 .unload = vbox_driver_unload,
276 .lastclose = vbox_driver_lastclose,
277 .master_set = vbox_master_set,
278 .master_drop = vbox_master_drop,
279#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) || defined(RHEL_73)
280# if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) && !defined(RHEL_75)
281 .set_busid = drm_pci_set_busid,
282# endif
283#endif
284
285 .fops = &vbox_fops,
286 .irq_handler = vbox_irq_handler,
287 .name = DRIVER_NAME,
288 .desc = DRIVER_DESC,
289 .date = DRIVER_DATE,
290 .major = DRIVER_MAJOR,
291 .minor = DRIVER_MINOR,
292 .patchlevel = DRIVER_PATCHLEVEL,
293
294 .gem_free_object = vbox_gem_free_object,
295 .dumb_create = vbox_dumb_create,
296 .dumb_map_offset = vbox_dumb_mmap_offset,
297#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) && !defined(RHEL_73)
298 .dumb_destroy = vbox_dumb_destroy,
299#else
300 .dumb_destroy = drm_gem_dumb_destroy,
301#endif
302 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
303 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
304 .gem_prime_export = drm_gem_prime_export,
305 .gem_prime_import = drm_gem_prime_import,
306 .gem_prime_pin = vbox_gem_prime_pin,
307 .gem_prime_unpin = vbox_gem_prime_unpin,
308 .gem_prime_get_sg_table = vbox_gem_prime_get_sg_table,
309 .gem_prime_import_sg_table = vbox_gem_prime_import_sg_table,
310 .gem_prime_vmap = vbox_gem_prime_vmap,
311 .gem_prime_vunmap = vbox_gem_prime_vunmap,
312 .gem_prime_mmap = vbox_gem_prime_mmap,
313};
314
315static int __init vbox_init(void)
316{
317#if defined(CONFIG_VGA_CONSOLE) || LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
318 if (vgacon_text_force() && vbox_modeset == -1)
319 return -EINVAL;
320#endif
321
322 if (vbox_modeset == 0)
323 return -EINVAL;
324
325 return pci_register_driver(&vbox_pci_driver);
326}
327
328static void __exit vbox_exit(void)
329{
330 pci_unregister_driver(&vbox_pci_driver);
331}
332
333module_init(vbox_init);
334module_exit(vbox_exit);
335
336MODULE_AUTHOR(DRIVER_AUTHOR);
337MODULE_DESCRIPTION(DRIVER_DESC);
338MODULE_LICENSE("GPL and additional rights");
339#ifdef MODULE_VERSION
340MODULE_VERSION(VBOX_VERSION_STRING " r" __stringify(VBOX_SVN_REV));
341#endif
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette