Merge branch 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
Linus Torvalds [Thu, 7 Jan 2010 04:26:42 +0000 (20:26 -0800)]
* 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
  drm/radeon/kms: rs600: use correct mask for SW interrupt
  gpu/drm/radeon/radeon_irq.c: move a dereference below a NULL test
  drm/radeon/radeon_device.c: move a dereference below a NULL test
  drm/radeon/radeon_fence.c: move a dereference below the NULL test
  drm/radeon/radeon_connectors.c: add a NULL test before dereference
  drm/radeon/kms: fix memory leak
  drm/kms: Fix &&/|| confusion in drm_fb_helper_connector_parse_command_line()
  drm/edid: Fix CVT width/height decode
  drm/edid: Skip empty CVT codepoints
  drm: remove address mask param for drm_pci_alloc()
  drm/radeon/kms: add missing breaks in i2c and ss lookups
  drm/radeon/kms: add primary dac adj values table
  drm/radeon/kms: fallback to default connector table

1  2 
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_gem.c

@@@ -123,7 -123,7 +123,7 @@@ static int i915_init_phys_hws(struct dr
        drm_i915_private_t *dev_priv = dev->dev_private;
        /* Program Hardware Status Page */
        dev_priv->status_page_dmah =
-               drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
+               drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE);
  
        if (!dev_priv->status_page_dmah) {
                DRM_ERROR("Can not allocate hardware status page\n");
@@@ -813,13 -813,9 +813,13 @@@ static int i915_getparam(struct drm_dev
        case I915_PARAM_HAS_PAGEFLIPPING:
                value = 1;
                break;
 +      case I915_PARAM_HAS_EXECBUF2:
 +              /* depends on GEM */
 +              value = dev_priv->has_gem;
 +              break;
        default:
                DRM_DEBUG_DRIVER("Unknown parameter %d\n",
 -                                      param->param);
 +                               param->param);
                return -EINVAL;
        }
  
