VirtualBox

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

Last change on this file since 102874 was 102874, checked in by vboxsync, 4 months ago

Linux Host and Guest kernel modules: Fix build for older Fedora kernels.

This commit covers build errors for Fedora 34-38 kernels. In short,
we exclude Fedora kernels (identified as RHEL XX.99) from fixes intended
for RHEL kernels.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.5 KB
RevLine 
[58129]1/* $Id: vbox_drv.c 102874 2024-01-15 12:08:04Z vboxsync $ */
2/** @file
[48115]3 * VirtualBox Additions Linux kernel video driver
4 */
5
6/*
[98103]7 * Copyright (C) 2013-2023 Oracle and/or its affiliates.
[66544]8 * This file is based on ast_drv.c
[48115]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 <airlied@redhat.com>
[66544]32 * Michael Thayer <michael.thayer@oracle.com,
33 * Hans de Goede <hdegoede@redhat.com>
[48115]34 */
35#include <linux/module.h>
36#include <linux/console.h>
[60104]37#include <linux/vt_kern.h>
[48115]38
[83109]39#include "vbox_drv.h"
40
[48115]41#include <drm/drm_crtc_helper.h>
[85705]42#if RTLNX_VER_MIN(5,1,0) || RTLNX_RHEL_MAJ_PREREQ(8,1)
[85707]43# include <drm/drm_probe_helper.h>
[77850]44#endif
45
[94330]46#if RTLNX_VER_MIN(5,14,0) || RTLNX_RHEL_RANGE(8,6, 8,99)
[90498]47# include <drm/drm_aperture.h>
48#endif
49
[74773]50#include "version-generated.h"
51#include "revision-generated.h"
52
[93416]53/** Detect whether kernel mode setting is OFF. */
54#if defined(CONFIG_VGA_CONSOLE)
[100677]55# if RTLNX_VER_MIN(5,17,0) || RTLNX_RHEL_RANGE(8,7, 8,99) || RTLNX_RHEL_MIN(9,1) || RTLNX_SUSE_MAJ_PREREQ(15,5)
[93416]56# define VBOX_VIDEO_NOMODESET() drm_firmware_drivers_only() && vbox_modeset == -1
57# elif RTLNX_VER_MIN(4,7,0)
58# define VBOX_VIDEO_NOMODESET() vgacon_text_force() && vbox_modeset == -1
59# else /* < 4.7.0 */
60# define VBOX_VIDEO_NOMODESET() 0
61# endif /* < 4.7.0 */
62#else /* !CONFIG_VGA_CONSOLE */
63# define VBOX_VIDEO_NOMODESET() 0
64#endif /* !CONFIG_VGA_CONSOLE */
65
[74810]66static int vbox_modeset = -1;
[48115]67
68MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
69module_param_named(modeset, vbox_modeset, int, 0400);
70
71static struct drm_driver driver;
72
[67395]73static const struct pci_device_id pciidlist[] = {
74 { 0x80ee, 0xbeef, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
75 { 0, 0, 0},
[48115]76};
77MODULE_DEVICE_TABLE(pci, pciidlist);
78
79static int vbox_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
80{
[86196]81#if RTLNX_VER_MIN(4,19,0) || RTLNX_RHEL_MIN(8,3)
[76976]82 struct drm_device *dev = NULL;
83 int ret = 0;
84
[94330]85# if RTLNX_VER_MIN(5,14,0) || RTLNX_RHEL_RANGE(8,6, 8,99)
[97566]86# if RTLNX_VER_MIN(5,15,0) || RTLNX_RHEL_RANGE(8,7, 8,99) || RTLNX_RHEL_MIN(9,1) || RTLNX_SUSE_MAJ_PREREQ(15,4)
[91233]87 ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &driver);
88# else
[90498]89 ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, "vboxvideofb");
[91233]90# endif
[90498]91 if (ret)
92 {
93 printk("unable to remove conflicting framebuffer devices\n");
94 return ret;
95 }
[91233]96# endif /* >= 5.14. */
[90498]97
[76976]98 dev = drm_dev_alloc(&driver, &pdev->dev);
99 if (IS_ERR(dev)) {
100 ret = PTR_ERR(dev);
101 goto err_drv_alloc;
102 }
[94330]103# if RTLNX_VER_MAX(5,14,0) && !RTLNX_RHEL_RANGE(8,6, 8,99)
[76976]104 dev->pdev = pdev;
[90583]105# endif
[76976]106 pci_set_drvdata(pdev, dev);
107
108 ret = vbox_driver_load(dev);
109 if (ret)
110 goto err_vbox_driver_load;
111
112 ret = drm_dev_register(dev, 0);
113 if (ret)
114 goto err_drv_dev_register;
115 return ret;
116
117err_drv_dev_register:
118 vbox_driver_unload(dev);
119err_vbox_driver_load:
120 drm_dev_put(dev);
121err_drv_alloc:
122 return ret;
[86196]123#else /* < 4.19.0 || RHEL < 8.3 */
124 return drm_get_pci_dev(pdev, ent, &driver);
[76976]125#endif
[48115]126}
127
[49518]128static void vbox_pci_remove(struct pci_dev *pdev)
[48115]129{
[67395]130 struct drm_device *dev = pci_get_drvdata(pdev);
[48115]131
[85704]132#if RTLNX_VER_MAX(4,19,0)
[67395]133 drm_put_dev(dev);
[76976]134#else
135 drm_dev_unregister(dev);
136 vbox_driver_unload(dev);
137 drm_dev_put(dev);
138#endif
[48115]139}
140
[85705]141#if RTLNX_VER_MAX(4,9,0) && !RTLNX_RHEL_MAJ_PREREQ(7,4)
[74773]142static void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
143 bool suspend)
144{
145 if (!fb_helper || !fb_helper->fbdev)
146 return;
147
148 console_lock();
149 fb_set_suspend(fb_helper->fbdev, suspend);
150 console_unlock();
151}
152#endif
153
[59526]154static int vbox_drm_freeze(struct drm_device *dev)
155{
[74773]156 struct vbox_private *vbox = dev->dev_private;
157
[67395]158 drm_kms_helper_poll_disable(dev);
[59526]159
[90498]160 pci_save_state(VBOX_DRM_TO_PCI_DEV(dev));
[59526]161
[74773]162 drm_fb_helper_set_suspend_unlocked(&vbox->fbdev->helper, true);
[67395]163
164 return 0;
[59526]165}
166
167static int vbox_drm_thaw(struct drm_device *dev)
168{
[74773]169 struct vbox_private *vbox = dev->dev_private;
170
[67395]171 drm_mode_config_reset(dev);
172 drm_helper_resume_force_mode(dev);
[74773]173 drm_fb_helper_set_suspend_unlocked(&vbox->fbdev->helper, false);
[59526]174
[67395]175 return 0;
[59526]176}
177
178static int vbox_drm_resume(struct drm_device *dev)
179{
[67395]180 int ret;
[59526]181
[90498]182 if (pci_enable_device(VBOX_DRM_TO_PCI_DEV(dev)))
[67395]183 return -EIO;
[59526]184
[67395]185 ret = vbox_drm_thaw(dev);
186 if (ret)
187 return ret;
[59526]188
[67395]189 drm_kms_helper_poll_enable(dev);
190
191 return 0;
[59526]192}
193
194static int vbox_pm_suspend(struct device *dev)
195{
[67395]196 struct pci_dev *pdev = to_pci_dev(dev);
197 struct drm_device *ddev = pci_get_drvdata(pdev);
198 int error;
[59526]199
[67395]200 error = vbox_drm_freeze(ddev);
201 if (error)
202 return error;
[59526]203
[67395]204 pci_disable_device(pdev);
205 pci_set_power_state(pdev, PCI_D3hot);
206
207 return 0;
[59526]208}
209
210static int vbox_pm_resume(struct device *dev)
211{
[67395]212 struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
213
214 return vbox_drm_resume(ddev);
[59526]215}
216
217static int vbox_pm_freeze(struct device *dev)
218{
[67395]219 struct pci_dev *pdev = to_pci_dev(dev);
220 struct drm_device *ddev = pci_get_drvdata(pdev);
[59526]221
[67395]222 if (!ddev || !ddev->dev_private)
223 return -ENODEV;
[59526]224
[67395]225 return vbox_drm_freeze(ddev);
[59526]226}
227
228static int vbox_pm_thaw(struct device *dev)
229{
[67395]230 struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
231
232 return vbox_drm_thaw(ddev);
[59526]233}
234
235static int vbox_pm_poweroff(struct device *dev)
236{
[67395]237 struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
[59526]238
[67395]239 return vbox_drm_freeze(ddev);
[59526]240}
241
242static const struct dev_pm_ops vbox_pm_ops = {
[67395]243 .suspend = vbox_pm_suspend,
244 .resume = vbox_pm_resume,
245 .freeze = vbox_pm_freeze,
246 .thaw = vbox_pm_thaw,
247 .poweroff = vbox_pm_poweroff,
248 .restore = vbox_pm_resume,
[59526]249};
250
[67395]251static struct pci_driver vbox_pci_driver = {
252 .name = DRIVER_NAME,
253 .id_table = pciidlist,
254 .probe = vbox_pci_probe,
255 .remove = vbox_pci_remove,
256 .driver.pm = &vbox_pm_ops,
[48115]257};
258
[85705]259#if RTLNX_VER_MAX(4,7,0) && !RTLNX_RHEL_MAJ_PREREQ(7,4)
[63551]260/* This works around a bug in X servers prior to 1.18.4, which sometimes
261 * submit more dirty rectangles than the kernel is willing to handle and
262 * then disable dirty rectangle handling altogether when they see the
263 * EINVAL error. I do not want the code to hang around forever, which is
264 * why I am limiting it to certain kernel versions. We can increase the
265 * limit if some distributions uses old X servers with new kernels. */
[67395]266long vbox_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
[63551]267{
[67395]268 long rc = drm_ioctl(filp, cmd, arg);
269
270 if (cmd == DRM_IOCTL_MODE_DIRTYFB && rc == -EINVAL)
271 return -EOVERFLOW;
272
273 return rc;
[63551]274}
[85705]275#endif /* RTLNX_VER_MAX(4,7,0) && !RTLNX_RHEL_MAJ_PREREQ(7,4) */
[63551]276
[67395]277static const struct file_operations vbox_fops = {
278 .owner = THIS_MODULE,
279 .open = drm_open,
280 .release = drm_release,
[85705]281#if RTLNX_VER_MAX(4,7,0) && !RTLNX_RHEL_MAJ_PREREQ(7,4)
[67395]282 .unlocked_ioctl = vbox_ioctl,
[63551]283#else
[67395]284 .unlocked_ioctl = drm_ioctl,
[63551]285#endif
[67395]286 .mmap = vbox_mmap,
287 .poll = drm_poll,
[85705]288#if RTLNX_VER_MAX(3,12,0) && !RTLNX_RHEL_MAJ_PREREQ(7,0)
[67395]289 .fasync = drm_fasync,
[52599]290#endif
[48115]291#ifdef CONFIG_COMPAT
[67395]292 .compat_ioctl = drm_compat_ioctl,
[48115]293#endif
[67395]294 .read = drm_read,
[48115]295};
296
[89690]297#if RTLNX_VER_MIN(5,9,0) || RTLNX_RHEL_MIN(8,4) || RTLNX_SUSE_MAJ_PREREQ(15,3)
[86542]298static void
299#else
300static int
301#endif
[86547]302vbox_master_set(struct drm_device *dev,
303 struct drm_file *file_priv, bool from_open)
[60352]304{
[67395]305 struct vbox_private *vbox = dev->dev_private;
306
307 /*
308 * We do not yet know whether the new owner can handle hotplug, so we
309 * do not advertise dynamic modes on the first query and send a
310 * tentative hotplug notification after that to see if they query again.
311 */
312 vbox->initial_mode_queried = false;
313
314 mutex_lock(&vbox->hw_mutex);
[74581]315 /* Start the refresh timer in case the user does not provide dirty
316 * rectangles. */
317 vbox->need_refresh_timer = true;
318 schedule_delayed_work(&vbox->refresh_work, VBOX_REFRESH_PERIOD);
[67395]319 mutex_unlock(&vbox->hw_mutex);
320
[89690]321#if RTLNX_VER_MAX(5,9,0) && !RTLNX_RHEL_MAJ_PREREQ(8,4) && !RTLNX_SUSE_MAJ_PREREQ(15,3)
[67395]322 return 0;
[86542]323#endif
[60352]324}
325
[85705]326#if RTLNX_VER_MAX(4,8,0) && !RTLNX_RHEL_MAJ_PREREQ(7,4)
[60352]327static void vbox_master_drop(struct drm_device *dev,
[67395]328 struct drm_file *file_priv, bool from_release)
[63755]329#else
[67395]330static void vbox_master_drop(struct drm_device *dev, struct drm_file *file_priv)
[63755]331#endif
[60352]332{
[67395]333 struct vbox_private *vbox = dev->dev_private;
334
335 /* See vbox_master_set() */
336 vbox->initial_mode_queried = false;
[74963]337 vbox_report_caps(vbox);
[67395]338
339 mutex_lock(&vbox->hw_mutex);
[74581]340 vbox->need_refresh_timer = false;
[67395]341 mutex_unlock(&vbox->hw_mutex);
[60352]342}
343
[67395]344static struct drm_driver driver = {
[89690]345#if RTLNX_VER_MAX(5,4,0) && !RTLNX_RHEL_MAJ_PREREQ(8,3) && !RTLNX_SUSE_MAJ_PREREQ(15,3)
[86196]346 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_HAVE_IRQ |
[85705]347# if RTLNX_VER_MAX(5,1,0) && !RTLNX_RHEL_MAJ_PREREQ(8,1)
[77850]348 DRIVER_IRQ_SHARED |
[85705]349# endif
[67395]350 DRIVER_PRIME,
[89690]351#else /* >= 5.4.0 && RHEL >= 8.3 && SLES >= 15-SP3 */
[88274]352 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_HAVE_IRQ,
[86174]353#endif /* < 5.4.0 */
[48115]354
[86196]355#if RTLNX_VER_MAX(4,19,0) && !RTLNX_RHEL_MAJ_PREREQ(8,3)
[88274]356 /* Legacy hooks, but still supported. */
[67395]357 .load = vbox_driver_load,
358 .unload = vbox_driver_unload,
[76976]359#endif
[67395]360 .lastclose = vbox_driver_lastclose,
361 .master_set = vbox_master_set,
362 .master_drop = vbox_master_drop,
[85705]363#if RTLNX_VER_MIN(3,18,0) || RTLNX_RHEL_MAJ_PREREQ(7,2)
[85707]364# if RTLNX_VER_MAX(4,14,0) && !RTLNX_RHEL_MAJ_PREREQ(7,5) && !RTLNX_SUSE_MAJ_PREREQ(15,1) && !RTLNX_SUSE_MAJ_PREREQ(12,5)
[67395]365 .set_busid = drm_pci_set_busid,
[69143]366# endif
[59526]367#endif
[48115]368
[67395]369 .fops = &vbox_fops,
[100677]370#if RTLNX_VER_MAX(5,15,0) && !RTLNX_RHEL_RANGE(8,7, 8,99) && !RTLNX_RHEL_MAJ_PREREQ(9,1) && !RTLNX_SUSE_MAJ_PREREQ(15,5)
[67395]371 .irq_handler = vbox_irq_handler,
[91233]372#endif
[67395]373 .name = DRIVER_NAME,
374 .desc = DRIVER_DESC,
375 .date = DRIVER_DATE,
376 .major = DRIVER_MAJOR,
377 .minor = DRIVER_MINOR,
378 .patchlevel = DRIVER_PATCHLEVEL,
[48115]379
[85704]380#if RTLNX_VER_MAX(4,7,0)
[67395]381 .gem_free_object = vbox_gem_free_object,
[76943]382#endif
[67395]383 .dumb_create = vbox_dumb_create,
384 .dumb_map_offset = vbox_dumb_mmap_offset,
[85705]385#if RTLNX_VER_MAX(3,12,0) && !RTLNX_RHEL_MAJ_PREREQ(7,3)
[67395]386 .dumb_destroy = vbox_dumb_destroy,
[90577]387#elif RTLNX_VER_MAX(5,12,0) && !RTLNX_RHEL_MAJ_PREREQ(8,5)
[67395]388 .dumb_destroy = drm_gem_dumb_destroy,
[59568]389#endif
[102874]390#if RTLNX_VER_MAX(6,6,0) && !RTLNX_RHEL_RANGE(9,4, 9,99)
[67395]391 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
392 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
[101079]393#endif
[88207]394 .gem_prime_import = drm_gem_prime_import,
395 .gem_prime_import_sg_table = vbox_gem_prime_import_sg_table,
[102874]396#if RTLNX_VER_MAX(6,6,0) && !RTLNX_RHEL_RANGE(9,4, 9,99)
[88207]397 .gem_prime_mmap = vbox_gem_prime_mmap,
[101079]398#endif
[88207]399
[90577]400#if RTLNX_VER_MAX(5,11,0) && !RTLNX_RHEL_MAJ_PREREQ(8,5)
[88207]401 .dev_priv_size = 0,
[88212]402# if RTLNX_VER_MIN(4,7,0)
[88207]403 .gem_free_object_unlocked = vbox_gem_free_object,
[88212]404# endif
[67395]405 .gem_prime_export = drm_gem_prime_export,
406 .gem_prime_pin = vbox_gem_prime_pin,
407 .gem_prime_unpin = vbox_gem_prime_unpin,
408 .gem_prime_get_sg_table = vbox_gem_prime_get_sg_table,
409 .gem_prime_vmap = vbox_gem_prime_vmap,
410 .gem_prime_vunmap = vbox_gem_prime_vunmap,
[88207]411#endif
[48115]412};
413
414static int __init vbox_init(void)
415{
[88510]416 printk("vboxvideo: loading version " VBOX_VERSION_STRING " r" __stringify(VBOX_SVN_REV) "\n");
[93416]417 if (VBOX_VIDEO_NOMODESET())
[89689]418 {
419 printk("vboxvideo: kernel is running with *nomodeset* parameter,\n");
420 printk("vboxvideo: please consider either to remove it or load driver\n");
421 printk("vboxvideo: with parameter modeset=1, unloading\n");
[67395]422 return -EINVAL;
[89689]423 }
[48115]424
[67395]425 if (vbox_modeset == 0)
[89689]426 {
427 printk("vboxvideo: driver loaded with modeset=0 parameter, unloading\n");
[67395]428 return -EINVAL;
[89689]429 }
[60104]430
[85705]431#if RTLNX_VER_MIN(3,18,0) || RTLNX_RHEL_MAJ_PREREQ(7,3)
[69143]432 return pci_register_driver(&vbox_pci_driver);
[79690]433#else
434 return drm_pci_init(&driver, &vbox_pci_driver);
435#endif
[48115]436}
[67395]437
[48115]438static void __exit vbox_exit(void)
439{
[85705]440#if RTLNX_VER_MIN(3,18,0) || RTLNX_RHEL_MAJ_PREREQ(7,3)
[69143]441 pci_unregister_driver(&vbox_pci_driver);
[79690]442#else
443 drm_pci_exit(&driver, &vbox_pci_driver);
444#endif
[48115]445}
446
447module_init(vbox_init);
448module_exit(vbox_exit);
449
450MODULE_AUTHOR(DRIVER_AUTHOR);
451MODULE_DESCRIPTION(DRIVER_DESC);
452MODULE_LICENSE("GPL and additional rights");
[60584]453#ifdef MODULE_VERSION
[67177]454MODULE_VERSION(VBOX_VERSION_STRING " r" __stringify(VBOX_SVN_REV));
[60584]455#endif
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use