Commit 2ec77fc9 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6

* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (26 commits)
  drm/radeon: update sarea copies of last_ variables on resume.
  drm/i915: Keep refs on the object over the lifetime of vmas for GTT mmap.
  drm/i915: take struct mutex around fb unref
  drm: Use spread spectrum when the bios tells us it's ok.
  drm: Collapse identical i8xx_clock() and i9xx_clock().
  drm: Bring PLL limits in sync with DDX values.
  drm: Add locking around cursor gem operations.
  drm: Propagate failure from setting crtc base.
  drm: Check for a NULL encoder when reverting on error path
  drm/i915: Cleanup the hws on ringbuffer constrution failure.
  drm/i915: Don't add panel_fixed_mode to the probed modes list at LVDS init.
  drm: Release user fbs in drm_release
  drm/i915: Unpin the fb on error during construction.
  drm/i915: Unpin the hws if we fail to kmap.
  drm/i915: Unpin the ringbuffer if we fail to ioremap it.
  drm/i915: unpin for an invalid memory domain.
  drm/i915: Release and unlock on mmap_gtt error path.
  drm/i915: Set framebuffer alignment based upon the fence constraints.
  drm: Do not leak a new reference for flink() on an existing name
  drm/i915: Fix potential AB-BA deadlock in i915_gem_execbuffer()
  ...
