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

Commit eda1be63 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
  drm/i915: Move legacy breadcrumb out of the reserved status page area
  drm/i915: Filter pci devices based on PCI_CLASS_DISPLAY_VGA
  drm/radeon: map registers at load time
  drm: Remove infrastructure for supporting i915's vblank swapping.
  i915: Remove racy delayed vblank swap ioctl.
  i915: Don't whine when pci_enable_msi() fails.
  i915: Don't attempt to short-circuit object_wait_rendering by checking domains.
  i915: Clean up sarea pointers on leavevt
  i915: Save/restore MCHBAR_RENDER_STANDBY on GM965/GM45
parents 5da38d32 0baf823a
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -266,11 +266,19 @@ int drm_init(struct drm_driver *driver)
	for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
		pid = (struct pci_device_id *)&driver->pci_driver.id_table[i];

		/* Loop around setting up a DRM device for each PCI device
		 * matching our ID and device class.  If we had the internal
		 * function that pci_get_subsys and pci_get_class used, we'd
		 * be able to just pass pid in instead of doing a two-stage
		 * thing.
		 */
		pdev = NULL;
		/* pass back in pdev to account for multiple identical cards */
		while ((pdev =
			pci_get_subsys(pid->vendor, pid->device, pid->subvendor,
				       pid->subdevice, pdev)) != NULL) {
			if ((pdev->class & pid->class_mask) != pid->class)
				continue;

			/* stealth mode requires a manual probe */
			pci_dev_get(pdev);
			drm_get_dev(pdev, pid, driver);
+0 −80
Original line number Diff line number Diff line
@@ -280,8 +280,6 @@ int drm_irq_uninstall(struct drm_device * dev)

	drm_vblank_cleanup(dev);

	dev->locked_tasklet_func = NULL;

	return 0;
}
EXPORT_SYMBOL(drm_irq_uninstall);
@@ -699,81 +697,3 @@ void drm_handle_vblank(struct drm_device *dev, int crtc)
	drm_vbl_send_signals(dev, crtc);
}
EXPORT_SYMBOL(drm_handle_vblank);

/**
 * Tasklet wrapper function.
 *
 * \param data DRM device in disguise.
 *
 * Attempts to grab the HW lock and calls the driver callback on success. On
 * failure, leave the lock marked as contended so the callback can be called
 * from drm_unlock().
 */
static void drm_locked_tasklet_func(unsigned long data)
{
	struct drm_device *dev = (struct drm_device *)data;
	unsigned long irqflags;
	void (*tasklet_func)(struct drm_device *);
	
	spin_lock_irqsave(&dev->tasklet_lock, irqflags);
	tasklet_func = dev->locked_tasklet_func;
	spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);

	if (!tasklet_func ||
	    !drm_lock_take(&dev->lock,
			   DRM_KERNEL_CONTEXT)) {
		return;
	}

	dev->lock.lock_time = jiffies;
	atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);

	spin_lock_irqsave(&dev->tasklet_lock, irqflags);
	tasklet_func = dev->locked_tasklet_func;
	dev->locked_tasklet_func = NULL;
	spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
	
	if (tasklet_func != NULL)
		tasklet_func(dev);

	drm_lock_free(&dev->lock,
		      DRM_KERNEL_CONTEXT);
}

/**
 * Schedule a tasklet to call back a driver hook with the HW lock held.
 *
 * \param dev DRM device.
 * \param func Driver callback.
 *
 * This is intended for triggering actions that require the HW lock from an
 * interrupt handler. The lock will be grabbed ASAP after the interrupt handler
 * completes. Note that the callback may be called from interrupt or process
 * context, it must not make any assumptions about this. Also, the HW lock will
 * be held with the kernel context or any client context.
 */
