diff options
Diffstat (limited to 'drivers/gpu/vga/vgaarb.c')
| -rw-r--r-- | drivers/gpu/vga/vgaarb.c | 87 |
1 files changed, 41 insertions, 46 deletions
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c index 111d956d8e7..af025970835 100644 --- a/drivers/gpu/vga/vgaarb.c +++ b/drivers/gpu/vga/vgaarb.c @@ -136,6 +136,17 @@ struct pci_dev *vga_default_device(void) { return vga_default; } + +EXPORT_SYMBOL_GPL(vga_default_device); + +void vga_set_default_device(struct pci_dev *pdev) +{ + if (vga_default == pdev) + return; + + pci_dev_put(vga_default); + vga_default = pci_dev_get(pdev); +} #endif static inline void vga_irq_set_state(struct vga_device *vgadev, bool state) @@ -246,9 +257,9 @@ static struct vga_device *__vga_tryget(struct vga_device *vgadev, if (!conflict->bridge_has_one_vga) { vga_irq_set_state(conflict, false); flags |= PCI_VGA_STATE_CHANGE_DECODES; - if (lwants & (VGA_RSRC_LEGACY_MEM|VGA_RSRC_NORMAL_MEM)) + if (match & (VGA_RSRC_LEGACY_MEM|VGA_RSRC_NORMAL_MEM)) pci_bits |= PCI_COMMAND_MEMORY; - if (lwants & (VGA_RSRC_LEGACY_IO|VGA_RSRC_NORMAL_IO)) + if (match & (VGA_RSRC_LEGACY_IO|VGA_RSRC_NORMAL_IO)) pci_bits |= PCI_COMMAND_IO; } @@ -256,11 +267,11 @@ static struct vga_device *__vga_tryget(struct vga_device *vgadev, flags |= PCI_VGA_STATE_CHANGE_BRIDGE; pci_set_vga_state(conflict->pdev, false, pci_bits, flags); - conflict->owns &= ~lwants; + conflict->owns &= ~match; /* If he also owned non-legacy, that is no longer the case */ - if (lwants & VGA_RSRC_LEGACY_MEM) + if (match & VGA_RSRC_LEGACY_MEM) conflict->owns &= ~VGA_RSRC_NORMAL_MEM; - if (lwants & VGA_RSRC_LEGACY_IO) + if (match & VGA_RSRC_LEGACY_IO) conflict->owns &= ~VGA_RSRC_NORMAL_IO; } @@ -570,7 +581,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev) #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE if (vga_default == NULL && ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK)) - vga_default = pci_dev_get(pdev); + vga_set_default_device(pdev); #endif vga_arbiter_check_bridge_sharing(vgadev); @@ -605,10 +616,10 @@ static bool vga_arbiter_del_pci_device(struct pci_dev *pdev) goto bail; } - if (vga_default == pdev) { - pci_dev_put(vga_default); - vga_default = NULL; - } +#ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE + if (vga_default == pdev) + vga_set_default_device(NULL); +#endif if (vgadev->decodes & (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM)) vga_decode_count--; @@ -633,10 +644,12 @@ bail: 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", @@ -645,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); } @@ -1057,7 +1061,6 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf, } } else if (strncmp(curr_pos, "target ", 7) == 0) { - struct pci_bus *pbus; unsigned int domain, bus, devfn; struct vga_device *vgadev; @@ -1076,19 +1079,11 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf, pr_debug("vgaarb: %s ==> %x:%x:%x.%x\n", curr_pos, domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); - pbus = pci_find_bus(domain, bus); - pr_debug("vgaarb: pbus %p\n", pbus); - if (pbus == NULL) { - pr_err("vgaarb: invalid PCI domain and/or bus address %x:%x\n", - domain, bus); - ret_val = -ENODEV; - goto done; - } - pdev = pci_get_slot(pbus, devfn); + pdev = pci_get_domain_bus_and_slot(domain, bus, devfn); pr_debug("vgaarb: pdev %p\n", pdev); if (!pdev) { - pr_err("vgaarb: invalid PCI address %x:%x\n", - bus, devfn); + pr_err("vgaarb: invalid PCI address %x:%x:%x\n", + domain, bus, devfn); ret_val = -ENODEV; goto done; } |
