aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/vga/vgaarb.c40
1 files changed, 22 insertions, 18 deletions
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index af0259708358..d2077f040f3e 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -237,12 +237,10 @@ static struct vga_device *__vga_tryget(struct vga_device *vgadev,
237 if (conflict->locks & lwants) 237 if (conflict->locks & lwants)
238 return conflict; 238 return conflict;
239 239
240 /* Ok, now check if he owns the resource we want. We don't need 240 /* Ok, now check if it owns the resource we want. We can
241 * to check "decodes" since it should be impossible to own 241 * lock resources that are not decoded, therefore a device
242 * own legacy resources you don't decode unless I have a bug 242 * can own resources it doesn't decode.
243 * in this code...
244 */ 243 */
245 WARN_ON(conflict->owns & ~conflict->decodes);
246 match = lwants & conflict->owns; 244 match = lwants & conflict->owns;
247 if (!match) 245 if (!match)
248 continue; 246 continue;
@@ -254,13 +252,19 @@ static struct vga_device *__vga_tryget(struct vga_device *vgadev,
254 flags = 0; 252 flags = 0;
255 pci_bits = 0; 253 pci_bits = 0;
256 254
255 /* If we can't control legacy resources via the bridge, we
256 * also need to disable normal decoding.
257 */
257 if (!conflict->bridge_has_one_vga) { 258 if (!conflict->bridge_has_one_vga) {
258 vga_irq_set_state(conflict, false); 259 if ((match & conflict->decodes) & VGA_RSRC_LEGACY_MEM)
259 flags |= PCI_VGA_STATE_CHANGE_DECODES;
260 if (match & (VGA_RSRC_LEGACY_MEM|VGA_RSRC_NORMAL_MEM))
261 pci_bits |= PCI_COMMAND_MEMORY; 260 pci_bits |= PCI_COMMAND_MEMORY;
262 if (match & (VGA_RSRC_LEGACY_IO|VGA_RSRC_NORMAL_IO)) 261 if ((match & conflict->decodes) & VGA_RSRC_LEGACY_IO)
263 pci_bits |= PCI_COMMAND_IO; 262 pci_bits |= PCI_COMMAND_IO;
263
264 if (pci_bits) {
265 vga_irq_set_state(conflict, false);
266 flags |= PCI_VGA_STATE_CHANGE_DECODES;
267 }
264 } 268 }
265 269
266 if (change_bridge) 270 if (change_bridge)
@@ -268,18 +272,19 @@ static struct vga_device *__vga_tryget(struct vga_device *vgadev,
268 272
269 pci_set_vga_state(conflict->pdev, false, pci_bits, flags); 273 pci_set_vga_state(conflict->pdev, false, pci_bits, flags);
270 conflict->owns &= ~match; 274 conflict->owns &= ~match;
271 /* If he also owned non-legacy, that is no longer the case */ 275
272 if (match & VGA_RSRC_LEGACY_MEM) 276 /* If we disabled normal decoding, reflect it in owns */
277 if (pci_bits & PCI_COMMAND_MEMORY)
273 conflict->owns &= ~VGA_RSRC_NORMAL_MEM; 278 conflict->owns &= ~VGA_RSRC_NORMAL_MEM;
274 if (match & VGA_RSRC_LEGACY_IO) 279 if (pci_bits & PCI_COMMAND_IO)
275 conflict->owns &= ~VGA_RSRC_NORMAL_IO; 280 conflict->owns &= ~VGA_RSRC_NORMAL_IO;
276 } 281 }
277 282
278enable_them: 283enable_them:
279 /* ok dude, we got it, everybody conflicting has been disabled, let's 284 /* ok dude, we got it, everybody conflicting has been disabled, let's
280 * enable us. Make sure we don't mark a bit in "owns" that we don't 285 * enable us. Mark any bits in "owns" regardless of whether we
281 * also have in "decodes". We can lock resources we don't decode but 286 * decoded them. We can lock resources we don't decode, therefore
282 * not own them. 287 * we must track them via "owns".
283 */ 288 */
284 flags = 0; 289 flags = 0;
285 pci_bits = 0; 290 pci_bits = 0;
@@ -291,7 +296,7 @@ enable_them:
291 if (wants & (VGA_RSRC_LEGACY_IO|VGA_RSRC_NORMAL_IO)) 296 if (wants & (VGA_RSRC_LEGACY_IO|VGA_RSRC_NORMAL_IO))
292 pci_bits |= PCI_COMMAND_IO; 297 pci_bits |= PCI_COMMAND_IO;
293 } 298 }
294 if (!!(wants & VGA_RSRC_LEGACY_MASK)) 299 if (wants & VGA_RSRC_LEGACY_MASK)
295 flags |= PCI_VGA_STATE_CHANGE_BRIDGE; 300 flags |= PCI_VGA_STATE_CHANGE_BRIDGE;
296 301
297 pci_set_vga_state(vgadev->pdev, true, pci_bits, flags); 302 pci_set_vga_state(vgadev->pdev, true, pci_bits, flags);
@@ -299,7 +304,7 @@ enable_them:
299 if (!vgadev->bridge_has_one_vga) { 304 if (!vgadev->bridge_has_one_vga) {
300 vga_irq_set_state(vgadev, true); 305 vga_irq_set_state(vgadev, true);
301 } 306 }
302 vgadev->owns |= (wants & vgadev->decodes); 307 vgadev->owns |= wants;
303lock_them: 308lock_them:
304 vgadev->locks |= (rsrc & VGA_RSRC_LEGACY_MASK); 309 vgadev->locks |= (rsrc & VGA_RSRC_LEGACY_MASK);
305 if (rsrc & VGA_RSRC_LEGACY_IO) 310 if (rsrc & VGA_RSRC_LEGACY_IO)
@@ -649,7 +654,6 @@ static inline void vga_update_device_decodes(struct vga_device *vgadev,
649 old_decodes = vgadev->decodes; 654 old_decodes = vgadev->decodes;
650 decodes_removed = ~new_decodes & old_decodes; 655 decodes_removed = ~new_decodes & old_decodes;
651 decodes_unlocked = vgadev->locks & decodes_removed; 656 decodes_unlocked = vgadev->locks & decodes_removed;
652 vgadev->owns &= ~decodes_removed;
653 vgadev->decodes = new_decodes; 657 vgadev->decodes = new_decodes;
654 658
655 pr_info("vgaarb: device changed decodes: PCI:%s,olddecodes=%s,decodes=%s:owns=%s\n", 659 pr_info("vgaarb: device changed decodes: PCI:%s,olddecodes=%s,decodes=%s:owns=%s\n",