VirtualBox

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

Last change on this file since 67269 was 67177, checked in by vboxsync, 8 years ago

bugref:8524: Additions/linux: play nicely with distribution-installed Additions
[PATCH 3/3] additions/linux/drm: Remove dependency on iprt/cdefs,stdarg,stdint and types.h
Signed-off-by: Hans de Goede <hdegoede@…>
With a small fix to remove a left-over IPRT symbol.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.2 KB
Line 
1/* $Id: vbox_drv.c 67177 2017-05-31 14:59:02Z 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 "vbox_drv.h"
36
37#include "version-generated.h"
38#include "revision-generated.h"
39
40#include <linux/module.h>
41#include <linux/console.h>
42#include <linux/vt_kern.h>
43
44#include <drm/drmP.h>
45#include <drm/drm_crtc_helper.h>
46
47int 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{
56 {0x80ee, 0xbeef, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
57 {0, 0, 0},
58};
59
60MODULE_DEVICE_TABLE(pci, pciidlist);
61
62static int vbox_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
63{
64 return drm_get_pci_dev(pdev, ent, &driver);
65}
66
67
68static void vbox_pci_remove(struct pci_dev *pdev)
69{
70 struct drm_device *dev = pci_get_drvdata(pdev);
71
72 drm_put_dev(dev);
73}
74
75
76
77static int vbox_drm_freeze(struct drm_device *dev)
78{
79 drm_kms_helper_poll_disable(dev);
80
81 pci_save_state(dev->pdev);
82
83 console_lock();
84 vbox_fbdev_set_suspend(dev, 1);
85 console_unlock();
86 return 0;
87}
88
89static int vbox_drm_thaw(struct drm_device *dev)
90{
91 int error = 0;
92
93 drm_mode_config_reset(dev);
94 drm_helper_resume_force_mode(dev);
95
96 console_lock();
97 vbox_fbdev_set_suspend(dev, 0);
98 console_unlock();
99 return error;
100}
101
102static int vbox_drm_resume(struct drm_device *dev)
103{
104 int ret;
105
106 if (pci_enable_device(dev->pdev))
107 return -EIO;
108
109 ret = vbox_drm_thaw(dev);
110 if (ret)
111 return ret;
112
113 drm_kms_helper_poll_enable(dev);
114 return 0;
115}
116
117static int vbox_pm_suspend(struct device *dev)
118{
119 struct pci_dev *pdev = to_pci_dev(dev);
120 struct drm_device *ddev = pci_get_drvdata(pdev);
121 int error;
122
123 error = vbox_drm_freeze(ddev);
124 if (error)
125 return error;
126
127 pci_disable_device(pdev);
128 pci_set_power_state(pdev, PCI_D3hot);
129 return 0;
130}
131
132static int vbox_pm_resume(struct device *dev)
133{
134 struct pci_dev *pdev = to_pci_dev(dev);
135 struct drm_device *ddev = pci_get_drvdata(pdev);
136 return vbox_drm_resume(ddev);
137}
138
139static int vbox_pm_freeze(struct device *dev)
140{
141 struct pci_dev *pdev = to_pci_dev(dev);
142 struct drm_device *ddev = pci_get_drvdata(pdev);
143
144 if (!ddev || !ddev->dev_private)
145 return -ENODEV;
146 return vbox_drm_freeze(ddev);
147
148}
149
150static int vbox_pm_thaw(struct device *dev)
151{
152 struct pci_dev *pdev = to_pci_dev(dev);
153 struct drm_device *ddev = pci_get_drvdata(pdev);
154 return vbox_drm_thaw(ddev);
155}
156
157static int vbox_pm_poweroff(struct device *dev)
158{
159 struct pci_dev *pdev = to_pci_dev(dev);
160 struct drm_device *ddev = pci_get_drvdata(pdev);
161
162 return vbox_drm_freeze(ddev);
163}
164
165static const struct dev_pm_ops vbox_pm_ops = {
166 .suspend = vbox_pm_suspend,
167 .resume = vbox_pm_resume,
168 .freeze = vbox_pm_freeze,
169 .thaw = vbox_pm_thaw,
170 .poweroff = vbox_pm_poweroff,
171 .restore = vbox_pm_resume,
172};
173
174static struct pci_driver vbox_pci_driver =
175{
176 .name = DRIVER_NAME,
177 .id_table = pciidlist,
178 .probe = vbox_pci_probe,
179 .remove = vbox_pci_remove,
180 .driver.pm = &vbox_pm_ops,
181};
182
183#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0)
184/* This works around a bug in X servers prior to 1.18.4, which sometimes
185 * submit more dirty rectangles than the kernel is willing to handle and
186 * then disable dirty rectangle handling altogether when they see the
187 * EINVAL error. I do not want the code to hang around forever, which is
188 * why I am limiting it to certain kernel versions. We can increase the
189 * limit if some distributions uses old X servers with new kernels. */
190long vbox_ioctl(struct file *filp,
191 unsigned int cmd, unsigned long arg)
192{
193 long rc = drm_ioctl(filp, cmd, arg);
194 if (cmd == DRM_IOCTL_MODE_DIRTYFB && rc == -EINVAL)
195 return -EOVERFLOW;
196 return rc;
197}
198#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) */
199
200static const struct file_operations vbox_fops =
201{
202 .owner = THIS_MODULE,
203 .open = drm_open,
204 .release = drm_release,
205#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0)
206 .unlocked_ioctl = vbox_ioctl,
207#else
208 .unlocked_ioctl = drm_ioctl,
209#endif
210 .mmap = vbox_mmap,
211 .poll = drm_poll,
212#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)
213 .fasync = drm_fasync,
214#endif
215#ifdef CONFIG_COMPAT
216 .compat_ioctl = drm_compat_ioctl,
217#endif
218 .read = drm_read,
219};
220
221static int vbox_master_set(struct drm_device *dev,
222 struct drm_file *file_priv,
223 bool from_open)
224{
225 struct vbox_private *vbox = dev->dev_private;
226 /* We do not yet know whether the new owner can handle hotplug, so we
227 * do not advertise dynamic modes on the first query and send a
228 * tentative hotplug notification after that to see if they query again. */
229 vbox->initial_mode_queried = false;
230 mutex_lock(&vbox->hw_mutex);
231 /* Disable VBVA when someone releases master in case the next person tries
232 * to do VESA. */
233 /** @todo work out if anyone is likely to and whether it will even work. */
234 /* Update: we also disable it because if the new master does not do dirty
235 * rectangle reporting (e.g. old versions of Plymouth) then at least the
236 * first screen will still be updated. We enable it as soon as we
237 * receive a dirty rectangle report. */
238 vbox_disable_accel(vbox);
239 mutex_unlock(&vbox->hw_mutex);
240 return 0;
241}
242
243#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)
244static void vbox_master_drop(struct drm_device *dev,
245 struct drm_file *file_priv,
246 bool from_release)
247#else
248static void vbox_master_drop(struct drm_device *dev,
249 struct drm_file *file_priv)
250#endif
251{
252 struct vbox_private *vbox = dev->dev_private;
253 /* See vbox_master_set() */
254 vbox->initial_mode_queried = false;
255 mutex_lock(&vbox->hw_mutex);
256 vbox_disable_accel(vbox);
257 mutex_unlock(&vbox->hw_mutex);
258}
259
260static struct drm_driver driver =
261{
262 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_PRIME,
263 .dev_priv_size = 0,
264
265 .load = vbox_driver_load,
266 .unload = vbox_driver_unload,
267 .lastclose = vbox_driver_lastclose,
268 .master_set = vbox_master_set,
269 .master_drop = vbox_master_drop,
270#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
271 .set_busid = drm_pci_set_busid,
272#endif
273
274 .fops = &vbox_fops,
275 .irq_handler = vbox_irq_handler,
276 .name = DRIVER_NAME,
277 .desc = DRIVER_DESC,
278 .date = DRIVER_DATE,
279 .major = DRIVER_MAJOR,
280 .minor = DRIVER_MINOR,
281 .patchlevel = DRIVER_PATCHLEVEL,
282
283 .gem_free_object = vbox_gem_free_object,
284 .dumb_create = vbox_dumb_create,
285 .dumb_map_offset = vbox_dumb_mmap_offset,
286#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)
287 .dumb_destroy = vbox_dumb_destroy,
288#else
289 .dumb_destroy = drm_gem_dumb_destroy,
290#endif
291 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
292 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
293 .gem_prime_export = drm_gem_prime_export,
294 .gem_prime_import = drm_gem_prime_import,
295 .gem_prime_pin = vbox_gem_prime_pin,
296 .gem_prime_unpin = vbox_gem_prime_unpin,
297 .gem_prime_get_sg_table = vbox_gem_prime_get_sg_table,
298 .gem_prime_import_sg_table = vbox_gem_prime_import_sg_table,
299 .gem_prime_vmap = vbox_gem_prime_vmap,
300 .gem_prime_vunmap = vbox_gem_prime_vunmap,
301 .gem_prime_mmap = vbox_gem_prime_mmap,
302
303};
304
305static int __init vbox_init(void)
306{
307#ifdef CONFIG_VGA_CONSOLE
308 if (vgacon_text_force() && vbox_modeset == -1)
309 return -EINVAL;
310#endif
311
312 if (vbox_modeset == 0)
313 return -EINVAL;
314
315 return drm_pci_init(&driver, &vbox_pci_driver);
316}
317static void __exit vbox_exit(void)
318{
319 drm_pci_exit(&driver, &vbox_pci_driver);
320}
321
322module_init(vbox_init);
323module_exit(vbox_exit);
324
325MODULE_AUTHOR(DRIVER_AUTHOR);
326MODULE_DESCRIPTION(DRIVER_DESC);
327MODULE_LICENSE("GPL and additional rights");
328#ifdef MODULE_VERSION
329MODULE_VERSION(VBOX_VERSION_STRING " r" __stringify(VBOX_SVN_REV));
330#endif
Note: See TracBrowser for help on using the repository browser.

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