Skip to content

Commit

Permalink
vgaarb: Fix VGA decodes changes
Browse files Browse the repository at this point in the history
When VGA decodes change we need to do a bit more evaluation of exactly what
has changed.  We don't necessarily give up all the old owns resources and
we need to account for resources with locks.  The new algorithm is: If
something is added, update decodes.  If legacy resources were added and
none were there before, we have a new participant.  If something is
removed, update decodes.  If we previously owned it, we no longer own it.
If it was previously locked, invalidate all locks and release it.  If
legacy resources were removed and none are left, remove the participant
from VGA arbitration.

Previously we updated decodes, released ownership of everything that was
previously decoded, ignored all locks, and went off looking for another
device to transfer VGA to.  In a test case where Intel IGD removes only
legacy VGA memory decoding, this left the arbiter switching to discrete
graphics without actually disabling legacy VGA IO from the IGD.  As a
bonus, we bumped up the count of VGA arbitration participants for no
good reason.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Cc: Dave Airlie <airlied@redhat.com>
Acked-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
[danvet: Kill now unused variables, reported by the 0-day kernel
builtbot.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
  • Loading branch information
Alex Williamson authored and Daniel Vetter committed Sep 3, 2013
1 parent f22d776 commit 5c0f6ee
Showing 1 changed file with 17 additions and 24 deletions.
41 changes: 17 additions & 24 deletions drivers/gpu/vga/vgaarb.c
Original file line number Diff line number Diff line change
Expand Up @@ -644,10 +644,12 @@ static bool vga_arbiter_del_pci_device(struct pci_dev *pdev)
static inline void vga_update_device_decodes(struct vga_device *vgadev,
int new_decodes)
{
int old_decodes;
struct vga_device *new_vgadev, *conflict;
int old_decodes, decodes_removed, decodes_unlocked;

old_decodes = vgadev->decodes;
decodes_removed = ~new_decodes & old_decodes;
decodes_unlocked = vgadev->locks & decodes_removed;
vgadev->owns &= ~decodes_removed;
vgadev->decodes = new_decodes;

pr_info("vgaarb: device changed decodes: PCI:%s,olddecodes=%s,decodes=%s:owns=%s\n",
Expand All @@ -656,31 +658,22 @@ static inline void vga_update_device_decodes(struct vga_device *vgadev,
vga_iostate_to_str(vgadev->decodes),
vga_iostate_to_str(vgadev->owns));


/* if we own the decodes we should move them along to
another card */
if ((vgadev->owns & old_decodes) && (vga_count > 1)) {
/* set us to own nothing */
vgadev->owns &= ~old_decodes;
list_for_each_entry(new_vgadev, &vga_list, list) {
if ((new_vgadev != vgadev) &&
(new_vgadev->decodes & VGA_RSRC_LEGACY_MASK)) {
pr_info("vgaarb: transferring owner from PCI:%s to PCI:%s\n", pci_name(vgadev->pdev), pci_name(new_vgadev->pdev));
conflict = __vga_tryget(new_vgadev, VGA_RSRC_LEGACY_MASK);
if (!conflict)
__vga_put(new_vgadev, VGA_RSRC_LEGACY_MASK);
break;
}
}
/* if we removed locked decodes, lock count goes to zero, and release */
if (decodes_unlocked) {
if (decodes_unlocked & VGA_RSRC_LEGACY_IO)
vgadev->io_lock_cnt = 0;
if (decodes_unlocked & VGA_RSRC_LEGACY_MEM)
vgadev->mem_lock_cnt = 0;
__vga_put(vgadev, decodes_unlocked);
}

/* change decodes counter */
if (old_decodes != new_decodes) {
if (new_decodes & (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM))
vga_decode_count++;
else
vga_decode_count--;
}
if (old_decodes & VGA_RSRC_LEGACY_MASK &&
!(new_decodes & VGA_RSRC_LEGACY_MASK))
vga_decode_count--;
if (!(old_decodes & VGA_RSRC_LEGACY_MASK) &&
new_decodes & VGA_RSRC_LEGACY_MASK)
vga_decode_count++;
pr_debug("vgaarb: decoding count now is: %d\n", vga_decode_count);
}

Expand Down

0 comments on commit 5c0f6ee

Please sign in to comment.