[Intel-gfx] [PATCH] vgaarb: call pci_disable|enable_device on decoding vga devices
Jani Nikula
jani.nikula at linux.intel.com
Mon Jun 11 10:42:35 CEST 2012
On Fri, 08 Jun 2012, Daniel Vetter <daniel.vetter at ffwll.ch> wrote:
> There's the neat little problem that some systems die if vga decoding
> isn't decoded anywhere, because linux disabled that pci device.
>
> Atm we solve that problem by simple not calling pci_disable_device at
> driver unregister time for drm pci devices. Which isn't to great
> because it leaks a pci_enable_device reference on module reload and
> also is rather inconsistent, since the driver load codcode in
> drm/drm_pci.c _does_ call pci_disable_device on the load error path.
>
> To fix this issue, let the vga arbiter hold a pci_enable_device
> reference on its own when the vga device decodes anything. This leaves
> the issue still open when the vga arbiter isn't loaded/compiled in,
> but I guess since drm module unload is riddled with dragons it's ok to
> say "just don't do this".
>
> Signed-Off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
> ---
> drivers/gpu/vga/vgaarb.c | 27 +++++++++++++++++++++++++--
> 1 files changed, 25 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
> index 3df8fc0..82f19a1 100644
> --- a/drivers/gpu/vga/vgaarb.c
> +++ b/drivers/gpu/vga/vgaarb.c
> @@ -49,7 +49,11 @@
> static void vga_arbiter_notify_clients(void);
> /*
> * We keep a list of all vga devices in the system to speed
> - * up the various operations of the arbiter
> + * up the various operations of the arbiter. Note that vgaarb keeps a
> + * pci_enable_device reference for all vga devices with owns != 0. This is to
> + * avoid drm devices from killing the system when they call pci_disable_device
> + * on module unload (as they should), because some systems don't like it if no
> + * one decodes vga.
> */
> struct vga_device {
> struct list_head list;
> @@ -171,7 +175,7 @@ static struct vga_device *__vga_tryget(struct vga_device *vgadev,
> {
> unsigned int wants, legacy_wants, match;
> struct vga_device *conflict;
> - unsigned int pci_bits;
> + unsigned int pci_bits, ret;
> u32 flags = 0;
>
> /* Account for "normal" resources to lock. If we decode the legacy,
> @@ -264,6 +268,10 @@ static struct vga_device *__vga_tryget(struct vga_device *vgadev,
>
> pci_set_vga_state(conflict->pdev, false, pci_bits, flags);
> conflict->owns &= ~lwants;
> +
> + if (conflict->owns == 0)
> + pci_disable_device(conflict->pdev);
> +
> /* If he also owned non-legacy, that is no longer the case */
> if (lwants & VGA_RSRC_LEGACY_MEM)
> conflict->owns &= ~VGA_RSRC_NORMAL_MEM;
> @@ -290,6 +298,12 @@ enable_them:
> if (!!(wants & VGA_RSRC_LEGACY_MASK))
> flags |= PCI_VGA_STATE_CHANGE_BRIDGE;
>
> + if (vgadev->owns == 0) {
> + ret = pci_enable_device(vgadev->pdev);
> + if (ret)
> + return ERR_PTR(ret);
Hi Daniel, I think unsigned ret will result in a positive ERR_PTR, which
won't be caught by IS_ERR_VALUE(). (Either that, or I need more coffee
to get the promotion rules right. Better use signed int no matter what.)
BR,
Jani.
> + }
> +
> pci_set_vga_state(vgadev->pdev, true, pci_bits, flags);
>
> if (!vgadev->bridge_has_one_vga) {
> @@ -376,6 +390,8 @@ int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible)
> if (conflict == NULL)
> break;
>
> + if (IS_ERR(conflict))
> + return PTR_ERR(conflict);
>
> /* We have a conflict, we wait until somebody kicks the
> * work queue. Currently we have one work queue that we
> @@ -513,6 +529,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
> unsigned long flags;
> struct pci_bus *bus;
> struct pci_dev *bridge;
> + int ret;
> u16 cmd;
>
> /* Only deal with VGA class devices */
> @@ -582,6 +599,12 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
>
> vga_arbiter_check_bridge_sharing(vgadev);
>
> + if (vgadev->owns != 0) {
> + ret = pci_enable_device(vgadev->pdev);
> + if (ret)
> + goto fail;
> + }
> +
> /* Add to the list */
> list_add(&vgadev->list, &vga_list);
> vga_count++;
> --
> 1.7.7.6
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
More information about the Intel-gfx
mailing list