VirtualBox

source: vbox/trunk/src/VBox/Additions/linux/drm/vbox_irq.c@ 69496

最後變更 在這個檔案從69496是 69083,由 vboxsync 提交於 7 年 前

Additions/linux/drm: Fix reporting invalid suggested-offset-properties.
bugref:8524: Additions/linux: play nicely with distribution-installed Additions

The x and y hints receives from the host are unsigned 32 bit integers and
they get set to -1 (0xffffffff) when invalid. Before this commit the
vboxvideo driver was storing them in an u16 causing the -1 to be truncated
to 65535 which, once reported to userspace, was breaking gnome 3.26+
in Wayland mode.

This commit stores the host values in 32 bit variables, removing the
truncation and checks for -1, replacing it with 0 as -1 is not a valid
suggested-offset-property value. Likewise the properties are now
initialized to 0 instead of -1, since -1 is not a valid value.
This fixes gnome 3.26+ in Wayland mode not working with the vboxvideo
driver.

Reported-by: Gianfranco Costamagna <locutusofborg@…>
Signed-off-by: Hans de Goede <hdegoede@…>

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 6.5 KB
 
1/* $Id: vbox_irq.c 69083 2017-10-13 16:03:36Z vboxsync $ */
2/** @file
3 * VirtualBox Additions Linux kernel video driver
4 */
5
6/*
7 * Copyright (C) 2016-2017 Oracle Corporation
8 * This file is based on qxl_irq.c
9 * Copyright 2013 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 "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
25 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 *
29 * Authors: Dave Airlie
30 * Alon Levy
31 * Michael Thayer <[email protected],
32 * Hans de Goede <[email protected]>
33 */
34
35#include "vbox_drv.h"
36
37#include <VBoxVideo.h>
38
39#include <drm/drm_crtc_helper.h>
40
41static void vbox_clear_irq(void)
42{
43 outl((u32)~0, VGA_PORT_HGSMI_HOST);
44}
45
46static u32 vbox_get_flags(struct vbox_private *vbox)
47{
48 return readl(vbox->guest_heap + HOST_FLAGS_OFFSET);
49}
50
51void vbox_report_hotplug(struct vbox_private *vbox)
52{
53 schedule_work(&vbox->hotplug_work);
54}
55
56irqreturn_t vbox_irq_handler(int irq, void *arg)
57{
58 struct drm_device *dev = (struct drm_device *)arg;
59 struct vbox_private *vbox = (struct vbox_private *)dev->dev_private;
60 u32 host_flags = vbox_get_flags(vbox);
61
62 if (!(host_flags & HGSMIHOSTFLAGS_IRQ))
63 return IRQ_NONE;
64
65 /*
66 * Due to a bug in the initial host implementation of hot-plug irqs,
67 * the hot-plug and cursor capability flags were never cleared.
68 * Fortunately we can tell when they would have been set by checking
69 * that the VSYNC flag is not set.
70 */
71 if (host_flags &
72 (HGSMIHOSTFLAGS_HOTPLUG | HGSMIHOSTFLAGS_CURSOR_CAPABILITIES) &&
73 !(host_flags & HGSMIHOSTFLAGS_VSYNC))
74 vbox_report_hotplug(vbox);
75
76 vbox_clear_irq();
77
78 return IRQ_HANDLED;
79}
80
81/**
82 * Check that the position hints provided by the host are suitable for GNOME
83 * shell (i.e. all screens disjoint and hints for all enabled screens) and if
84 * not replace them with default ones. Providing valid hints improves the
85 * chances that we will get a known screen layout for pointer mapping.
86 */
87static void validate_or_set_position_hints(struct vbox_private *vbox)
88{
89 int i, j;
90 u16 currentx = 0;
91 bool valid = true;
92
93 for (i = 0; i < vbox->num_crtcs; ++i) {
94 for (j = 0; j < i; ++j) {
95 struct VBVAMODEHINT *hintsi = &vbox->last_mode_hints[i];
96 struct VBVAMODEHINT *hintsj = &vbox->last_mode_hints[j];
97
98 if (hintsi->fEnabled && hintsj->fEnabled) {
99 if (hintsi->dx >= 0xffff ||
100 hintsi->dy >= 0xffff ||
101 hintsj->dx >= 0xffff ||
102 hintsj->dy >= 0xffff ||
103 (hintsi->dx <
104 hintsj->dx + (hintsj->cx & 0x8fff) &&
105 hintsi->dx + (hintsi->cx & 0x8fff) >
106 hintsj->dx) ||
107 (hintsi->dy <
108 hintsj->dy + (hintsj->cy & 0x8fff) &&
109 hintsi->dy + (hintsi->cy & 0x8fff) >
110 hintsj->dy))
111 valid = false;
112 }
113 }
114 }
115 if (!valid)
116 for (i = 0; i < vbox->num_crtcs; ++i) {
117 if (vbox->last_mode_hints[i].fEnabled) {
118 vbox->last_mode_hints[i].dx = currentx;
119 vbox->last_mode_hints[i].dy = 0;
120 currentx +=
121 vbox->last_mode_hints[i].cx & 0x8fff;
122 }
123 }
124}
125
126/**
127 * Query the host for the most recent video mode hints.
128 */
129static void vbox_update_mode_hints(struct vbox_private *vbox)
130{
131 struct drm_device *dev = vbox->dev;
132 struct drm_connector *connector;
133 struct vbox_connector *vbox_connector;
134 struct VBVAMODEHINT *hints;
135 u16 flags;
136 bool disconnected;
137 unsigned int crtc_id;
138 int rc;
139
140 rc = VBoxHGSMIGetModeHints(vbox->guest_pool, vbox->num_crtcs,
141 vbox->last_mode_hints);
142 if (RT_FAILURE(rc)) {
143 DRM_ERROR("vboxvideo: VBoxHGSMIGetModeHints failed, rc=%i.\n",
144 rc);
145 return;
146 }
147 validate_or_set_position_hints(vbox);
148#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
149 drm_modeset_lock_all(dev);
150#else
151 mutex_lock(&dev->mode_config.mutex);
152#endif
153 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
154 vbox_connector = to_vbox_connector(connector);
155 hints =
156 &vbox->last_mode_hints[vbox_connector->vbox_crtc->crtc_id];
157 if (hints->magic == VBVAMODEHINT_MAGIC) {
158 disconnected = !(hints->fEnabled);
159 crtc_id = vbox_connector->vbox_crtc->crtc_id;
160 flags = VBVA_SCREEN_F_ACTIVE
161 | (disconnected ? VBVA_SCREEN_F_DISABLED :
162 VBVA_SCREEN_F_BLANK);
163 vbox_connector->mode_hint.width = hints->cx;
164 vbox_connector->mode_hint.height = hints->cy;
165 vbox_connector->vbox_crtc->x_hint = hints->dx;
166 vbox_connector->vbox_crtc->y_hint = hints->dy;
167 vbox_connector->mode_hint.disconnected = disconnected;
168 if (vbox_connector->vbox_crtc->disconnected !=
169 disconnected) {
170 VBoxHGSMIProcessDisplayInfo(vbox->guest_pool,
171 crtc_id, 0, 0, 0,
172 hints->cx * 4,
173 hints->cx,
174 hints->cy, 0,
175 flags);
176 vbox_connector->vbox_crtc->disconnected =
177 disconnected;
178 }
179 }
180 }
181#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
182 drm_modeset_unlock_all(dev);
183#else
184 mutex_unlock(&dev->mode_config.mutex);
185#endif
186}
187
188static void vbox_hotplug_worker(struct work_struct *work)
189{
190 struct vbox_private *vbox = container_of(work, struct vbox_private,
191 hotplug_work);
192
193 vbox_update_mode_hints(vbox);
194 drm_kms_helper_hotplug_event(vbox->dev);
195}
196
197int vbox_irq_init(struct vbox_private *vbox)
198{
199 int ret;
200
201 vbox_update_mode_hints(vbox);
202#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) || defined(RHEL_73)
203 ret = drm_irq_install(vbox->dev, vbox->dev->pdev->irq);
204#else
205 ret = drm_irq_install(vbox->dev);
206#endif
207 if (unlikely(ret != 0)) {
208 vbox_irq_fini(vbox);
209 DRM_ERROR("Failed installing irq: %d\n", ret);
210 return 1;
211 }
212 INIT_WORK(&vbox->hotplug_work, vbox_hotplug_worker);
213 vbox->isr_installed = true;
214 return 0;
215}
216
217void vbox_irq_fini(struct vbox_private *vbox)
218{
219 if (vbox->isr_installed) {
220 drm_irq_uninstall(vbox->dev);
221 flush_work(&vbox->hotplug_work);
222 vbox->isr_installed = false;
223 }
224}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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