@@@ -1121,8 -1117,7 +1121,8 @@@ static void i915_setup_compression(stru
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_mm_node *compressed_fb, *compressed_llb;
 -      unsigned long cfb_base, ll_base;
 +      unsigned long cfb_base;
 +      unsigned long ll_base = 0;
  
        /* Leave 1M for line length buffer & misc. */
        compressed_fb = drm_mm_search_free(&dev_priv->vram, size, 4096, 0);
@@@ -1205,6 -1200,14 +1205,6 @@@ static int i915_load_modeset_init(struc
        dev->mode_config.fb_base = drm_get_resource_start(dev, fb_bar) &
                0xff000000;
  
 -      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;
 -
        /* Basic memrange allocator for stolen space (aka vram) */
        drm_mm_init(&dev_priv->vram, 0, prealloc_size);
        DRM_INFO("set up %ldM of stolen space\n", prealloc_size / (1024*1024));
        if (ret)
                goto destroy_ringbuffer;
  
 +      intel_modeset_init(dev);
 +
        ret = drm_irq_install(dev);
        if (ret)
                goto destroy_ringbuffer;
  
        I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
  
 -      intel_modeset_init(dev);
 -
        drm_helper_initial_config(dev);
  
        return 0;
@@@ -1357,7 -1360,7 +1357,7 @@@ int i915_driver_load(struct drm_device 
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        resource_size_t base, size;
 -      int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
 +      int ret = 0, mmio_bar;
        uint32_t agp_size, prealloc_size, prealloc_start;
  
        /* i915 has 4 more counters */
  
        dev->dev_private = (void *)dev_priv;
        dev_priv->dev = dev;
 +      dev_priv->info = (struct intel_device_info *) flags;
  
        /* Add register map (needed for suspend/resume) */
 +      mmio_bar = IS_I9XX(dev) ? 0 : 1;
        base = drm_get_resource_start(dev, mmio_bar);
        size = drm_get_resource_len(dev, mmio_bar);
  
@@@ -1651,7 -1652,6 +1651,7 @@@ struct drm_ioctl_desc i915_ioctls[] = 
        DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
 +      DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH),
        DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH),
@@@ -1310,7 -1310,7 +1310,7 @@@ out_free_list
   * i915_gem_release_mmap - remove physical page mappings
   * @obj: obj in question
   *
 - * Preserve the reservation of the mmaping with the DRM core code, but
 + * Preserve the reservation of the mmapping with the DRM core code, but
   * relinquish ownership of the pages back to the system.
   *
   * It is vital that we remove the page mapping if we have mapped a tiled
@@@ -2021,6 -2021,9 +2021,6 @@@ i915_gem_object_unbind(struct drm_gem_o
        /* blow away mappings if mapped through GTT */
        i915_gem_release_mmap(obj);
  
 -      if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
 -              i915_gem_clear_fence_reg(obj);
 -
        /* Move the object to the CPU domain to ensure that
         * any possible CPU writes while it's not in the GTT
         * are flushed when we go to remap it. This will
  
        BUG_ON(obj_priv->active);
  
 +      /* release the fence reg _after_ flushing */
 +      if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
 +              i915_gem_clear_fence_reg(obj);
 +
        if (obj_priv->agp_mem != NULL) {
                drm_unbind_agp(obj_priv->agp_mem);
                drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE);
@@@ -2582,6 -2581,9 +2582,6 @@@ i915_gem_object_bind_to_gtt(struct drm_
        bool retry_alloc = false;
        int ret;
  
 -      if (dev_priv->mm.suspended)
 -              return -EBUSY;
 -
        if (obj_priv->madv != I915_MADV_WILLNEED) {
                DRM_ERROR("Attempting to bind a purgeable object\n");
                return -EINVAL;
@@@ -3196,7 -3198,7 +3196,7 @@@ i915_gem_object_set_cpu_read_domain_ran
  static int
  i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
                                 struct drm_file *file_priv,
 -                               struct drm_i915_gem_exec_object *entry,
 +                               struct drm_i915_gem_exec_object2 *entry,
                                 struct drm_i915_gem_relocation_entry *relocs)
  {
        struct drm_device *dev = obj->dev;
        struct drm_i915_gem_object *obj_priv = obj->driver_private;
        int i, ret;
        void __iomem *reloc_page;
 +      bool need_fence;
 +
 +      need_fence = entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
 +                   obj_priv->tiling_mode != I915_TILING_NONE;
 +
 +      /* Check fence reg constraints and rebind if necessary */
 +      if (need_fence && !i915_obj_fenceable(dev, obj))
 +              i915_gem_object_unbind(obj);
  
        /* Choose the GTT offset for our buffer and put it there. */
        ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment);
        if (ret)
                return ret;
  
 +      /*
 +       * Pre-965 chips need a fence register set up in order to
 +       * properly handle blits to/from tiled surfaces.
 +       */
 +      if (need_fence) {
 +              ret = i915_gem_object_get_fence_reg(obj);
 +              if (ret != 0) {
 +                      if (ret != -EBUSY && ret != -ERESTARTSYS)
 +                              DRM_ERROR("Failure to install fence: %d\n",
 +                                        ret);
 +                      i915_gem_object_unpin(obj);
 +                      return ret;
 +              }
 +      }
 +
        entry->offset = obj_priv->gtt_offset;
  
        /* Apply the relocations, using the GTT aperture to avoid cache
   */
  static int
  i915_dispatch_gem_execbuffer(struct drm_device *dev,
 -                            struct drm_i915_gem_execbuffer *exec,
 +                            struct drm_i915_gem_execbuffer2 *exec,
                              struct drm_clip_rect *cliprects,
                              uint64_t exec_offset)
  {
@@@ -3484,7 -3463,7 +3484,7 @@@ i915_gem_ring_throttle(struct drm_devic
  }
  
  static int
 -i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list,
 +i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object2 *exec_list,
                              uint32_t buffer_count,
                              struct drm_i915_gem_relocation_entry **relocs)
  {
        }
  
        *relocs = drm_calloc_large(reloc_count, sizeof(**relocs));
 -      if (*relocs == NULL)
 +      if (*relocs == NULL) {
 +              DRM_ERROR("failed to alloc relocs, count %d\n", reloc_count);
                return -ENOMEM;
 +      }
  
        for (i = 0; i < buffer_count; i++) {
                struct drm_i915_gem_relocation_entry __user *user_relocs;
  }
  
  static int
 -i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object *exec_list,
 +i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object2 *exec_list,
                            uint32_t buffer_count,
                            struct drm_i915_gem_relocation_entry *relocs)
  {
@@@ -3559,7 -3536,7 +3559,7 @@@ err
  }
  
  static int
 -i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer *exec,
 +i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer2 *exec,
                           uint64_t exec_offset)
  {
        uint32_t exec_start, exec_len;
@@@ -3612,18 -3589,18 +3612,18 @@@ i915_gem_wait_for_pending_flip(struct d
  }
  
  int
 -i915_gem_execbuffer(struct drm_device *dev, void *data,
 -                  struct drm_file *file_priv)
 +i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 +                     struct drm_file *file_priv,
 +                     struct drm_i915_gem_execbuffer2 *args,
 +                     struct drm_i915_gem_exec_object2 *exec_list)
  {
        drm_i915_private_t *dev_priv = dev->dev_private;
 -      struct drm_i915_gem_execbuffer *args = data;
 -      struct drm_i915_gem_exec_object *exec_list = NULL;
        struct drm_gem_object **object_list = NULL;
        struct drm_gem_object *batch_obj;
        struct drm_i915_gem_object *obj_priv;
        struct drm_clip_rect *cliprects = NULL;
        struct drm_i915_gem_relocation_entry *relocs;
 -      int ret, ret2, i, pinned = 0;
 +      int ret = 0, ret2, i, pinned = 0;
        uint64_t exec_offset;
        uint32_t seqno, flush_domains, reloc_index;
        int pin_tries, flips;
                DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
                return -EINVAL;
        }
 -      /* Copy in the exec list from userland */
 -      exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count);
        object_list = drm_malloc_ab(sizeof(*object_list), args->buffer_count);
 -      if (exec_list == NULL || object_list == NULL) {
 -              DRM_ERROR("Failed to allocate exec or object list "
 -                        "for %d buffers\n",
 +      if (object_list == NULL) {
 +              DRM_ERROR("Failed to allocate object list for %d buffers\n",
                          args->buffer_count);
                ret = -ENOMEM;
                goto pre_mutex_err;
        }
 -      ret = copy_from_user(exec_list,
 -                           (struct drm_i915_relocation_entry __user *)
 -                           (uintptr_t) args->buffers_ptr,
 -                           sizeof(*exec_list) * args->buffer_count);
 -      if (ret != 0) {
 -              DRM_ERROR("copy %d exec entries failed %d\n",
 -                        args->buffer_count, ret);
 -              goto pre_mutex_err;
 -      }
  
        if (args->num_cliprects != 0) {
                cliprects = kcalloc(args->num_cliprects, sizeof(*cliprects),
@@@ -3895,6 -3884,20 +3895,6 @@@ err
  
        mutex_unlock(&dev->struct_mutex);
  
 -      if (!ret) {
 -              /* Copy the new buffer offsets back to the user's exec list. */
 -              ret = copy_to_user((struct drm_i915_relocation_entry __user *)
 -                                 (uintptr_t) args->buffers_ptr,
 -                                 exec_list,
 -                                 sizeof(*exec_list) * args->buffer_count);
 -              if (ret) {
 -                      ret = -EFAULT;
 -                      DRM_ERROR("failed to copy %d exec entries "
 -                                "back to user (%d)\n",
 -                                args->buffer_count, ret);
 -              }
 -      }
 -
        /* Copy the updated relocations out regardless of current error
         * state.  Failure to update the relocs would mean that the next
         * time userland calls execbuf, it would do so with presumed offset
  
  pre_mutex_err:
        drm_free_large(object_list);
 -      drm_free_large(exec_list);
        kfree(cliprects);
  
        return ret;
  }
  
 +/*
 + * Legacy execbuffer just creates an exec2 list from the original exec object
 + * list array and passes it to the real function.
 + */
 +int
 +i915_gem_execbuffer(struct drm_device *dev, void *data,
 +                  struct drm_file *file_priv)
 +{
 +      struct drm_i915_gem_execbuffer *args = data;
 +      struct drm_i915_gem_execbuffer2 exec2;
 +      struct drm_i915_gem_exec_object *exec_list = NULL;
 +      struct drm_i915_gem_exec_object2 *exec2_list = NULL;
 +      int ret, i;
 +
 +#if WATCH_EXEC
 +      DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
 +                (int) args->buffers_ptr, args->buffer_count, args->batch_len);
 +#endif
 +
 +      if (args->buffer_count < 1) {
 +              DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
 +              return -EINVAL;
 +      }
 +
 +      /* Copy in the exec list from userland */
 +      exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count);
 +      exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count);
 +      if (exec_list == NULL || exec2_list == NULL) {
 +              DRM_ERROR("Failed to allocate exec list for %d buffers\n",
 +                        args->buffer_count);
 +              drm_free_large(exec_list);
 +              drm_free_large(exec2_list);
 +              return -ENOMEM;
 +      }
 +      ret = copy_from_user(exec_list,
 +                           (struct drm_i915_relocation_entry __user *)
 +                           (uintptr_t) args->buffers_ptr,
 +                           sizeof(*exec_list) * args->buffer_count);
 +      if (ret != 0) {
 +              DRM_ERROR("copy %d exec entries failed %d\n",
 +                        args->buffer_count, ret);
 +              drm_free_large(exec_list);
 +              drm_free_large(exec2_list);
 +              return -EFAULT;
 +      }
 +
 +      for (i = 0; i < args->buffer_count; i++) {
 +              exec2_list[i].handle = exec_list[i].handle;
 +              exec2_list[i].relocation_count = exec_list[i].relocation_count;
 +              exec2_list[i].relocs_ptr = exec_list[i].relocs_ptr;
 +              exec2_list[i].alignment = exec_list[i].alignment;
 +              exec2_list[i].offset = exec_list[i].offset;
 +              if (!IS_I965G(dev))
 +                      exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE;
 +              else
 +                      exec2_list[i].flags = 0;
 +      }
 +
 +      exec2.buffers_ptr = args->buffers_ptr;
 +      exec2.buffer_count = args->buffer_count;
 +      exec2.batch_start_offset = args->batch_start_offset;
 +      exec2.batch_len = args->batch_len;
 +      exec2.DR1 = args->DR1;
 +      exec2.DR4 = args->DR4;
 +      exec2.num_cliprects = args->num_cliprects;
 +      exec2.cliprects_ptr = args->cliprects_ptr;
 +      exec2.flags = 0;
 +
 +      ret = i915_gem_do_execbuffer(dev, data, file_priv, &exec2, exec2_list);
 +      if (!ret) {
 +              /* Copy the new buffer offsets back to the user's exec list. */
 +              for (i = 0; i < args->buffer_count; i++)
 +                      exec_list[i].offset = exec2_list[i].offset;
 +              /* ... and back out to userspace */
 +              ret = copy_to_user((struct drm_i915_relocation_entry __user *)
 +                                 (uintptr_t) args->buffers_ptr,
 +                                 exec_list,
 +                                 sizeof(*exec_list) * args->buffer_count);
 +              if (ret) {
 +                      ret = -EFAULT;
 +                      DRM_ERROR("failed to copy %d exec entries "
 +                                "back to user (%d)\n",
 +                                args->buffer_count, ret);
 +              }
 +      } else {
 +              DRM_ERROR("i915_gem_do_execbuffer returns %d\n", ret);
 +      }
 +
 +      drm_free_large(exec_list);
 +      drm_free_large(exec2_list);
 +      return ret;
 +}
 +
 +int
 +i915_gem_execbuffer2(struct drm_device *dev, void *data,
 +                   struct drm_file *file_priv)
 +{
 +      struct drm_i915_gem_execbuffer2 *args = data;
 +      struct drm_i915_gem_exec_object2 *exec2_list = NULL;
 +      int ret;
 +
 +#if WATCH_EXEC
 +      DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
 +                (int) args->buffers_ptr, args->buffer_count, args->batch_len);
 +#endif
 +
 +      if (args->buffer_count < 1) {
 +              DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count);
 +              return -EINVAL;
 +      }
 +
 +      exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count);
 +      if (exec2_list == NULL) {
 +              DRM_ERROR("Failed to allocate exec list for %d buffers\n",
 +                        args->buffer_count);
 +              return -ENOMEM;
 +      }
 +      ret = copy_from_user(exec2_list,
 +                           (struct drm_i915_relocation_entry __user *)
 +                           (uintptr_t) args->buffers_ptr,
 +                           sizeof(*exec2_list) * args->buffer_count);
 +      if (ret != 0) {
 +              DRM_ERROR("copy %d exec entries failed %d\n",
 +                        args->buffer_count, ret);
 +              drm_free_large(exec2_list);
 +              return -EFAULT;
 +      }
 +
 +      ret = i915_gem_do_execbuffer(dev, data, file_priv, args, exec2_list);
 +      if (!ret) {
 +              /* Copy the new buffer offsets back to the user's exec list. */
 +              ret = copy_to_user((struct drm_i915_relocation_entry __user *)
 +                                 (uintptr_t) args->buffers_ptr,
 +                                 exec2_list,
 +                                 sizeof(*exec2_list) * args->buffer_count);
 +              if (ret) {
 +                      ret = -EFAULT;
 +                      DRM_ERROR("failed to copy %d exec entries "
 +                                "back to user (%d)\n",
 +                                args->buffer_count, ret);
 +              }
 +      }
 +
 +      drm_free_large(exec2_list);
 +      return ret;
 +}
 +
  int
  i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
  {
                if (ret)
                        return ret;
        }
 -      /*
 -       * Pre-965 chips need a fence register set up in order to
 -       * properly handle tiled surfaces.
 -       */
 -      if (!IS_I965G(dev) && obj_priv->tiling_mode != I915_TILING_NONE) {
 -              ret = i915_gem_object_get_fence_reg(obj);
 -              if (ret != 0) {
 -                      if (ret != -EBUSY && ret != -ERESTARTSYS)
 -                              DRM_ERROR("Failure to install fence: %d\n",
 -                                        ret);
 -                      return ret;
 -              }
 -      }
 +
        obj_priv->pin_count++;
  
        /* If the object is not active and not pending a flush,
@@@ -4839,7 -4708,7 +4839,7 @@@ int i915_gem_init_phys_object(struct dr
  
        phys_obj->id = id;
  
-       phys_obj->handle = drm_pci_alloc(dev, size, 0, 0xffffffff);
+       phys_obj->handle = drm_pci_alloc(dev, size, 0);
        if (!phys_obj->handle) {
                ret = -ENOMEM;
                goto kfree_obj;