parents be71cb5b 3d16118d
...@@ -1741,9 +1741,8 @@ int drm_mode_getfb(struct drm_device *dev, ...@@ -1741,9 +1741,8 @@ int drm_mode_getfb(struct drm_device *dev,
* RETURNS: * RETURNS:
* Zero on success, errno on failure. * Zero on success, errno on failure.
*/ */
void drm_fb_release(struct file *filp) void drm_fb_release(struct drm_file *priv)
{ {
struct drm_file *priv = filp->private_data;
struct drm_device *dev = priv->minor->dev; struct drm_device *dev = priv->minor->dev;
struct drm_framebuffer *fb, *tfb; struct drm_framebuffer *fb, *tfb;
......
...@@ -512,8 +512,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, ...@@ -512,8 +512,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
if (drm_mode_equal(&saved_mode, &crtc->mode)) { if (drm_mode_equal(&saved_mode, &crtc->mode)) {
if (saved_x != crtc->x || saved_y != crtc->y || if (saved_x != crtc->x || saved_y != crtc->y ||
depth_changed || bpp_changed) { depth_changed || bpp_changed) {
crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, ret = !crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
old_fb); old_fb);
goto done; goto done;
} }
} }
...@@ -552,7 +552,9 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, ...@@ -552,7 +552,9 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
/* Set up the DPLL and any encoders state that needs to adjust or depend /* Set up the DPLL and any encoders state that needs to adjust or depend
* on the DPLL. * on the DPLL.
*/ */
crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb); ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
if (!ret)
goto done;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
...@@ -752,6 +754,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) ...@@ -752,6 +754,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
if (!drm_crtc_helper_set_mode(set->crtc, set->mode, if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
set->x, set->y, set->x, set->y,
old_fb)) { old_fb)) {
DRM_ERROR("failed to set mode on crtc %p\n",
set->crtc);
ret = -EINVAL; ret = -EINVAL;
goto fail_set_mode; goto fail_set_mode;
} }
...@@ -765,7 +769,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) ...@@ -765,7 +769,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
old_fb = set->crtc->fb; old_fb = set->crtc->fb;
if (set->crtc->fb != set->fb) if (set->crtc->fb != set->fb)
set->crtc->fb = set->fb; set->crtc->fb = set->fb;
crtc_funcs->mode_set_base(set->crtc, set->x, set->y, old_fb); ret = crtc_funcs->mode_set_base(set->crtc,
set->x, set->y, old_fb);
if (ret != 0)
goto fail_set_mode;
} }
kfree(save_encoders); kfree(save_encoders);
...@@ -775,8 +782,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) ...@@ -775,8 +782,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
fail_set_mode: fail_set_mode:
set->crtc->enabled = save_enabled; set->crtc->enabled = save_enabled;
count = 0; count = 0;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
if (!connector->encoder)
continue;
connector->encoder->crtc = save_crtcs[count++]; connector->encoder->crtc = save_crtcs[count++];
}
fail_no_encoder: fail_no_encoder:
kfree(save_crtcs); kfree(save_crtcs);
count = 0; count = 0;
......
...@@ -457,6 +457,9 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -457,6 +457,9 @@ int drm_release(struct inode *inode, struct file *filp)
if (dev->driver->driver_features & DRIVER_GEM) if (dev->driver->driver_features & DRIVER_GEM)
drm_gem_release(dev, file_priv); drm_gem_release(dev, file_priv);
if (dev->driver->driver_features & DRIVER_MODESET)
drm_fb_release(file_priv);
mutex_lock(&dev->ctxlist_mutex); mutex_lock(&dev->ctxlist_mutex);
if (!list_empty(&dev->ctxlist)) { if (!list_empty(&dev->ctxlist)) {
struct drm_ctx_list *pos, *n; struct drm_ctx_list *pos, *n;
......
...@@ -104,8 +104,8 @@ drm_gem_init(struct drm_device *dev) ...@@ -104,8 +104,8 @@ drm_gem_init(struct drm_device *dev)
if (drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START, if (drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START,
DRM_FILE_PAGE_OFFSET_SIZE)) { DRM_FILE_PAGE_OFFSET_SIZE)) {
drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
drm_ht_remove(&mm->offset_hash); drm_ht_remove(&mm->offset_hash);
drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
return -ENOMEM; return -ENOMEM;
} }
...@@ -295,35 +295,37 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data, ...@@ -295,35 +295,37 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
return -EBADF; return -EBADF;
again: again:
if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) {
return -ENOMEM; ret = -ENOMEM;
goto err;
}
spin_lock(&dev->object_name_lock); spin_lock(&dev->object_name_lock);
if (obj->name) { if (!obj->name) {
args->name = obj->name; ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
&obj->name);
args->name = (uint64_t) obj->name;
spin_unlock(&dev->object_name_lock); spin_unlock(&dev->object_name_lock);
return 0;
}
ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
&obj->name);
spin_unlock(&dev->object_name_lock);
if (ret == -EAGAIN)
goto again;
if (ret != 0) { if (ret == -EAGAIN)
mutex_lock(&dev->struct_mutex); goto again;
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return ret;
}
/* if (ret != 0)
* Leave the reference from the lookup around as the goto err;
* name table now holds one
*/
args->name = (uint64_t) obj->name;
return 0; /* Allocate a reference for the name table. */
drm_gem_object_reference(obj);
} else {
args->name = (uint64_t) obj->name;
spin_unlock(&dev->object_name_lock);
ret = 0;
}
err:
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return ret;
} }
/** /**
...@@ -448,6 +450,7 @@ drm_gem_object_handle_free(struct kref *kref) ...@@ -448,6 +450,7 @@ drm_gem_object_handle_free(struct kref *kref)
spin_lock(&dev->object_name_lock); spin_lock(&dev->object_name_lock);
if (obj->name) { if (obj->name) {
idr_remove(&dev->object_name_idr, obj->name); idr_remove(&dev->object_name_idr, obj->name);
obj->name = 0;
spin_unlock(&dev->object_name_lock); spin_unlock(&dev->object_name_lock);
/* /*
* The object name held a reference to this object, drop * The object name held a reference to this object, drop
...@@ -460,6 +463,26 @@ drm_gem_object_handle_free(struct kref *kref) ...@@ -460,6 +463,26 @@ drm_gem_object_handle_free(struct kref *kref)
} }
EXPORT_SYMBOL(drm_gem_object_handle_free); EXPORT_SYMBOL(drm_gem_object_handle_free);
void drm_gem_vm_open(struct vm_area_struct *vma)
{
struct drm_gem_object *obj = vma->vm_private_data;
drm_gem_object_reference(obj);
}
EXPORT_SYMBOL(drm_gem_vm_open);
void drm_gem_vm_close(struct vm_area_struct *vma)
{
struct drm_gem_object *obj = vma->vm_private_data;
struct drm_device *dev = obj->dev;
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
}
EXPORT_SYMBOL(drm_gem_vm_close);
/** /**
* drm_gem_mmap - memory map routine for GEM objects * drm_gem_mmap - memory map routine for GEM objects
* @filp: DRM file pointer * @filp: DRM file pointer
...@@ -521,6 +544,14 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) ...@@ -521,6 +544,14 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
#endif #endif
vma->vm_page_prot = __pgprot(prot); vma->vm_page_prot = __pgprot(prot);
/* Take a ref for this mapping of the object, so that the fault
* handler can dereference the mmap offset's pointer to the object.
* This reference is cleaned up by the corresponding vm_close
* (which should happen whether the vma was created by this call, or
* by a vm_open due to mremap or partial unmap or whatever).
*/
drm_gem_object_reference(obj);
vma->vm_file = filp; /* Needed for drm_vm_open() */ vma->vm_file = filp; /* Needed for drm_vm_open() */
drm_vm_open_locked(vma); drm_vm_open_locked(vma);
......
...@@ -94,6 +94,8 @@ static int i915_resume(struct drm_device *dev) ...@@ -94,6 +94,8 @@ static int i915_resume(struct drm_device *dev)
static struct vm_operations_struct i915_gem_vm_ops = { static struct vm_operations_struct i915_gem_vm_ops = {
.fault = i915_gem_fault, .fault = i915_gem_fault,
.open = drm_gem_vm_open,
.close = drm_gem_vm_close,
}; };
static struct drm_driver driver = { static struct drm_driver driver = {
......
...@@ -184,6 +184,8 @@ typedef struct drm_i915_private { ...@@ -184,6 +184,8 @@ typedef struct drm_i915_private {
unsigned int lvds_dither:1; unsigned int lvds_dither:1;
unsigned int lvds_vbt:1; unsigned int lvds_vbt:1;
unsigned int int_crt_support:1; unsigned int int_crt_support:1;
unsigned int lvds_use_ssc:1;
int lvds_ssc_freq;
struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */ struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
......
...@@ -607,8 +607,6 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -607,8 +607,6 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
case -EAGAIN: case -EAGAIN:
return VM_FAULT_OOM; return VM_FAULT_OOM;
case -EFAULT: case -EFAULT:
case -EBUSY:
DRM_ERROR("can't insert pfn?? fault or busy...\n");
return VM_FAULT_SIGBUS; return VM_FAULT_SIGBUS;
default: default:
return VM_FAULT_NOPAGE; return VM_FAULT_NOPAGE;
...@@ -684,6 +682,30 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj) ...@@ -684,6 +682,30 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj)
return ret; return ret;
} }
static void
i915_gem_free_mmap_offset(struct drm_gem_object *obj)
{
struct drm_device *dev = obj->dev;
struct drm_i915_gem_object *obj_priv = obj->driver_private;
struct drm_gem_mm *mm = dev->mm_private;
struct drm_map_list *list;
list = &obj->map_list;
drm_ht_remove_item(&mm->offset_hash, &list->hash);
if (list->file_offset_node) {
drm_mm_put_block(list->file_offset_node);
list->file_offset_node = NULL;
}
if (list->map) {
drm_free(list->map, sizeof(struct drm_map), DRM_MEM_DRIVER);
list->map = NULL;
}
obj_priv->mmap_offset = 0;
}
/** /**
* i915_gem_get_gtt_alignment - return required GTT alignment for an object * i915_gem_get_gtt_alignment - return required GTT alignment for an object
* @obj: object to check * @obj: object to check
...@@ -758,8 +780,11 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, ...@@ -758,8 +780,11 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
if (!obj_priv->mmap_offset) { if (!obj_priv->mmap_offset) {
ret = i915_gem_create_mmap_offset(obj); ret = i915_gem_create_mmap_offset(obj);
if (ret) if (ret) {
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return ret; return ret;
}
} }
args->offset = obj_priv->mmap_offset; args->offset = obj_priv->mmap_offset;
...@@ -2251,6 +2276,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, ...@@ -2251,6 +2276,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
(int) reloc.offset, (int) reloc.offset,
reloc.read_domains, reloc.read_domains,
reloc.write_domain); reloc.write_domain);
drm_gem_object_unreference(target_obj);
i915_gem_object_unpin(obj);
return -EINVAL; return -EINVAL;
} }
...@@ -2480,13 +2507,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ...@@ -2480,13 +2507,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
if (dev_priv->mm.wedged) { if (dev_priv->mm.wedged) {
DRM_ERROR("Execbuf while wedged\n"); DRM_ERROR("Execbuf while wedged\n");
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return -EIO; ret = -EIO;
goto pre_mutex_err;
} }
if (dev_priv->mm.suspended) { if (dev_priv->mm.suspended) {
DRM_ERROR("Execbuf while VT-switched.\n"); DRM_ERROR("Execbuf while VT-switched.\n");
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return -EBUSY; ret = -EBUSY;
goto pre_mutex_err;
} }
/* Look up object handles */ /* Look up object handles */
...@@ -2632,15 +2661,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ...@@ -2632,15 +2661,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
i915_verify_inactive(dev, __FILE__, __LINE__); i915_verify_inactive(dev, __FILE__, __LINE__);
/* 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)
DRM_ERROR("failed to copy %d exec entries "
"back to user (%d)\n",
args->buffer_count, ret);
err: err:
for (i = 0; i < pinned; i++) for (i = 0; i < pinned; i++)
i915_gem_object_unpin(object_list[i]); i915_gem_object_unpin(object_list[i]);
...@@ -2650,6 +2670,18 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ...@@ -2650,6 +2670,18 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
mutex_unlock(&dev->struct_mutex); 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)
DRM_ERROR("failed to copy %d exec entries "
"back to user (%d)\n",
args->buffer_count, ret);
}
pre_mutex_err: pre_mutex_err:
drm_free(object_list, sizeof(*object_list) * args->buffer_count, drm_free(object_list, sizeof(*object_list) * args->buffer_count,
DRM_MEM_DRIVER); DRM_MEM_DRIVER);
...@@ -2753,6 +2785,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, ...@@ -2753,6 +2785,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) { if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) {
DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n", DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n",
args->handle); args->handle);
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return -EINVAL; return -EINVAL;
} }
...@@ -2885,9 +2918,6 @@ int i915_gem_init_object(struct drm_gem_object *obj) ...@@ -2885,9 +2918,6 @@ int i915_gem_init_object(struct drm_gem_object *obj)
void i915_gem_free_object(struct drm_gem_object *obj) void i915_gem_free_object(struct drm_gem_object *obj)
{ {
struct drm_device *dev = obj->dev; struct drm_device *dev = obj->dev;
struct drm_gem_mm *mm = dev->mm_private;
struct drm_map_list *list;
struct drm_map *map;
struct drm_i915_gem_object *obj_priv = obj->driver_private; struct drm_i915_gem_object *obj_priv = obj->driver_private;
while (obj_priv->pin_count > 0) while (obj_priv->pin_count > 0)
...@@ -2898,19 +2928,7 @@ void i915_gem_free_object(struct drm_gem_object *obj) ...@@ -2898,19 +2928,7 @@ void i915_gem_free_object(struct drm_gem_object *obj)
i915_gem_object_unbind(obj); i915_gem_object_unbind(obj);
list = &obj->map_list; i915_gem_free_mmap_offset(obj);
drm_ht_remove_item(&mm->offset_hash, &list->hash);
if (list->file_offset_node) {
drm_mm_put_block(list->file_offset_node);
list->file_offset_node = NULL;
}
map = list->map;
if (map) {
drm_free(map, sizeof(*map), DRM_MEM_DRIVER);
list->map = NULL;
}
drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER); drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER);
drm_free(obj->driver_private, 1, DRM_MEM_DRIVER); drm_free(obj->driver_private, 1, DRM_MEM_DRIVER);
...@@ -3095,6 +3113,7 @@ i915_gem_init_hws(struct drm_device *dev) ...@@ -3095,6 +3113,7 @@ i915_gem_init_hws(struct drm_device *dev)
if (dev_priv->hw_status_page == NULL) { if (dev_priv->hw_status_page == NULL) {
DRM_ERROR("Failed to map status page.\n"); DRM_ERROR("Failed to map status page.\n");
memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
i915_gem_object_unpin(obj);
drm_gem_object_unreference(obj); drm_gem_object_unreference(obj);
return -EINVAL; return -EINVAL;
} }
...@@ -3107,6 +3126,27 @@ i915_gem_init_hws(struct drm_device *dev) ...@@ -3107,6 +3126,27 @@ i915_gem_init_hws(struct drm_device *dev)
return 0; return 0;
} }
static void
i915_gem_cleanup_hws(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_gem_object *obj = dev_priv->hws_obj;
struct drm_i915_gem_object *obj_priv = obj->driver_private;
if (dev_priv->hws_obj == NULL)
return;
kunmap(obj_priv->page_list[0]);
i915_gem_object_unpin(obj);
drm_gem_object_unreference(obj);
dev_priv->hws_obj = NULL;
memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
dev_priv->hw_status_page = NULL;
/* Write high address into HWS_PGA when disabling. */
I915_WRITE(HWS_PGA, 0x1ffff000);
}
int int
i915_gem_init_ringbuffer(struct drm_device *dev) i915_gem_init_ringbuffer(struct drm_device *dev)
{ {
...@@ -3124,6 +3164,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev) ...@@ -3124,6 +3164,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
obj = drm_gem_object_alloc(dev, 128 * 1024); obj = drm_gem_object_alloc(dev, 128 * 1024);
if (obj == NULL) { if (obj == NULL) {
DRM_ERROR("Failed to allocate ringbuffer\n"); DRM_ERROR("Failed to allocate ringbuffer\n");
i915_gem_cleanup_hws(dev);
return -ENOMEM; return -ENOMEM;
} }
obj_priv = obj->driver_private; obj_priv = obj->driver_private;
...@@ -3131,6 +3172,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev) ...@@ -3131,6 +3172,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
ret = i915_gem_object_pin(obj, 4096); ret = i915_gem_object_pin(obj, 4096);
if (ret != 0) { if (ret != 0) {
drm_gem_object_unreference(obj); drm_gem_object_unreference(obj);
i915_gem_cleanup_hws(dev);
return ret; return ret;
} }
...@@ -3148,7 +3190,9 @@ i915_gem_init_ringbuffer(struct drm_device *dev) ...@@ -3148,7 +3190,9 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
if (ring->map.handle == NULL) { if (ring->map.handle == NULL) {
DRM_ERROR("Failed to map ringbuffer.\n"); DRM_ERROR("Failed to map ringbuffer.\n");
memset(&dev_priv->ring, 0, sizeof(dev_priv->ring)); memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
i915_gem_object_unpin(obj);
drm_gem_object_unreference(obj); drm_gem_object_unreference(obj);
i915_gem_cleanup_hws(dev);
return -EINVAL; return -EINVAL;
} }
ring->ring_obj = obj; ring->ring_obj = obj;
...@@ -3228,20 +3272,7 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev) ...@@ -3228,20 +3272,7 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev)
dev_priv->ring.ring_obj = NULL; dev_priv->ring.ring_obj = NULL;
memset(&dev_priv->ring, 0, sizeof(dev_priv->ring)); memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
if (dev_priv->hws_obj != NULL) { i915_gem_cleanup_hws(dev);
struct drm_gem_object *obj = dev_priv->hws_obj;
struct drm_i915_gem_object *obj_priv = obj->driver_private;
kunmap(obj_priv->page_list[0]);
i915_gem_object_unpin(obj);
drm_gem_object_unreference(obj);
dev_priv->hws_obj = NULL;
memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
dev_priv->hw_status_page = NULL;
/* Write high address into HWS_PGA when disabling. */
I915_WRITE(HWS_PGA, 0x1ffff000);
}
} }
int int
......
...@@ -299,9 +299,8 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, ...@@ -299,9 +299,8 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
} }
obj_priv->stride = args->stride; obj_priv->stride = args->stride;
mutex_unlock(&dev->struct_mutex);
drm_gem_object_unreference(obj); drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return 0; return 0;
} }
...@@ -340,9 +339,8 @@ i915_gem_get_tiling(struct drm_device *dev, void *data, ...@@ -340,9 +339,8 @@ i915_gem_get_tiling(struct drm_device *dev, void *data,
DRM_ERROR("unknown tiling mode\n"); DRM_ERROR("unknown tiling mode\n");
} }
mutex_unlock(&dev->struct_mutex);
drm_gem_object_unreference(obj); drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return 0; return 0;
} }
...@@ -135,6 +135,14 @@ parse_general_features(struct drm_i915_private *dev_priv, ...@@ -135,6 +135,14 @@ parse_general_features(struct drm_i915_private *dev_priv,
if (general) { if (general) {
dev_priv->int_tv_support = general->int_tv_support; dev_priv->int_tv_support = general->int_tv_support;
dev_priv->int_crt_support = general->int_crt_support; dev_priv->int_crt_support = general->int_crt_support;
dev_priv->lvds_use_ssc = general->enable_ssc;
if (dev_priv->lvds_use_ssc) {
if (IS_I855(dev_priv->dev))
dev_priv->lvds_ssc_freq = general->ssc_freq ? 66 : 48;
else
dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 96;
}
} }
} }
......
This diff is collapsed.
...@@ -473,7 +473,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, ...@@ -473,7 +473,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
ret = intel_framebuffer_create(dev, &mode_cmd, &fb, fbo); ret = intel_framebuffer_create(dev, &mode_cmd, &fb, fbo);
if (ret) { if (ret) {
DRM_ERROR("failed to allocate fb.\n"); DRM_ERROR("failed to allocate fb.\n");
goto out_unref; goto out_unpin;
} }
list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list); list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list);
...@@ -484,7 +484,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, ...@@ -484,7 +484,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
info = framebuffer_alloc(sizeof(struct intelfb_par), device); info = framebuffer_alloc(sizeof(struct intelfb_par), device);
if (!info) { if (!info) {
ret = -ENOMEM; ret = -ENOMEM;
goto out_unref; goto out_unpin;
} }
par = info->par; par = info->par;
...@@ -513,7 +513,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, ...@@ -513,7 +513,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
size); size);
if (!info->screen_base) { if (!info->screen_base) {
ret = -ENOSPC; ret = -ENOSPC;
goto out_unref; goto out_unpin;
} }
info->screen_size = size; info->screen_size = size;
...@@ -608,6 +608,8 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, ...@@ -608,6 +608,8 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return 0; return 0;
out_unpin:
i915_gem_object_unpin(fbo);
out_unref: out_unref:
drm_gem_object_unreference(fbo); drm_gem_object_unreference(fbo);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
......
...@@ -481,8 +481,6 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -481,8 +481,6 @@ void intel_lvds_init(struct drm_device *dev)
if (dev_priv->panel_fixed_mode) { if (dev_priv->panel_fixed_mode) {
dev_priv->panel_fixed_mode->type |= dev_priv->panel_fixed_mode->type |=
DRM_MODE_TYPE_PREFERRED; DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector,
dev_priv->panel_fixed_mode);
goto out; goto out;
} }
} }
......
...@@ -193,7 +193,7 @@ static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr, ...@@ -193,7 +193,7 @@ static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr,
#define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} #define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd}
/** Mapping of command numbers to names, for debug output */ /** Mapping of command numbers to names, for debug output */
const static struct _sdvo_cmd_name { static const struct _sdvo_cmd_name {
u8 cmd; u8 cmd;
char *name; char *name;
} sdvo_cmd_names[] = { } sdvo_cmd_names[] = {
......
...@@ -411,7 +411,7 @@ struct tv_mode { ...@@ -411,7 +411,7 @@ struct tv_mode {
* These values account for -1s required. * These values account for -1s required.
*/ */
const static struct tv_mode tv_modes[] = { static const struct tv_mode tv_modes[] = {
{ {
.name = "NTSC-M", .name = "NTSC-M",
.clock = 107520, .clock = 107520,
......
...@@ -557,8 +557,10 @@ static int radeon_do_engine_reset(struct drm_device * dev) ...@@ -557,8 +557,10 @@ static int radeon_do_engine_reset(struct drm_device * dev)
} }
static void radeon_cp_init_ring_buffer(struct drm_device * dev, static void radeon_cp_init_ring_buffer(struct drm_device * dev,
drm_radeon_private_t * dev_priv) drm_radeon_private_t *dev_priv,
struct drm_file *file_priv)
{ {
struct drm_radeon_master_private *master_priv;
u32 ring_start, cur_read_ptr; u32 ring_start, cur_read_ptr;
u32 tmp; u32 tmp;
...@@ -677,6 +679,14 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev, ...@@ -677,6 +679,14 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
dev_priv->scratch[2] = 0; dev_priv->scratch[2] = 0;
RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0); RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0);
/* reset sarea copies of these */
master_priv = file_priv->master->driver_priv;
if (master_priv->sarea_priv) {
master_priv->sarea_priv->last_frame = 0;
master_priv->sarea_priv->last_dispatch = 0;
master_priv->sarea_priv->last_clear = 0;
}
radeon_do_wait_for_idle(dev_priv); radeon_do_wait_for_idle(dev_priv);
/* Sync everything up */ /* Sync everything up */
...@@ -1215,7 +1225,7 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, ...@@ -1215,7 +1225,7 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
} }
radeon_cp_load_microcode(dev_priv); radeon_cp_load_microcode(dev_priv);
radeon_cp_init_ring_buffer(dev, dev_priv); radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
dev_priv->last_buf = 0; dev_priv->last_buf = 0;
...@@ -1281,7 +1291,7 @@ static int radeon_do_cleanup_cp(struct drm_device * dev) ...@@ -1281,7 +1291,7 @@ static int radeon_do_cleanup_cp(struct drm_device * dev)
* *
* Charl P. Botha <http://cpbotha.net> * Charl P. Botha <http://cpbotha.net>
*/ */
static int radeon_do_resume_cp(struct drm_device * dev) static int radeon_do_resume_cp(struct drm_device *dev, struct drm_file *file_priv)
{ {
drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_private_t *dev_priv = dev->dev_private;
...@@ -1304,7 +1314,7 @@ static int radeon_do_resume_cp(struct drm_device * dev) ...@@ -1304,7 +1314,7 @@ static int radeon_do_resume_cp(struct drm_device * dev)
} }
radeon_cp_load_microcode(dev_priv); radeon_cp_load_microcode(dev_priv);
radeon_cp_init_ring_buffer(dev, dev_priv); radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
radeon_do_engine_reset(dev); radeon_do_engine_reset(dev);
radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
...@@ -1479,8 +1489,7 @@ int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_pri ...@@ -1479,8 +1489,7 @@ int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_pri
*/ */
int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv) int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv)
{ {
return radeon_do_resume_cp(dev, file_priv);
return radeon_do_resume_cp(dev);
} }
int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
......
...@@ -1321,6 +1321,8 @@ void drm_gem_object_free(struct kref *kref); ...@@ -1321,6 +1321,8 @@ void drm_gem_object_free(struct kref *kref);
struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev, struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
size_t size); size_t size);
void drm_gem_object_handle_free(struct kref *kref); void drm_gem_object_handle_free(struct kref *kref);
void drm_gem_vm_open(struct vm_area_struct *vma);
void drm_gem_vm_close(struct vm_area_struct *vma);
int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
static inline void static inline void
......
...@@ -609,7 +609,7 @@ extern char *drm_get_dvi_i_subconnector_name(int val); ...@@ -609,7 +609,7 @@ extern char *drm_get_dvi_i_subconnector_name(int val);
extern char *drm_get_dvi_i_select_name(int val); extern char *drm_get_dvi_i_select_name(int val);
extern char *drm_get_tv_subconnector_name(int val); extern char *drm_get_tv_subconnector_name(int val);
extern char *drm_get_tv_select_name(int val); extern char *drm_get_tv_select_name(int val);
extern void drm_fb_release(struct file *filp); extern void drm_fb_release(struct drm_file *file_priv);
extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group); extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group);
extern struct edid *drm_get_edid(struct drm_connector *connector, extern struct edid *drm_get_edid(struct drm_connector *connector,
struct i2c_adapter *adapter); struct i2c_adapter *adapter);
......
...@@ -54,13 +54,13 @@ struct drm_crtc_helper_funcs { ...@@ -54,13 +54,13 @@ struct drm_crtc_helper_funcs {
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode); struct drm_display_mode *adjusted_mode);
/* Actually set the mode */ /* Actually set the mode */
void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode, int x, int y, struct drm_display_mode *adjusted_mode, int x, int y,
struct drm_framebuffer *old_fb); struct drm_framebuffer *old_fb);
/* Move the crtc on the current fb to the given position *optional* */ /* Move the crtc on the current fb to the given position *optional* */
void (*mode_set_base)(struct drm_crtc *crtc, int x, int y, int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb); struct drm_framebuffer *old_fb);
}; };
struct drm_encoder_helper_funcs { struct drm_encoder_helper_funcs {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment