Merge remote branch 'origin/master' into modesetting-gem
authorDave Airlie <airlied@redhat.com>
Fri, 26 Sep 2008 05:37:21 +0000 (15:37 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 30 Sep 2008 04:13:49 +0000 (14:13 +1000)
Conflicts:

libdrm/Makefile.am
libdrm/dri_bufmgr.h
linux-core/drm_irq.c
linux-core/drm_sysfs.c
linux-core/drm_ttm.c
shared-core/i915_dma.c
shared-core/i915_irq.c
shared-core/nouveau_drv.h
shared-core/radeon_cp.c

19 files changed:
1  2 
libdrm/Makefile.am
libdrm/intel/intel_bufmgr_fake.c
libdrm/intel/intel_bufmgr_gem.c
libdrm/xf86drm.c
linux-core/Makefile
linux-core/drm_irq.c
linux-core/drm_lock.c
linux-core/drm_memory.c
linux-core/drm_sysfs.c
shared-core/Makefile.am
shared-core/drm.h
shared-core/i915_dma.c
shared-core/i915_drv.h
shared-core/i915_init.c
shared-core/i915_irq.c
shared-core/nouveau_drv.h
shared-core/nouveau_state.c
shared-core/radeon_cp.c
tests/Makefile.am

@@@ -26,10 -26,9 +26,10 @@@ libdrm_la_LDFLAGS = -version-number 2:3
  
  AM_CFLAGS = -I$(top_srcdir)/shared-core
  libdrm_la_SOURCES = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c \
-       xf86drmMode.c dri_bufmgr.c libdrm_lists.h
 -      libdrm_lists.h
++      xf86drmMode.c
 +libdrm_la_LIBADD = intel/libdrm_intel.la
  
  libdrmincludedir = ${includedir}
- libdrminclude_HEADERS = xf86drm.h xf86drmMode.h dri_bufmgr.h
 -libdrminclude_HEADERS = xf86drm.h
++libdrminclude_HEADERS = xf86drm.h xf86drmMode.h
  
  EXTRA_DIST = ChangeLog TODO
Simple merge
@@@ -316,7 -316,6 +316,7 @@@ dri_gem_bo_alloc(dri_bufmgr *bufmgr, co
  
        ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CREATE, &create);
        bo_gem->gem_handle = create.handle;
-       bo_gem->bo.handle = bo_gem->gem_handle;
++      //bo_gem->bo.handle = bo_gem->gem_handle;
        if (ret != 0) {
            free(bo_gem);
            return NULL;
Simple merge
Simple merge
@@@ -841,27 -705,31 +841,31 @@@ static void drm_locked_tasklet_func(uns
  {
        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 (!dev->locked_tasklet_func ||
+       if (!tasklet_func ||
 -          !drm_lock_take(&dev->lock,
 +          !drm_lock_take(&dev->primary->master->lock,
                           DRM_KERNEL_CONTEXT)) {
-               spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
                return;
        }
  
 -      dev->lock.lock_time = jiffies;
 +      dev->primary->master->lock.lock_time = jiffies;
        atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
  
-       dev->locked_tasklet_func(dev);
+       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_lock_free(&dev->primary->master->lock,
                      DRM_KERNEL_CONTEXT);
-       dev->locked_tasklet_func = NULL;
-       spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
  }
  
  /**
@@@ -156,8 -154,8 +156,9 @@@ int drm_lock(struct drm_device *dev, vo
  int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
  {
        struct drm_lock *lock = data;
 +      struct drm_master *master = file_priv->master;
        unsigned long irqflags;
+       void (*tasklet_func)(struct drm_device *);
  
        if (lock->context == DRM_KERNEL_CONTEXT) {
                DRM_ERROR("Process %d using kernel context %d\n",
Simple merge
@@@ -511,7 -188,7 +511,7 @@@ int drm_sysfs_device_add(struct drm_min
  err_out_files:
        if (i > 0)
                for (j = 0; j < i; j++)
-                       device_remove_file(&minor->kdev, &dri_attrs[i]);
 -                      device_remove_file(&minor->kdev, &device_attrs[j]);
++                      device_remove_file(&minor->kdev, &dri_attrs[j]);
        device_unregister(&minor->kdev);
  err_out:
  
@@@ -25,6 -25,6 +25,7 @@@
  klibdrmincludedir = ${includedir}/drm
  klibdrminclude_HEADERS = \
                           drm.h \
++                         drm_mode.h \
                           drm_sarea.h \
                           i915_drm.h \
                           mach64_drm.h \
Simple merge
@@@ -79,10 -125,10 +79,10 @@@ int i915_wait_ring(struct drm_device * 
   */
  void i915_ring_validate(struct drm_device *dev, const char *func, int line)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
        drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
-       u32     tail = I915_READ(LP_RING+RING_TAIL) & HEAD_ADDR;
-       u32     head = I915_READ(LP_RING+RING_HEAD) & HEAD_ADDR;
+       u32     tail = I915_READ(PRB0_TAIL) & HEAD_ADDR;
+       u32     head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
  
        if (tail != ring->tail) {
                DRM_ERROR("%s:%d head sw %x, hw %x. tail sw %x hw %x\n",
@@@ -999,8 -1046,9 +1001,7 @@@ static int i915_set_status_page(struct 
  
        memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
        I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
 -      DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n",
 -                      dev_priv->status_gfx_addr);
        DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
        return 0;
  }
  
@@@ -1023,6 -1226,10 +1024,7 @@@ struct drm_ioctl_desc i915_ioctls[] = 
        DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
        DRM_IOCTL_DEF(DRM_I915_MMIO, i915_mmio, DRM_AUTH),
        DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH),
 -#ifdef I915_HAVE_BUFFER
 -      DRM_IOCTL_DEF(DRM_I915_EXECBUFFER, i915_execbuffer, DRM_AUTH),
 -#endif
+ #ifdef I915_HAVE_GEM
        DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH),
        DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
        DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
@@@ -42,7 -40,9 +42,8 @@@
  #define DRIVER_DATE           "20080730"
  
  #if defined(__linux__)
 -#define I915_HAVE_FENCE
  #define I915_HAVE_BUFFER
+ #define I915_HAVE_GEM
  #endif
  
  /* Interface history:
@@@ -501,6 -475,8 +503,7 @@@ extern int i915_dma_cleanup(struct drm_
  extern int i915_dispatch_batchbuffer(struct drm_device * dev,
                                     drm_i915_batchbuffer_t * batch);
  extern int i915_quiescent(struct drm_device *dev);
 -extern int i915_init_hardware_status(struct drm_device *dev);
+ extern void i915_free_hardware_status(struct drm_device *dev);
  
  int i915_emit_box(struct drm_device * dev,
                  struct drm_clip_rect __user * boxes,
index d638392,0000000..b513379
mode 100644,000000..100644
--- /dev/null
@@@ -1,523 -1,0 +1,552 @@@
- i915_init_hws_phys(struct drm_device *dev)
 +/*
 + * Copyright (c) 2007 Intel Corporation
 + *   Jesse Barnes <jesse.barnes@intel.com>
 + *
 + * Copyright Â© 2002, 2003 David Dawes <dawes@xfree86.org>
 + *                   2004 Sylvain Meyer
 + *
 + * GPL/BSD dual license
 + */
 +#include "drmP.h"
 +#include "drm.h"
 +#include "drm_sarea.h"
 +#include "i915_drm.h"
 +#include "i915_drv.h"
 +#include "intel_bios.h"
 +#include "intel_drv.h"
 +
 +/**
 + * i915_probe_agp - get AGP bootup configuration
 + * @pdev: PCI device
 + * @aperture_size: returns AGP aperture configured size
 + * @preallocated_size: returns size of BIOS preallocated AGP space
 + *
 + * Since Intel integrated graphics are UMA, the BIOS has to set aside
 + * some RAM for the framebuffer at early boot.  This code figures out
 + * how much was set aside so we can use it for our own purposes.
 + */
 +int i915_probe_agp(struct pci_dev *pdev, unsigned long *aperture_size,
 +                 unsigned long *preallocated_size)
 +{
 +      struct pci_dev *bridge_dev;
 +      u16 tmp = 0;
 +      unsigned long overhead;
 +
 +      bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
 +      if (!bridge_dev) {
 +              DRM_ERROR("bridge device not found\n");
 +              return -1;
 +      }
 +
 +      /* Get the fb aperture size and "stolen" memory amount. */
 +      pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);
 +      pci_dev_put(bridge_dev);
 +
 +      *aperture_size = 1024 * 1024;
 +      *preallocated_size = 1024 * 1024;
 +
 +      switch (pdev->device) {
 +      case PCI_DEVICE_ID_INTEL_82830_CGC:
 +      case PCI_DEVICE_ID_INTEL_82845G_IG:
 +      case PCI_DEVICE_ID_INTEL_82855GM_IG:
 +      case PCI_DEVICE_ID_INTEL_82865_IG:
 +              if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M)
 +                      *aperture_size *= 64;
 +              else
 +                      *aperture_size *= 128;
 +              break;
 +      default:
 +              /* 9xx supports large sizes, just look at the length */
 +              *aperture_size = pci_resource_len(pdev, 2);
 +              break;
 +      }
 +
 +      /*
 +       * Some of the preallocated space is taken by the GTT
 +       * and popup.  GTT is 1K per MB of aperture size, and popup is 4K.
 +       */
 +      overhead = (*aperture_size / 1024) + 4096;
 +      switch (tmp & INTEL_855_GMCH_GMS_MASK) {
 +      case INTEL_855_GMCH_GMS_STOLEN_1M:
 +              break; /* 1M already */
 +      case INTEL_855_GMCH_GMS_STOLEN_4M:
 +              *preallocated_size *= 4;
 +              break;
 +      case INTEL_855_GMCH_GMS_STOLEN_8M:
 +              *preallocated_size *= 8;
 +              break;
 +      case INTEL_855_GMCH_GMS_STOLEN_16M:
 +              *preallocated_size *= 16;
 +              break;
 +      case INTEL_855_GMCH_GMS_STOLEN_32M:
 +              *preallocated_size *= 32;
 +              break;
 +      case INTEL_915G_GMCH_GMS_STOLEN_48M:
 +              *preallocated_size *= 48;
 +              break;
 +      case INTEL_915G_GMCH_GMS_STOLEN_64M:
 +              *preallocated_size *= 64;
 +              break;
 +      case INTEL_855_GMCH_GMS_DISABLED:
 +              DRM_ERROR("video memory is disabled\n");
 +              return -1;
 +      default:
 +              DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n",
 +                      tmp & INTEL_855_GMCH_GMS_MASK);
 +              return -1;
 +      }
 +      *preallocated_size -= overhead;
 +
 +      return 0;
 +}
 +
 +static int
-       dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
++i915_init_hardware_status(struct drm_device *dev)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
++      drm_dma_handle_t *dmah;
 +      int ret = 0;
 +
-       if (!dev_priv->status_page_dmah) {
++#ifdef __FreeBSD__
++      DRM_UNLOCK();
++#endif
++      dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
 +                                                 0xffffffff);
-       dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
-       dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
++#ifdef __FreeBSD__
++      DRM_LOCK();
++#endif
++      if (!dmah) {
 +              DRM_ERROR("Can not allocate hardware status page\n");
 +              ret = -ENOMEM;
 +              goto out;
 +      }
-       if (!I915_NEED_GFX_HWS(dev))
-               i915_init_hws_phys(dev);
++      dev_priv->status_page_dmah = dmah;
++      dev_priv->hw_status_page = dmah->vaddr;
++      dev_priv->dma_status_page = dmah->busaddr;
 +
 +      memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
 +
 +      I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
 +      DRM_DEBUG("hws kernel virt: 0x%p\n", dev_priv->hw_status_page);
 +
 +out:
 +      return ret;
 +}
 +
++void i915_free_hardware_status(struct drm_device *dev)
++{
++      struct drm_i915_private *dev_priv = dev->dev_private;
++      if (dev_priv->status_page_dmah) {
++              drm_pci_free(dev, dev_priv->status_page_dmah);
++              dev_priv->status_page_dmah = NULL;
++              /* Need to rewrite hardware status page */
++              I915_WRITE(0x02080, 0x1ffff000);
++      }
++
++      if (dev_priv->status_gfx_addr) {
++              dev_priv->status_gfx_addr = 0;
++              drm_core_ioremapfree(&dev_priv->hws_map, dev);
++              I915_WRITE(0x02080, 0x1ffff000);
++      }
++}
++
 +static int i915_load_modeset_init(struct drm_device *dev)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      unsigned long agp_size, prealloc_size;
 +      int ret = 0;
 +
 +      i915_probe_agp(dev->pdev, &agp_size, &prealloc_size);
 +
 +      /* Basic memrange allocator for stolen space (aka vram) */
 +      drm_mm_init(&dev_priv->vram, 0, prealloc_size);
 +      /* Let GEM Manage from end of prealloc space to end of aperture */
 +      i915_gem_do_init(dev, prealloc_size, agp_size);
 +
 +      ret = i915_gem_init_ringbuffer(dev);
 +      if (ret)
 +              goto out;
 +
 +      /* Allow hardware batchbuffers unless told otherwise.
 +       */
 +      dev_priv->allow_batchbuffer = 1;
 +      dev_priv->max_validate_buffers = I915_MAX_VALIDATE_BUFFERS;
 +      mutex_init(&dev_priv->cmdbuf_mutex);
 +
 +      dev_priv->wq = create_singlethread_workqueue("i915");
 +      if (dev_priv->wq == 0) {
 +              DRM_DEBUG("Error\n");
 +              ret = -EINVAL;
 +              goto destroy_ringbuffer;
 +      }
 +
 +      ret = intel_init_bios(dev);
 +      if (ret) {
 +              DRM_ERROR("failed to find VBIOS tables\n");
 +              ret = -ENODEV;
 +              goto destroy_wq;
 +      }
 +
 +      intel_modeset_init(dev);
 +      drm_helper_initial_config(dev, false);
 +
 +      dev->devname = kstrdup(DRIVER_NAME, GFP_KERNEL);
 +      if (!dev->devname) {
 +              ret = -ENOMEM;
 +              goto modeset_cleanup;
 +      }
 +
 +      ret = drm_irq_install(dev);
 +      if (ret) {
 +              kfree(dev->devname);
 +              goto modeset_cleanup;
 +      }
 +      return 0;
 +
 +modeset_cleanup:
 +      intel_modeset_cleanup(dev);
 +destroy_wq:
 +      destroy_workqueue(dev_priv->wq);
 +destroy_ringbuffer:
 +      i915_gem_cleanup_ringbuffer(dev);
 +out:
 +      return ret;
 +}
 +
 +/**
 + * i915_driver_load - setup chip and create an initial config
 + * @dev: DRM device
 + * @flags: startup flags
 + *
 + * The driver load routine has to do several things:
 + *   - drive output discovery via intel_modeset_init()
 + *   - initialize the memory manager
 + *   - allocate initial config memory
 + *   - setup the DRM framebuffer with the allocated memory
 + */
 +int i915_driver_load(struct drm_device *dev, unsigned long flags)
 +{
 +      struct drm_i915_private *dev_priv;
 +      int ret = 0, num_pipes = 2;
 +      u32 tmp;
 +
 +      dev_priv = drm_alloc(sizeof(struct drm_i915_private), DRM_MEM_DRIVER);
 +      if (dev_priv == NULL)
 +              return -ENOMEM;
 +
 +      memset(dev_priv, 0, sizeof(struct drm_i915_private));
 +      dev->dev_private = (void *)dev_priv;
 +      dev_priv->dev = dev;
 +
 +      /* i915 has 4 more counters */
 +      dev->counters += 4;
 +      dev->types[6] = _DRM_STAT_IRQ;
 +      dev->types[7] = _DRM_STAT_PRIMARY;
 +      dev->types[8] = _DRM_STAT_SECONDARY;
 +      dev->types[9] = _DRM_STAT_DMA;
 +
 +      if (IS_MOBILE(dev) || IS_I9XX(dev))
 +              dev_priv->cursor_needs_physical = true;
 +      else
 +              dev_priv->cursor_needs_physical = false;
 +
 +      if (IS_I965G(dev) || IS_G33(dev))
 +              dev_priv->cursor_needs_physical = false;
 +
 +      if (IS_I9XX(dev))
 +              pci_read_config_dword(dev->pdev, 0x5C, &dev_priv->stolen_base);
 +
 +      if (IS_I9XX(dev)) {
 +              dev_priv->mmiobase = drm_get_resource_start(dev, 0);
 +              dev_priv->mmiolen = drm_get_resource_len(dev, 0);
 +              dev->mode_config.fb_base =
 +                      drm_get_resource_start(dev, 2) & 0xff000000;
 +      } else if (drm_get_resource_start(dev, 1)) {
 +              dev_priv->mmiobase = drm_get_resource_start(dev, 1);
 +              dev_priv->mmiolen = drm_get_resource_len(dev, 1);
 +              dev->mode_config.fb_base =
 +                      drm_get_resource_start(dev, 0) & 0xff000000;
 +      } else {
 +              DRM_ERROR("Unable to find MMIO registers\n");
 +              ret = -ENODEV;
 +              goto free_priv;
 +      }
 +
 +      DRM_DEBUG("fb_base: 0x%08lx\n", dev->mode_config.fb_base);
 +
 +      ret = drm_addmap(dev, dev_priv->mmiobase, dev_priv->mmiolen,
 +                       _DRM_REGISTERS, _DRM_KERNEL|_DRM_READ_ONLY|_DRM_DRIVER,
 +                       &dev_priv->mmio_map);
 +      if (ret != 0) {
 +              DRM_ERROR("Cannot add mapping for MMIO registers\n");
 +              goto free_priv;
 +      }
 +
 +      i915_gem_load(dev);
 +
 +#ifdef __linux__
 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
 +      intel_init_chipset_flush_compat(dev);
 +#endif
 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25)
 +      intel_opregion_init(dev);
 +#endif
 +#endif
 +
 +      tmp = I915_READ(PIPEASTAT);
 +      I915_WRITE(PIPEASTAT, tmp);
 +      tmp = I915_READ(PIPEBSTAT);
 +      I915_WRITE(PIPEBSTAT, tmp);
 +
 +      atomic_set(&dev_priv->irq_received, 0);
 +      I915_WRITE(HWSTAM, 0xeffe);
 +      I915_WRITE(IMR, 0x0);
 +      I915_WRITE(IER, 0x0);
 +
 +      DRM_SPININIT(&dev_priv->swaps_lock, "swap");
 +      INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
 +      dev_priv->swaps_pending = 0;
 +
 +      DRM_SPININIT(&dev_priv->user_irq_lock, "userirq");
 +      dev_priv->user_irq_refcount = 0;
 +      dev_priv->irq_mask_reg = ~0;
 +
 +      ret = drm_vblank_init(dev, num_pipes);
 +      if (ret)
 +              goto out_rmmap;
 +
 +      ret = drm_hotplug_init(dev);
 +      if (ret)
 +              goto out_rmmap;
 +
 +      dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
 +      dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
 +
 +      i915_enable_interrupt(dev);
 +      DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
 +
 +      /*
 +       * Initialize the hardware status page IRQ location.
 +       */
 +
 +      I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
 +