void drm_locked_tasklet(struct drm_device *dev, void (*func)(struct drm_device *))
{
	unsigned long irqflags;
	static DECLARE_TASKLET(drm_tasklet, drm_locked_tasklet_func, 0);

	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ) ||
	    test_bit(TASKLET_STATE_SCHED, &drm_tasklet.state))
		return;

	spin_lock_irqsave(&dev->tasklet_lock, irqflags);

	if (dev->locked_tasklet_func) {
		spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
		return;
	}

	dev->locked_tasklet_func = func;

	spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);

	drm_tasklet.data = (unsigned long)dev;

	tasklet_hi_schedule(&drm_tasklet);
}
EXPORT_SYMBOL(drm_locked_tasklet);
+0 −9
Original line number Diff line number Diff line
@@ -154,8 +154,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
	struct drm_lock *lock = data;
	unsigned long irqflags;
	void (*tasklet_func)(struct drm_device *);

	if (lock->context == DRM_KERNEL_CONTEXT) {
		DRM_ERROR("Process %d using kernel context %d\n",
@@ -163,13 +161,6 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
		return -EINVAL;
	}

	spin_lock_irqsave(&dev->tasklet_lock, irqflags);
	tasklet_func = dev->locked_tasklet_func;
	dev->locked_tasklet_func = NULL;
	spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
	if (tasklet_func != NULL)
		tasklet_func(dev);

	atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);

	/* kernel_context_switch isn't used by any of the x86 drm
+0 −1
Original line number Diff line number Diff line
@@ -92,7 +92,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,

	spin_lock_init(&dev->count_lock);
	spin_lock_init(&dev->drw_lock);
	spin_lock_init(&dev->tasklet_lock);
	spin_lock_init(&dev->lock.spinlock);
	init_timer(&dev->timer);
	mutex_init(&dev->struct_mutex);
+8 −8
Original line number Diff line number Diff line
@@ -154,6 +154,9 @@ static int i915_dma_cleanup(struct drm_device * dev)
	if (I915_NEED_GFX_HWS(dev))
		i915_free_hws(dev);

	dev_priv->sarea = NULL;
	dev_priv->sarea_priv = NULL;

	return 0;
}

@@ -442,7 +445,7 @@ static void i915_emit_breadcrumb(struct drm_device *dev)

	BEGIN_LP_RING(4);
	OUT_RING(MI_STORE_DWORD_INDEX);
	OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT);
	OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
	OUT_RING(dev_priv->counter);
	OUT_RING(0);
	ADVANCE_LP_RING();
@@ -573,7 +576,7 @@ static int i915_dispatch_flip(struct drm_device * dev)

	BEGIN_LP_RING(4);
	OUT_RING(MI_STORE_DWORD_INDEX);
	OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT);
	OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
	OUT_RING(dev_priv->counter);
	OUT_RING(0);
	ADVANCE_LP_RING();
@@ -608,7 +611,6 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
			    struct drm_file *file_priv)
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
	u32 *hw_status = dev_priv->hw_status_page;
	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
	    dev_priv->sarea_priv;
	drm_i915_batchbuffer_t *batch = data;
@@ -634,7 +636,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
	mutex_unlock(&dev->struct_mutex);

	if (sarea_priv)
		sarea_priv->last_dispatch = (int)hw_status[5];
		sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
	return ret;
}

@@ -642,7 +644,6 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
			  struct drm_file *file_priv)
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
	u32 *hw_status = dev_priv->hw_status_page;
	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
	    dev_priv->sarea_priv;
	drm_i915_cmdbuffer_t *cmdbuf = data;
@@ -670,7 +671,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
	}

	if (sarea_priv)
		sarea_priv->last_dispatch = (int)hw_status[5];
		sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
	return 0;
}

@@ -849,8 +850,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
	 * be lost or delayed
	 */
	if (!IS_I945G(dev) && !IS_I945GM(dev) && !IS_I965GM(dev))
		if (pci_enable_msi(dev->pdev))
			DRM_ERROR("failed to enable MSI\n");
		pci_enable_msi(dev->pdev);

	intel_opregion_init(dev);

Loading