Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 28d52043 authored by Dave Airlie's avatar Dave Airlie
Browse files

drm/vgaarb: add VGA arbitration support to the drm and kms.



VGA arb requires DRM support for non-kms drivers, to turn on/off
irqs when disabling the mem/io regions.

VGA arb requires KMS support for GPUs where we can turn off VGA
decoding. Currently we know how to do this for intel and radeon
kms drivers, which allows them to be removed from the arbiter.

This patch comes from Fedora rawhide kernel.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent aadd4e17
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@

#include <linux/interrupt.h>	/* For task queue support */

#include <linux/vgaarb.h>
/**
 * Get interrupt from bus id.
 *
@@ -171,6 +172,26 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
}
EXPORT_SYMBOL(drm_vblank_init);

static void drm_irq_vgaarb_nokms(void *cookie, bool state)
{
	struct drm_device *dev = cookie;

	if (dev->driver->vgaarb_irq) {
		dev->driver->vgaarb_irq(dev, state);
		return;
	}

	if (!dev->irq_enabled)
		return;

	if (state)
		dev->driver->irq_uninstall(dev);
	else {
		dev->driver->irq_preinstall(dev);
		dev->driver->irq_postinstall(dev);
	}
}

/**
 * Install IRQ handler.
 *
@@ -231,6 +252,9 @@ int drm_irq_install(struct drm_device *dev)
		return ret;
	}

	if (!drm_core_check_feature(dev, DRIVER_MODESET))
		vga_client_register(dev->pdev, (void *)dev, drm_irq_vgaarb_nokms, NULL);

	/* After installing handler */
	ret = dev->driver->irq_postinstall(dev);
	if (ret < 0) {
@@ -279,6 +303,9 @@ int drm_irq_uninstall(struct drm_device * dev)

	DRM_DEBUG("irq=%d\n", dev->pdev->irq);

	if (!drm_core_check_feature(dev, DRIVER_MODESET))
		vga_client_register(dev->pdev, NULL, NULL, NULL);

	dev->driver->irq_uninstall(dev);

	free_irq(dev->pdev->irq, dev);
+20 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#include "intel_drv.h"
#include "i915_drm.h"
#include "i915_drv.h"
#include <linux/vgaarb.h>

/* Really want an OS-independent resettable timer.  Would like to have
 * this loop run for (eg) 3 sec, but have the timer reset every time
@@ -1012,6 +1013,19 @@ static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size,
	return 0;
}

/* true = enable decode, false = disable decoder */
static unsigned int i915_vga_set_decode(void *cookie, bool state)
{
	struct drm_device *dev = cookie;

	intel_modeset_vga_set_state(dev, state);
	if (state)
		return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
		       VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
	else
		return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
}

static int i915_load_modeset_init(struct drm_device *dev,
				  unsigned long prealloc_size,
				  unsigned long agp_size)
@@ -1057,6 +1071,11 @@ static int i915_load_modeset_init(struct drm_device *dev,
	if (ret)
		DRM_INFO("failed to find VBIOS tables\n");

	/* if we have > 1 VGA cards, then disable the radeon VGA resources */
	ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode);
	if (ret)
		goto destroy_ringbuffer;

	ret = drm_irq_install(dev);
	if (ret)
		goto destroy_ringbuffer;
@@ -1324,6 +1343,7 @@ int i915_driver_unload(struct drm_device *dev)

	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
		drm_irq_uninstall(dev);
		vga_client_register(dev->pdev, NULL, NULL, NULL);
	}

	if (dev->pdev->msi_enabled)
+1 −0
Original line number Diff line number Diff line
@@ -766,6 +766,7 @@ static inline void opregion_enable_asle(struct drm_device *dev) { return; }
/* modesetting */
extern void intel_modeset_init(struct drm_device *dev);
extern void intel_modeset_cleanup(struct drm_device *dev);
extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);

/**
 * Lock test for when it's just for synchronization of ring access.
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
 * fb aperture size and the amount of pre-reserved memory.
 */
#define INTEL_GMCH_CTRL		0x52
#define INTEL_GMCH_VGA_DISABLE  (1 << 1)
#define INTEL_GMCH_ENABLED	0x4
#define INTEL_GMCH_MEM_MASK	0x1
#define INTEL_GMCH_MEM_64M	0x1
+17 −0
Original line number Diff line number Diff line
@@ -3917,3 +3917,20 @@ struct drm_encoder *intel_best_encoder(struct drm_connector *connector)

	return &intel_output->enc;
}

/*
 * set vga decode state - true == enable VGA decode
 */
int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	u16 gmch_ctrl;

	pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &gmch_ctrl);
	if (state)
		gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
	else
		gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
	pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl);
	return 0;
}
Loading