++      if (!I915_NEED_GFX_HWS(dev)) {
++              ret = i915_init_hardware_status(dev);
++              if (ret)
++                      return ret;
++      }
++
 +      if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 +              ret = i915_load_modeset_init(dev);
 +              if (ret < 0) {
 +                      DRM_ERROR("failed to init modeset\n");
 +                      goto out_rmmap;
 +              }
 +      }
 +
 +      return 0;
 +
 +out_rmmap:
 +      drm_rmmap(dev, dev_priv->mmio_map);
 +free_priv:
 +      drm_free(dev_priv, sizeof(struct drm_i915_private), DRM_MEM_DRIVER);
 +      return ret;
 +}
 +
 +int i915_driver_unload(struct drm_device *dev)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +
 +      u32 temp;
 +
++      i915_free_hardware_status(dev);
++
 +      dev_priv->vblank_pipe = 0;
 +
 +      dev_priv->irq_enabled = 0;
 +
 +      I915_WRITE(HWSTAM, 0xffffffff);
 +      I915_WRITE(IMR, 0xffffffff);
 +      I915_WRITE(IER, 0x0);
 +
 +      temp = I915_READ(PIPEASTAT);
 +      I915_WRITE(PIPEASTAT, temp);
 +      temp = I915_READ(PIPEBSTAT);
 +      I915_WRITE(PIPEBSTAT, temp);
 +      temp = I915_READ(IIR);
 +      I915_WRITE(IIR, temp);
 +
 +      I915_WRITE(PRB0_CTL, 0);
 +
 +      if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 +              drm_irq_uninstall(dev);
 +              intel_modeset_cleanup(dev);
 +              destroy_workqueue(dev_priv->wq);
 +      }
 +
 +#if 0
 +      if (dev_priv->ring.virtual_start) {
 +              drm_core_ioremapfree(&dev_priv->ring.map, dev);
 +      }
 +#endif
 +
 +#ifdef DRI2
 +      if (dev_priv->sarea_kmap.virtual) {
 +              drm_bo_kunmap(&dev_priv->sarea_kmap);
 +              dev_priv->sarea_kmap.virtual = NULL;
 +              dev->sigdata.lock = NULL;
 +      }
 +
 +      if (dev_priv->sarea_bo) {
 +              mutex_lock(&dev->struct_mutex);
 +              drm_bo_usage_deref_locked(&dev_priv->sarea_bo);
 +              mutex_unlock(&dev->struct_mutex);
 +              dev_priv->sarea_bo = NULL;
 +      }
 +#endif
 +
 +      if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 +              mutex_lock(&dev->struct_mutex);
 +              i915_gem_cleanup_ringbuffer(dev);
 +              mutex_unlock(&dev->struct_mutex);
 +              drm_mm_takedown(&dev_priv->vram);
 +              i915_gem_lastclose(dev);
 +              if (!I915_NEED_GFX_HWS(dev))
 +                      drm_pci_free(dev, dev_priv->status_page_dmah);
 +      }
 +
 +        drm_rmmap(dev, dev_priv->mmio_map);
 +
 +#ifdef __linux__
 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25)
 +      intel_opregion_free(dev);
 +#endif
 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
 +      intel_fini_chipset_flush_compat(dev);
 +#endif
 +#endif
 +
 +      drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
 +
 +      dev->dev_private = NULL;
 +      return 0;
 +}
 +
 +int i915_master_create(struct drm_device *dev, struct drm_master *master)
 +{
 +      struct drm_i915_master_private *master_priv;
 +      unsigned long sareapage;
 +      int ret;
 +
 +      master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER);
 +      if (!master_priv)
 +              return -ENOMEM;
 +
 +      /* prebuild the SAREA */
 +      sareapage = max(SAREA_MAX, PAGE_SIZE);
 +      ret = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK|_DRM_DRIVER,
 +                       &master_priv->sarea);
 +      if (ret) {
 +              DRM_ERROR("SAREA setup failed\n");
 +              return ret;
 +      }
 +      master_priv->sarea_priv = master_priv->sarea->handle + sizeof(struct drm_sarea);
 +      master_priv->sarea_priv->pf_current_page = 0;
 +
 +      master->driver_priv = master_priv;
 +      return 0;
 +}
 +
 +void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
 +{
 +      struct drm_i915_master_private *master_priv = master->driver_priv;
 +
 +      if (!master_priv)
 +              return;
 +
 +      if (master_priv->sarea)
 +              drm_rmmap_locked(dev, master_priv->sarea);
 +              
 +      drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER);
 +
 +      master->driver_priv = NULL;
 +}
 +
 +int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
 +{
 +      struct drm_i915_file_private *i915_file_priv;
 +
 +      DRM_DEBUG("\n");
 +      i915_file_priv = (struct drm_i915_file_private *)
 +          drm_alloc(sizeof(*i915_file_priv), DRM_MEM_FILES);
 +
 +      if (!i915_file_priv)
 +              return -ENOMEM;
 +
 +      file_priv->driver_priv = i915_file_priv;
 +
 +      i915_file_priv->mm.last_gem_seqno = 0;
 +      i915_file_priv->mm.last_gem_throttle_seqno = 0;
 +
 +      return 0;
 +}
 +
 +void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
 +{
 +      struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
 +
 +      drm_free(i915_file_priv, sizeof(*i915_file_priv), DRM_MEM_FILES);
 +}
 +
 +void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
 +{
 +        struct drm_i915_private *dev_priv = dev->dev_private;
 +      if (!drm_core_check_feature(dev, DRIVER_MODESET))
 +              i915_mem_release(dev, file_priv, dev_priv->agp_heap);
 +}
 +
 +void i915_driver_lastclose(struct drm_device * dev)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +
 +      if (drm_core_check_feature(dev, DRIVER_MODESET))
 +              return;
 +
 +#ifdef I915_HAVE_BUFFER
 +      if (dev_priv->val_bufs) {
 +              vfree(dev_priv->val_bufs);
 +              dev_priv->val_bufs = NULL;
 +      }
 +#endif
 +
 +      i915_gem_lastclose(dev);
 +
 +      if (dev_priv->agp_heap)
 +              i915_mem_takedown(&(dev_priv->agp_heap));
 +
 +#if defined(DRI2)
 +      if (dev_priv->sarea_kmap.virtual) {
 +              drm_bo_kunmap(&dev_priv->sarea_kmap);
 +              dev_priv->sarea_kmap.virtual = NULL;
 +              dev->control->master->lock.hw_lock = NULL;
 +              dev->sigdata.lock = NULL;
 +      }
 +
 +      if (dev_priv->sarea_bo) {
 +              mutex_lock(&dev->struct_mutex);
 +              drm_bo_usage_deref_locked(&dev_priv->sarea_bo);
 +              mutex_unlock(&dev->struct_mutex);
 +              dev_priv->sarea_bo = NULL;
 +      }
 +#endif
 +      
 +      i915_dma_cleanup(dev);
 +}
 +
 +int i915_driver_firstopen(struct drm_device *dev)
 +{
 +      if (drm_core_check_feature(dev, DRIVER_MODESET))
 +              return 0;
 +      return 0;
 +}
@@@ -486,18 -428,21 +486,20 @@@ static int i915_run_hotplug_tasklet(str
  irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
  {
        struct drm_device *dev = (struct drm_device *) arg;
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +      struct drm_i915_master_private *master_priv;
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
        u32 iir;
 -      u32 pipea_stats = 0, pipeb_stats = 0;
 +      u32 pipea_stats = 0, pipeb_stats = 0, tvdac;
 +      int hotplug = 0;
        int vblank = 0;
+ #ifdef __linux__
        if (dev->pdev->msi_enabled)
                I915_WRITE(IMR, ~0);
+ #endif
        iir = I915_READ(IIR);
 -#if 0
 -      DRM_DEBUG("flag=%08x\n", iir);
 -#endif
        atomic_inc(&dev_priv->irq_received);
        if (iir == 0) {
+ #ifdef __linux__
                if (dev->pdev->msi_enabled) {
                        I915_WRITE(IMR, dev_priv->irq_mask_reg);
                        (void) I915_READ(IMR);
         */
        if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
                pipea_stats = I915_READ(PIPEASTAT);
 -              if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
 -                                 PIPE_VBLANK_INTERRUPT_STATUS))
 -              {
 -                      vblank++;
 -                      drm_handle_vblank(dev, i915_get_plane(dev, 0));
 -              }
                I915_WRITE(PIPEASTAT, pipea_stats);
        }
 +
        if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
                pipeb_stats = I915_READ(PIPEBSTAT);
 -              /* Ack the event */
                I915_WRITE(PIPEBSTAT, pipeb_stats);
 +      }
  
 -              /* The vblank interrupt gets enabled even if we didn't ask for
 -                 it, so make sure it's shut down again */
 -              if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B))
 -                      pipeb_stats &= ~(I915_VBLANK_INTERRUPT_ENABLE);
 -
 -              if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
 -                                 PIPE_VBLANK_INTERRUPT_STATUS))
 -              {
 -                      vblank++;
 -                      drm_handle_vblank(dev, i915_get_plane(dev, 1));
 -              }
 -
 +      I915_WRITE(IIR, iir);
+ #ifdef __linux__
 -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25)
 -              if (pipeb_stats & I915_LEGACY_BLC_EVENT_ENABLE)
 -                      opregion_asle_intr(dev);
 -#endif
 +      if (dev->pdev->msi_enabled)
 +              I915_WRITE(IMR, dev_priv->irq_mask_reg);
+ #endif
 -              I915_WRITE(PIPEBSTAT, pipeb_stats);
++
 +      (void) I915_READ(IIR); /* Flush posted writes */
 +
 +      /* This is a global event, and not a pipe A event */
 +      if (pipea_stats & PIPE_HOTPLUG_INTERRUPT_STATUS)
 +              hotplug = 1;
 +
 +      if (pipea_stats & PIPE_HOTPLUG_TV_INTERRUPT_STATUS) {
 +              hotplug = 1;
 +              /* Toggle hotplug detection to clear hotplug status */
 +              tvdac = I915_READ(TV_DAC);
 +              I915_WRITE(TV_DAC, tvdac & ~TVDAC_STATE_CHG_EN);
 +              I915_WRITE(TV_DAC, tvdac | TVDAC_STATE_CHG_EN);
 +      }
 +
 +      if (dev->primary->master) {
 +              master_priv = dev->primary->master->driver_priv;
 +              master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
        }
  
  #ifdef __linux__
  #endif
  #endif
  
 -      if (dev_priv->sarea_priv)
 -          dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
 -
 -      I915_WRITE(IIR, iir);
 -#ifdef __linux__
 -      if (dev->pdev->msi_enabled)
 -              I915_WRITE(IMR, dev_priv->irq_mask_reg);
 -#endif
 -      (void) I915_READ(IIR); /* Flush posted writes */
 -
        if (iir & I915_USER_INTERRUPT) {
+ #ifdef I915_HAVE_GEM
                dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
+ #endif
                DRM_WAKEUP(&dev_priv->irq_queue);
 -#ifdef I915_HAVE_FENCE
 -              i915_fence_handler(dev);
 -#endif
 +      }
 +
 +      if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
 +                         PIPE_VBLANK_INTERRUPT_STATUS)) {
 +              vblank++;
 +              drm_handle_vblank(dev, i915_get_plane(dev, 0));
 +      }
 +
 +      /* The vblank interrupt gets enabled even if we didn't ask for
 +         it, so make sure it's shut down again */
 +      if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B))
 +              pipeb_stats &= ~(I915_VBLANK_INTERRUPT_ENABLE);
 +
 +      if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
 +                         PIPE_VBLANK_INTERRUPT_STATUS)) {
 +              vblank++;
 +              drm_handle_vblank(dev, i915_get_plane(dev, 1));
        }
  
        if (vblank) {
@@@ -628,13 -552,13 +636,15 @@@ void i915_user_irq_on(struct drm_devic
                i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
        DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
  }
 -
 -void i915_user_irq_off(drm_i915_private_t *dev_priv)
 +              
 +void i915_user_irq_off(struct drm_device *dev)
  {
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
 +
        DRM_SPINLOCK(&dev_priv->user_irq_lock);
+ #ifdef __linux__
        BUG_ON(dev_priv->irq_enabled && dev_priv->user_irq_refcount <= 0);
+ #endif
        if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0))
                i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
        DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
@@@ -1107,10 -954,9 +1117,9 @@@ void i915_driver_irq_preinstall(struct 
  
  int i915_driver_irq_postinstall(struct drm_device * dev)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
        int ret, num_pipes = 2;
  
-       DRM_SPININIT(&dev_priv->swaps_lock, "swap");
        INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
        dev_priv->swaps_pending = 0;
  
@@@ -314,27 -311,13 +314,34 @@@ struct drm_nouveau_private 
  
        struct list_head gpuobj_list;
  
 +      void *display_priv; /* internal modesetting */
 +      void *kms_priv; /* related to public interface */
 +
 +      /* Hook these up to the "public interface" to accomodate a certain allocation style. */
 +      /* This is to avoid polluting the internal interface. */
 +      void *(*alloc_crtc) (struct drm_device *dev);
 +      void *(*alloc_output) (struct drm_device *dev);
 +      void *(*alloc_connector) (struct drm_device *dev);
 +
 +      void (*free_crtc) (void *crtc);
 +      void (*free_output) (void *output);
 +      void (*free_connector) (void *connector);
 +
 +      struct bios bios;
 +
 +      struct {
 +              int entries;
 +              struct dcb_entry entry[MAX_NUM_DCB_ENTRIES];
 +              unsigned char i2c_read[MAX_NUM_DCB_ENTRIES];
 +              unsigned char i2c_write[MAX_NUM_DCB_ENTRIES];
 +      } dcb_table;
+       struct nouveau_suspend_resume {
+               uint32_t fifo_mode;
+               uint32_t graph_ctx_control;
+               uint32_t graph_state;
+               uint32_t *ramin_copy;
+               uint64_t ramin_size;
+       } susres;
  };
  
  #define NOUVEAU_CHECK_INITIALISED_WITH_RETURN do {         \
Simple merge
Simple merge
@@@ -24,10 -24,9 +24,11 @@@ TESTS = auth 
        setversion \
        updatedraw \
        gem_basic \
+       gem_flink \
        gem_readwrite \
 -      gem_mmap
 +      gem_mmap \
 +      radeon_gem_mmap \
 +      radeon_gem_basic
  
  EXTRA_PROGRAMS = $(TESTS)
  CLEANFILES = $(EXTRA_PROGRAMS) $(EXTRA_LTLIBRARIES)