From 496259048e6c75a212fa1c5bb863cfd6b008903c Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Sun, 5 Feb 2012 22:50:36 +0900 Subject: drm: Fix typo in vmwgfx_drv.c Correct spelling "unsuported" to "unsupported" in drivers/gpu/drm/vmwgfx/vmwgfx_drv.c Signed-off-by: Masanari Iida Signed-off-by: Jiri Kosina --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/vmwgfx') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index f390f5f9cb68..2d6f573bfff2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -430,7 +430,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) svga_id = vmw_read(dev_priv, SVGA_REG_ID); if (svga_id != SVGA_ID_2) { ret = -ENOSYS; - DRM_ERROR("Unsuported SVGA ID 0x%x\n", svga_id); + DRM_ERROR("Unsupported SVGA ID 0x%x\n", svga_id); mutex_unlock(&dev_priv->hw_mutex); goto out_err0; } -- cgit v1.2.3 From fb2a99e15ff0d342de4ba58c84a791224a96a01a Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 6 Feb 2012 10:58:19 +0100 Subject: drm: do not set fb_info->pixmap fields The drm drivers set the fb_info->pixmap fields without setting fb_info->pixmap.addr. If this is not set the fb core will overwrite these all fb_info->pixmap fields anyway, so there is not much point in setting them in the first place. [airlied: dropped nvidiafb piece - not mine] Signed-off-by: Sascha Hauer Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/framebuffer.c | 6 +----- drivers/gpu/drm/i915/intel_fb.c | 6 +----- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 6 +----- drivers/gpu/drm/radeon/radeon_fb.c | 6 +----- drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 14 +------------- 5 files changed, 5 insertions(+), 33 deletions(-) (limited to 'drivers/gpu/drm/vmwgfx') diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 78733b5fd3fb..c1c4dc174fa2 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -507,11 +507,7 @@ static int psbfb_create(struct psb_fbdev *fbdev, info->fix.mmio_start = pci_resource_start(dev->pdev, 0); info->fix.mmio_len = pci_resource_len(dev->pdev, 0); - info->pixmap.size = 64 * 1024; - info->pixmap.buf_align = 8; - info->pixmap.access_align = 32; - info->pixmap.flags = FB_PIXMAP_SYSTEM; - info->pixmap.scan_align = 1; + /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ dev_info(dev->dev, "allocated %dx%d fb\n", psbfb->base.width, psbfb->base.height); diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 571375a3eef4..2d8766978388 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -152,11 +152,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev, drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); - info->pixmap.size = 64*1024; - info->pixmap.buf_align = 8; - info->pixmap.access_align = 32; - info->pixmap.flags = FB_PIXMAP_SYSTEM; - info->pixmap.scan_align = 1; + /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n", fb->width, fb->height, diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 9892218d7452..8113e9201ed9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -381,11 +381,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, goto out_unref; } - info->pixmap.size = 64*1024; - info->pixmap.buf_align = 8; - info->pixmap.access_align = 32; - info->pixmap.flags = FB_PIXMAP_SYSTEM; - info->pixmap.scan_align = 1; + /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index cf2bf35b56b8..a5692d5f415d 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -254,11 +254,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev, info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base; info->apertures->ranges[0].size = rdev->mc.aper_size; - info->pixmap.size = 64*1024; - info->pixmap.buf_align = 8; - info->pixmap.access_align = 32; - info->pixmap.flags = FB_PIXMAP_SYSTEM; - info->pixmap.scan_align = 1; + /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ if (info->screen_base == NULL) { ret = -ENOSPC; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index 34e51a1695b8..67f1d54b79b4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c @@ -515,19 +515,7 @@ int vmw_fb_init(struct vmw_private *vmw_priv) info->var.xres = initial_width; info->var.yres = initial_height; -#if 0 - info->pixmap.size = 64*1024; - info->pixmap.buf_align = 8; - info->pixmap.access_align = 32; - info->pixmap.flags = FB_PIXMAP_SYSTEM; - info->pixmap.scan_align = 1; -#else - info->pixmap.size = 0; - info->pixmap.buf_align = 8; - info->pixmap.access_align = 32; - info->pixmap.flags = FB_PIXMAP_SYSTEM; - info->pixmap.scan_align = 1; -#endif + /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ info->apertures = alloc_apertures(1); if (!info->apertures) { -- cgit v1.2.3 From 8b7de6aa84682a3396544fd88cd457f95484573a Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Thu, 9 Feb 2012 16:56:41 +0100 Subject: vmwgfx: Rework fence event action Signed-off-by: Jakob Bornecrantz Reviewed-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 12 ++ drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 210 +++++++++++++++------------------- 2 files changed, 104 insertions(+), 118 deletions(-) (limited to 'drivers/gpu/drm/vmwgfx') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index dc279706ca70..7f09db178fce 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -657,6 +657,18 @@ int vmw_overlay_unref(struct vmw_private *dev_priv, uint32_t stream_id); int vmw_overlay_num_overlays(struct vmw_private *dev_priv); int vmw_overlay_num_free_overlays(struct vmw_private *dev_priv); +/** + * Fence function - vmwgfx_fence.c + */ + +int vmw_event_fence_action_queue(struct drm_file *file_priv, + struct vmw_fence_obj *fence, + struct drm_pending_event *event, + uint32_t *tv_sec, + uint32_t *tv_usec, + bool interruptible); + + /** * GMR Id manager */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index 15fb26088d68..ea9d0450b8a7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -69,12 +69,12 @@ struct vmw_user_fence { * be assigned the current time tv_usec val when the fence signals. */ struct vmw_event_fence_action { - struct drm_pending_event e; struct vmw_fence_action action; + + struct drm_pending_event *event; struct vmw_fence_obj *fence; struct drm_device *dev; - struct kref kref; - uint32_t size; + uint32_t *tv_sec; uint32_t *tv_usec; }; @@ -783,49 +783,6 @@ int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data, TTM_REF_USAGE); } -/** - * vmw_event_fence_action_destroy - * - * @kref: The struct kref embedded in a struct vmw_event_fence_action. - * - * The vmw_event_fence_action destructor that may be called either after - * the fence action cleanup, or when the event is delivered. - * It frees both the vmw_event_fence_action struct and the actual - * event structure copied to user-space. - */ -static void vmw_event_fence_action_destroy(struct kref *kref) -{ - struct vmw_event_fence_action *eaction = - container_of(kref, struct vmw_event_fence_action, kref); - struct ttm_mem_global *mem_glob = - vmw_mem_glob(vmw_priv(eaction->dev)); - uint32_t size = eaction->size; - - kfree(eaction->e.event); - kfree(eaction); - ttm_mem_global_free(mem_glob, size); -} - - -/** - * vmw_event_fence_action_delivered - * - * @e: The struct drm_pending_event embedded in a struct - * vmw_event_fence_action. - * - * The struct drm_pending_event destructor that is called by drm - * once the event is delivered. Since we don't know whether this function - * will be called before or after the fence action destructor, we - * free a refcount and destroy if it becomes zero. - */ -static void vmw_event_fence_action_delivered(struct drm_pending_event *e) -{ - struct vmw_event_fence_action *eaction = - container_of(e, struct vmw_event_fence_action, e); - - kref_put(&eaction->kref, vmw_event_fence_action_destroy); -} - /** * vmw_event_fence_action_seq_passed @@ -836,18 +793,16 @@ static void vmw_event_fence_action_delivered(struct drm_pending_event *e) * This function is called when the seqno of the fence where @action is * attached has passed. It queues the event on the submitter's event list. * This function is always called from atomic context, and may be called - * from irq context. It ups a refcount reflecting that we now have two - * destructors. + * from irq context. */ static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action) { struct vmw_event_fence_action *eaction = container_of(action, struct vmw_event_fence_action, action); struct drm_device *dev = eaction->dev; - struct drm_file *file_priv = eaction->e.file_priv; + struct drm_file *file_priv = eaction->event->file_priv; unsigned long irq_flags; - kref_get(&eaction->kref); spin_lock_irqsave(&dev->event_lock, irq_flags); if (likely(eaction->tv_sec != NULL)) { @@ -858,7 +813,7 @@ static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action) *eaction->tv_usec = tv.tv_usec; } - list_add_tail(&eaction->e.link, &file_priv->event_list); + list_add_tail(&eaction->event->link, &file_priv->event_list); wake_up_all(&file_priv->event_wait); spin_unlock_irqrestore(&dev->event_lock, irq_flags); } @@ -878,7 +833,7 @@ static void vmw_event_fence_action_cleanup(struct vmw_fence_action *action) container_of(action, struct vmw_event_fence_action, action); vmw_fence_obj_unreference(&eaction->fence); - kref_put(&eaction->kref, vmw_event_fence_action_destroy); + kfree(eaction); } @@ -946,39 +901,22 @@ void vmw_fence_obj_add_action(struct vmw_fence_obj *fence, * an error code, the caller needs to free that object. */ -int vmw_event_fence_action_create(struct drm_file *file_priv, - struct vmw_fence_obj *fence, - struct drm_event *event, - uint32_t *tv_sec, - uint32_t *tv_usec, - bool interruptible) +int vmw_event_fence_action_queue(struct drm_file *file_priv, + struct vmw_fence_obj *fence, + struct drm_pending_event *event, + uint32_t *tv_sec, + uint32_t *tv_usec, + bool interruptible) { struct vmw_event_fence_action *eaction; - struct ttm_mem_global *mem_glob = - vmw_mem_glob(fence->fman->dev_priv); struct vmw_fence_manager *fman = fence->fman; - uint32_t size = fman->event_fence_action_size + - ttm_round_pot(event->length); - int ret; - - /* - * Account for internal structure size as well as the - * event size itself. - */ - ret = ttm_mem_global_alloc(mem_glob, size, false, interruptible); - if (unlikely(ret != 0)) - return ret; eaction = kzalloc(sizeof(*eaction), GFP_KERNEL); - if (unlikely(eaction == NULL)) { - ttm_mem_global_free(mem_glob, size); + if (unlikely(eaction == NULL)) return -ENOMEM; - } - eaction->e.event = event; - eaction->e.file_priv = file_priv; - eaction->e.destroy = vmw_event_fence_action_delivered; + eaction->event = event; eaction->action.seq_passed = vmw_event_fence_action_seq_passed; eaction->action.cleanup = vmw_event_fence_action_cleanup; @@ -986,16 +924,85 @@ int vmw_event_fence_action_create(struct drm_file *file_priv, eaction->fence = vmw_fence_obj_reference(fence); eaction->dev = fman->dev_priv->dev; - eaction->size = size; eaction->tv_sec = tv_sec; eaction->tv_usec = tv_usec; - kref_init(&eaction->kref); vmw_fence_obj_add_action(fence, &eaction->action); return 0; } +struct vmw_event_fence_pending { + struct drm_pending_event base; + struct drm_vmw_event_fence event; +}; + +int vmw_event_fence_action_create(struct drm_file *file_priv, + struct vmw_fence_obj *fence, + uint32_t flags, + uint64_t user_data, + bool interruptible) +{ + struct vmw_event_fence_pending *event; + struct drm_device *dev = fence->fman->dev_priv->dev; + unsigned long irq_flags; + int ret; + + spin_lock_irqsave(&dev->event_lock, irq_flags); + + ret = (file_priv->event_space < sizeof(event->event)) ? -EBUSY : 0; + if (likely(ret == 0)) + file_priv->event_space -= sizeof(event->event); + + spin_unlock_irqrestore(&dev->event_lock, irq_flags); + + if (unlikely(ret != 0)) { + DRM_ERROR("Failed to allocate event space for this file.\n"); + goto out_no_space; + } + + + event = kzalloc(sizeof(event->event), GFP_KERNEL); + if (unlikely(event == NULL)) { + DRM_ERROR("Failed to allocate an event.\n"); + ret = -ENOMEM; + goto out_no_event; + } + + event->event.base.type = DRM_VMW_EVENT_FENCE_SIGNALED; + event->event.base.length = sizeof(*event); + event->event.user_data = user_data; + + event->base.event = &event->event.base; + event->base.file_priv = file_priv; + event->base.destroy = (void (*) (struct drm_pending_event *)) kfree; + + + if (flags & DRM_VMW_FE_FLAG_REQ_TIME) + ret = vmw_event_fence_action_queue(file_priv, fence, + &event->base, + &event->event.tv_sec, + &event->event.tv_usec, + interruptible); + else + ret = vmw_event_fence_action_queue(file_priv, fence, + &event->base, + NULL, + NULL, + interruptible); + if (ret != 0) + goto out_no_queue; + +out_no_queue: + event->base.destroy(&event->base); +out_no_event: + spin_lock_irqsave(&dev->event_lock, irq_flags); + file_priv->event_space += sizeof(*event); + spin_unlock_irqrestore(&dev->event_lock, irq_flags); +out_no_space: + return ret; +} + int vmw_fence_event_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -1008,8 +1015,6 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data, (struct drm_vmw_fence_rep __user *)(unsigned long) arg->fence_rep; uint32_t handle; - unsigned long irq_flags; - struct drm_vmw_event_fence *event; int ret; /* @@ -1062,59 +1067,28 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data, BUG_ON(fence == NULL); - spin_lock_irqsave(&dev->event_lock, irq_flags); - - ret = (file_priv->event_space < sizeof(*event)) ? -EBUSY : 0; - if (likely(ret == 0)) - file_priv->event_space -= sizeof(*event); - - spin_unlock_irqrestore(&dev->event_lock, irq_flags); - - if (unlikely(ret != 0)) { - DRM_ERROR("Failed to allocate event space for this file.\n"); - goto out_no_event_space; - } - - event = kzalloc(sizeof(*event), GFP_KERNEL); - if (unlikely(event == NULL)) { - DRM_ERROR("Failed to allocate an event.\n"); - goto out_no_event; - } - - event->base.type = DRM_VMW_EVENT_FENCE_SIGNALED; - event->base.length = sizeof(*event); - event->user_data = arg->user_data; - if (arg->flags & DRM_VMW_FE_FLAG_REQ_TIME) ret = vmw_event_fence_action_create(file_priv, fence, - &event->base, - &event->tv_sec, - &event->tv_usec, + arg->flags, + arg->user_data, true); else ret = vmw_event_fence_action_create(file_priv, fence, - &event->base, - NULL, - NULL, + arg->flags, + arg->user_data, true); if (unlikely(ret != 0)) { if (ret != -ERESTARTSYS) DRM_ERROR("Failed to attach event to fence.\n"); - goto out_no_attach; + goto out_no_create; } vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep, fence, handle); vmw_fence_obj_unreference(&fence); return 0; -out_no_attach: - kfree(event); -out_no_event: - spin_lock_irqsave(&dev->event_lock, irq_flags); - file_priv->event_space += sizeof(*event); - spin_unlock_irqrestore(&dev->event_lock, irq_flags); -out_no_event_space: +out_no_create: if (user_fence_rep != NULL) ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, handle, TTM_REF_USAGE); -- cgit v1.2.3 From 6b82ef50d8617f3fcd51dda9d89d973fe3bc65b8 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 9 Feb 2012 16:56:42 +0100 Subject: vmwgfx: Clean up pending event references to struct drm_file objects on close Pending events may have stale pointer references to struct drm_file objects after a file has been closed, but before the event is supposed to be attached to the drm file. Remove such events on file close. Tested with "modetest". Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 11 +++++++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 60 +++++++++++++++++++++++++++++++++-- drivers/gpu/drm/vmwgfx/vmwgfx_fence.h | 3 ++ 4 files changed, 73 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/vmwgfx') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index f390f5f9cb68..28f59a3c38d9 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -688,6 +688,15 @@ static int vmw_driver_unload(struct drm_device *dev) return 0; } +static void vmw_preclose(struct drm_device *dev, + struct drm_file *file_priv) +{ + struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv); + struct vmw_private *dev_priv = vmw_priv(dev); + + vmw_event_fence_fpriv_gone(dev_priv->fman, &vmw_fp->fence_events); +} + static void vmw_postclose(struct drm_device *dev, struct drm_file *file_priv) { @@ -710,6 +719,7 @@ static int vmw_driver_open(struct drm_device *dev, struct drm_file *file_priv) if (unlikely(vmw_fp == NULL)) return ret; + INIT_LIST_HEAD(&vmw_fp->fence_events); vmw_fp->tfile = ttm_object_file_init(dev_priv->tdev, 10); if (unlikely(vmw_fp->tfile == NULL)) goto out_no_tfile; @@ -1102,6 +1112,7 @@ static struct drm_driver driver = { .master_set = vmw_master_set, .master_drop = vmw_master_drop, .open = vmw_driver_open, + .preclose = vmw_preclose, .postclose = vmw_postclose, .fops = &vmwgfx_driver_fops, .name = VMWGFX_DRIVER_NAME, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 7f09db178fce..93505ce0ed10 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -62,6 +62,7 @@ struct vmw_fpriv { struct drm_master *locked_master; struct ttm_object_file *tfile; + struct list_head fence_events; }; struct vmw_dma_buffer { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index ea9d0450b8a7..f2fb8f15e2f1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -70,6 +70,7 @@ struct vmw_user_fence { */ struct vmw_event_fence_action { struct vmw_fence_action action; + struct list_head fpriv_head; struct drm_pending_event *event; struct vmw_fence_obj *fence; @@ -783,6 +784,43 @@ int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data, TTM_REF_USAGE); } +/** + * vmw_event_fence_fpriv_gone - Remove references to struct drm_file objects + * + * @fman: Pointer to a struct vmw_fence_manager + * @event_list: Pointer to linked list of struct vmw_event_fence_action objects + * with pointers to a struct drm_file object about to be closed. + * + * This function removes all pending fence events with references to a + * specific struct drm_file object about to be closed. The caller is required + * to pass a list of all struct vmw_event_fence_action objects with such + * events attached. This function is typically called before the + * struct drm_file object's event management is taken down. + */ +void vmw_event_fence_fpriv_gone(struct vmw_fence_manager *fman, + struct list_head *event_list) +{ + struct vmw_event_fence_action *eaction; + struct drm_pending_event *event; + unsigned long irq_flags; + + while (1) { + spin_lock_irqsave(&fman->lock, irq_flags); + if (list_empty(event_list)) + goto out_unlock; + eaction = list_first_entry(event_list, + struct vmw_event_fence_action, + fpriv_head); + list_del_init(&eaction->fpriv_head); + event = eaction->event; + eaction->event = NULL; + spin_unlock_irqrestore(&fman->lock, irq_flags); + event->destroy(event); + } +out_unlock: + spin_unlock_irqrestore(&fman->lock, irq_flags); +} + /** * vmw_event_fence_action_seq_passed @@ -800,9 +838,14 @@ static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action) struct vmw_event_fence_action *eaction = container_of(action, struct vmw_event_fence_action, action); struct drm_device *dev = eaction->dev; - struct drm_file *file_priv = eaction->event->file_priv; + struct drm_pending_event *event = eaction->event; + struct drm_file *file_priv; unsigned long irq_flags; + if (unlikely(event == NULL)) + return; + + file_priv = event->file_priv; spin_lock_irqsave(&dev->event_lock, irq_flags); if (likely(eaction->tv_sec != NULL)) { @@ -813,7 +856,9 @@ static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action) *eaction->tv_usec = tv.tv_usec; } + list_del_init(&eaction->fpriv_head); list_add_tail(&eaction->event->link, &file_priv->event_list); + eaction->event = NULL; wake_up_all(&file_priv->event_wait); spin_unlock_irqrestore(&dev->event_lock, irq_flags); } @@ -831,6 +876,12 @@ static void vmw_event_fence_action_cleanup(struct vmw_fence_action *action) { struct vmw_event_fence_action *eaction = container_of(action, struct vmw_event_fence_action, action); + struct vmw_fence_manager *fman = eaction->fence->fman; + unsigned long irq_flags; + + spin_lock_irqsave(&fman->lock, irq_flags); + list_del(&eaction->fpriv_head); + spin_unlock_irqrestore(&fman->lock, irq_flags); vmw_fence_obj_unreference(&eaction->fence); kfree(eaction); @@ -910,7 +961,8 @@ int vmw_event_fence_action_queue(struct drm_file *file_priv, { struct vmw_event_fence_action *eaction; struct vmw_fence_manager *fman = fence->fman; - + struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv); + unsigned long irq_flags; eaction = kzalloc(sizeof(*eaction), GFP_KERNEL); if (unlikely(eaction == NULL)) @@ -927,6 +979,10 @@ int vmw_event_fence_action_queue(struct drm_file *file_priv, eaction->tv_sec = tv_sec; eaction->tv_usec = tv_usec; + spin_lock_irqsave(&fman->lock, irq_flags); + list_add_tail(&eaction->fpriv_head, &vmw_fp->fence_events); + spin_unlock_irqrestore(&fman->lock, irq_flags); + vmw_fence_obj_add_action(fence, &eaction->action); return 0; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h index 0854a2096b55..8767fc13265d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h @@ -109,5 +109,8 @@ extern int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int vmw_fence_event_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern void vmw_event_fence_fpriv_gone(struct vmw_fence_manager *fman, + struct list_head *event_list); + #endif /* _VMWGFX_FENCE_H_ */ -- cgit v1.2.3 From bb1bd2f43ee15386a1c3f96cbcbb9302a9994443 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Thu, 9 Feb 2012 16:56:43 +0100 Subject: vmwgfx: Make it possible to get fence from execbuf Signed-off-by: Jakob Bornecrantz Reviewed-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 3 ++- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 15 +++++++++++---- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 10 +++++----- 3 files changed, 18 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/vmwgfx') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 93505ce0ed10..14c2f49b21ea 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -534,7 +534,8 @@ extern int vmw_execbuf_process(struct drm_file *file_priv, uint32_t command_size, uint64_t throttle_us, struct drm_vmw_fence_rep __user - *user_fence_rep); + *user_fence_rep, + struct vmw_fence_obj **out_fence); extern void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 40932fbdac0f..4acced44a623 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -1109,10 +1109,11 @@ int vmw_execbuf_process(struct drm_file *file_priv, void *kernel_commands, uint32_t command_size, uint64_t throttle_us, - struct drm_vmw_fence_rep __user *user_fence_rep) + struct drm_vmw_fence_rep __user *user_fence_rep, + struct vmw_fence_obj **out_fence) { struct vmw_sw_context *sw_context = &dev_priv->ctx; - struct vmw_fence_obj *fence; + struct vmw_fence_obj *fence = NULL; uint32_t handle; void *cmd; int ret; @@ -1208,8 +1209,13 @@ int vmw_execbuf_process(struct drm_file *file_priv, vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret, user_fence_rep, fence, handle); - if (likely(fence != NULL)) + /* Don't unreference when handing fence out */ + if (unlikely(out_fence != NULL)) { + *out_fence = fence; + fence = NULL; + } else if (likely(fence != NULL)) { vmw_fence_obj_unreference(&fence); + } mutex_unlock(&dev_priv->cmdbuf_mutex); return 0; @@ -1362,7 +1368,8 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data, ret = vmw_execbuf_process(file_priv, dev_priv, (void __user *)(unsigned long)arg->commands, NULL, arg->command_size, arg->throttle_us, - (void __user *)(unsigned long)arg->fence_rep); + (void __user *)(unsigned long)arg->fence_rep, + NULL); if (unlikely(ret != 0)) goto out_unlock; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index b66ef0e3cde1..12619c33953b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -547,7 +547,7 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv, fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num; cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header)); ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, - fifo_size, 0, NULL); + fifo_size, 0, NULL, NULL); if (unlikely(ret != 0)) break; @@ -809,7 +809,7 @@ static int do_dmabuf_define_gmrfb(struct drm_file *file_priv, cmd->body.ptr.offset = 0; ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, - fifo_size, 0, NULL); + fifo_size, 0, NULL, NULL); kfree(cmd); @@ -896,7 +896,7 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv, fifo_size = sizeof(*blits) * hit_num; ret = vmw_execbuf_process(file_priv, dev_priv, NULL, blits, - fifo_size, 0, NULL); + fifo_size, 0, NULL, NULL); if (unlikely(ret != 0)) break; @@ -1296,7 +1296,7 @@ int vmw_kms_present(struct vmw_private *dev_priv, fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num; cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header)); ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, - fifo_size, 0, NULL); + fifo_size, 0, NULL, NULL); if (unlikely(ret != 0)) break; @@ -1409,7 +1409,7 @@ int vmw_kms_readback(struct vmw_private *dev_priv, fifo_size = sizeof(*cmd) + sizeof(*blits) * blits_pos; ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, fifo_size, - 0, user_fence_rep); + 0, user_fence_rep, NULL); kfree(cmd); -- cgit v1.2.3 From bd49ae46f8a24c088dbca12064a846399e2da631 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Thu, 9 Feb 2012 16:56:44 +0100 Subject: vmwgfx: Pipe fence out of screen object dirty functions Signed-off-by: Jakob Bornecrantz Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/vmwgfx') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 12619c33953b..24efcae3e2f5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -422,7 +422,8 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv, struct vmw_framebuffer *framebuffer, unsigned flags, unsigned color, struct drm_clip_rect *clips, - unsigned num_clips, int inc) + unsigned num_clips, int inc, + struct vmw_fence_obj **out_fence) { struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS]; struct drm_clip_rect *clips_ptr; @@ -542,12 +543,15 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv, if (num == 0) continue; + /* only return the last fence */ + if (out_fence && *out_fence) + vmw_fence_obj_unreference(out_fence); /* recalculate package length */ fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num; cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header)); ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, - fifo_size, 0, NULL, NULL); + fifo_size, 0, NULL, out_fence); if (unlikely(ret != 0)) break; @@ -598,7 +602,7 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer, ret = do_surface_dirty_sou(dev_priv, file_priv, &vfbs->base, flags, color, - clips, num_clips, inc); + clips, num_clips, inc, NULL); ttm_read_unlock(&vmaster->lock); return 0; @@ -821,7 +825,8 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv, struct vmw_framebuffer *framebuffer, unsigned flags, unsigned color, struct drm_clip_rect *clips, - unsigned num_clips, int increment) + unsigned num_clips, int increment, + struct vmw_fence_obj **out_fence) { struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS]; struct drm_clip_rect *clips_ptr; @@ -894,9 +899,13 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv, if (hit_num == 0) continue; + /* only return the last fence */ + if (out_fence && *out_fence) + vmw_fence_obj_unreference(out_fence); + fifo_size = sizeof(*blits) * hit_num; ret = vmw_execbuf_process(file_priv, dev_priv, NULL, blits, - fifo_size, 0, NULL, NULL); + fifo_size, 0, NULL, out_fence); if (unlikely(ret != 0)) break; @@ -942,7 +951,7 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, } else { ret = do_dmabuf_dirty_sou(file_priv, dev_priv, &vfbd->base, flags, color, - clips, num_clips, increment); + clips, num_clips, increment, NULL); } ttm_read_unlock(&vmaster->lock); -- cgit v1.2.3 From b5ec427e8d8c66ea1bb9a3bf09663c1361ecf0b6 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Thu, 9 Feb 2012 16:56:45 +0100 Subject: vmwgfx: Add page flip support Signed-off-by: Jakob Bornecrantz Reviewed-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 64 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 8 +++++ drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 34 +++++++++++++++++++ 3 files changed, 106 insertions(+) (limited to 'drivers/gpu/drm/vmwgfx') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 24efcae3e2f5..2286d47e5022 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1681,6 +1681,70 @@ int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num, return 0; } +int vmw_du_page_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event) +{ + struct vmw_private *dev_priv = vmw_priv(crtc->dev); + struct drm_framebuffer *old_fb = crtc->fb; + struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb); + struct drm_file *file_priv = event->base.file_priv; + struct vmw_fence_obj *fence = NULL; + struct drm_clip_rect clips; + int ret; + + /* require ScreenObject support for page flipping */ + if (!dev_priv->sou_priv) + return -ENOSYS; + + if (!vmw_kms_screen_object_flippable(dev_priv, crtc)) + return -EINVAL; + + crtc->fb = fb; + + /* do a full screen dirty update */ + clips.x1 = clips.y1 = 0; + clips.x2 = fb->width; + clips.y2 = fb->height; + + if (vfb->dmabuf) + ret = do_dmabuf_dirty_sou(file_priv, dev_priv, vfb, + 0, 0, &clips, 1, 1, &fence); + else + ret = do_surface_dirty_sou(dev_priv, file_priv, vfb, + 0, 0, &clips, 1, 1, &fence); + + + if (ret != 0) + goto out_no_fence; + if (!fence) { + ret = -EINVAL; + goto out_no_fence; + } + + ret = vmw_event_fence_action_queue(file_priv, fence, + &event->base, + &event->event.tv_sec, + &event->event.tv_usec, + true); + + /* + * No need to hold on to this now. The only cleanup + * we need to do if we fail is unref the fence. + */ + vmw_fence_obj_unreference(&fence); + + if (vmw_crtc_to_du(crtc)->is_implicit) + vmw_kms_screen_object_update_implicit_fb(dev_priv, crtc); + + return ret; + +out_no_fence: + crtc->fb = old_fb; + return ret; +} + + void vmw_du_crtc_save(struct drm_crtc *crtc) { } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index a4f7f034996a..8184bc5b1730 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -121,6 +121,9 @@ struct vmw_display_unit { * Shared display unit functions - vmwgfx_kms.c */ void vmw_display_unit_cleanup(struct vmw_display_unit *du); +int vmw_du_page_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event); void vmw_du_crtc_save(struct drm_crtc *crtc); void vmw_du_crtc_restore(struct drm_crtc *crtc); void vmw_du_crtc_gamma_set(struct drm_crtc *crtc, @@ -154,5 +157,10 @@ int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv); int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv); int vmw_kms_sou_update_layout(struct vmw_private *dev_priv, unsigned num, struct drm_vmw_rect *rects); +bool vmw_kms_screen_object_flippable(struct vmw_private *dev_priv, + struct drm_crtc *crtc); +void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv, + struct drm_crtc *crtc); + #endif diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 4defdcf1c72e..97aca0bf94d0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -394,6 +394,7 @@ static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = { .gamma_set = vmw_du_crtc_gamma_set, .destroy = vmw_sou_crtc_destroy, .set_config = vmw_sou_crtc_set_config, + .page_flip = vmw_du_page_flip, }; /* @@ -535,3 +536,36 @@ int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv) return 0; } + +/** + * Returns if this unit can be page flipped. + * Must be called with the mode_config mutex held. + */ +bool vmw_kms_screen_object_flippable(struct vmw_private *dev_priv, + struct drm_crtc *crtc) +{ + struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc); + + if (!sou->base.is_implicit) + return true; + + if (dev_priv->sou_priv->num_implicit != 1) + return false; + + return true; +} + +/** + * Update the implicit fb to the current fb of this crtc. + * Must be called with the mode_config mutex held. + */ +void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv, + struct drm_crtc *crtc) +{ + struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc); + + BUG_ON(!sou->base.is_implicit); + + dev_priv->sou_priv->implicit_fb = + vmw_framebuffer_to_vfb(sou->base.crtc.fb); +} -- cgit v1.2.3 From eb4f923b1ceac8a618469c51ff249bd89bc0dfa4 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Thu, 9 Feb 2012 16:56:46 +0100 Subject: vmwgfx: Pick up the initial size from the width and height regs Signed-off-by: Jakob Bornecrantz Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 32 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 2 ++ drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 8 ++------ drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 4 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 4 ++-- 5 files changed, 40 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/vmwgfx') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 28f59a3c38d9..12272329d91b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -38,6 +38,10 @@ #define VMWGFX_CHIP_SVGAII 0 #define VMW_FB_RESERVATION 0 +#define VMW_MIN_INITIAL_WIDTH 800 +#define VMW_MIN_INITIAL_HEIGHT 600 + + /** * Fully encoded drm commands. Might move to vmw_drm.h */ @@ -387,6 +391,31 @@ void vmw_3d_resource_dec(struct vmw_private *dev_priv, BUG_ON(n3d < 0); } +/** + * Sets the initial_[width|height] fields on the given vmw_private. + * + * It does so by reading SVGA_REG_[WIDTH|HEIGHT] regs and then + * capping the value to fb_max_[width|height] fields and the + * VMW_MIN_INITIAL_[WIDTH|HEIGHT]. + */ +static void vmw_get_initial_size(struct vmw_private *dev_priv) +{ + uint32_t width; + uint32_t height; + + width = vmw_read(dev_priv, SVGA_REG_WIDTH); + height = vmw_read(dev_priv, SVGA_REG_HEIGHT); + + width = max_t(uint32_t, width, VMW_MIN_INITIAL_WIDTH); + width = min_t(uint32_t, width, dev_priv->fb_max_width); + + height = max_t(uint32_t, height, VMW_MIN_INITIAL_HEIGHT); + height = min_t(uint32_t, height, dev_priv->fb_max_height); + + dev_priv->initial_width = width; + dev_priv->initial_height = height; +} + static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) { struct vmw_private *dev_priv; @@ -441,6 +470,9 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->mmio_size = vmw_read(dev_priv, SVGA_REG_MEM_SIZE); dev_priv->fb_max_width = vmw_read(dev_priv, SVGA_REG_MAX_WIDTH); dev_priv->fb_max_height = vmw_read(dev_priv, SVGA_REG_MAX_HEIGHT); + + vmw_get_initial_size(dev_priv); + if (dev_priv->capabilities & SVGA_CAP_GMR) { dev_priv->max_gmr_descriptors = vmw_read(dev_priv, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 14c2f49b21ea..28664156a1d8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -203,6 +203,8 @@ struct vmw_private { uint32_t mmio_size; uint32_t fb_max_width; uint32_t fb_max_height; + uint32_t initial_width; + uint32_t initial_height; __le32 __iomem *mmio_virt; int mmio_mtrr; uint32_t capabilities; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index 67f1d54b79b4..3c447bf317cb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c @@ -414,10 +414,6 @@ int vmw_fb_init(struct vmw_private *vmw_priv) unsigned fb_bpp, fb_depth, fb_offset, fb_pitch, fb_size; int ret; - /* XXX These shouldn't be hardcoded. */ - initial_width = 800; - initial_height = 600; - fb_bpp = 32; fb_depth = 24; @@ -425,8 +421,8 @@ int vmw_fb_init(struct vmw_private *vmw_priv) fb_width = min(vmw_priv->fb_max_width, (unsigned)2048); fb_height = min(vmw_priv->fb_max_height, (unsigned)2048); - initial_width = min(fb_width, initial_width); - initial_height = min(fb_height, initial_height); + initial_width = min(vmw_priv->initial_width, fb_width); + initial_height = min(vmw_priv->initial_height, fb_height); fb_pitch = fb_width * fb_bpp / 8; fb_size = fb_pitch * fb_height; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index f77b184be807..070fb239c5af 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -354,8 +354,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) INIT_LIST_HEAD(&ldu->active); ldu->base.pref_active = (unit == 0); - ldu->base.pref_width = 800; - ldu->base.pref_height = 600; + ldu->base.pref_width = dev_priv->initial_width; + ldu->base.pref_height = dev_priv->initial_height; ldu->base.pref_mode = NULL; ldu->base.is_implicit = true; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 97aca0bf94d0..6deaf2f8bab1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -449,8 +449,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) sou->active_implicit = false; sou->base.pref_active = (unit == 0); - sou->base.pref_width = 800; - sou->base.pref_height = 600; + sou->base.pref_width = dev_priv->initial_width; + sou->base.pref_height = dev_priv->initial_height; sou->base.pref_mode = NULL; sou->base.is_implicit = true; -- cgit v1.2.3 From 67d4a87b0a6bf7225aacc2c14e3542ec2f6b803f Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 9 Feb 2012 16:56:47 +0100 Subject: drm/vmwgfx: Treat out-of-range initial width and height as host errors And assign the initial width and height to the minimum in that case. Strange values (-1) from these registers have been reported by users. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/vmwgfx') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 12272329d91b..f076f66b1153 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -395,7 +395,9 @@ void vmw_3d_resource_dec(struct vmw_private *dev_priv, * Sets the initial_[width|height] fields on the given vmw_private. * * It does so by reading SVGA_REG_[WIDTH|HEIGHT] regs and then - * capping the value to fb_max_[width|height] fields and the + * clamping the value to fb_max_[width|height] fields and the + * VMW_MIN_INITIAL_[WIDTH|HEIGHT]. + * If the values appear to be invalid, set them to * VMW_MIN_INITIAL_[WIDTH|HEIGHT]. */ static void vmw_get_initial_size(struct vmw_private *dev_priv) @@ -407,10 +409,18 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv) height = vmw_read(dev_priv, SVGA_REG_HEIGHT); width = max_t(uint32_t, width, VMW_MIN_INITIAL_WIDTH); - width = min_t(uint32_t, width, dev_priv->fb_max_width); - height = max_t(uint32_t, height, VMW_MIN_INITIAL_HEIGHT); - height = min_t(uint32_t, height, dev_priv->fb_max_height); + + if (width > dev_priv->fb_max_width || + height > dev_priv->fb_max_height) { + + /* + * This is a host error and shouldn't occur. + */ + + width = VMW_MIN_INITIAL_WIDTH; + height = VMW_MIN_INITIAL_HEIGHT; + } dev_priv->initial_width = width; dev_priv->initial_height = height; -- cgit v1.2.3 From f9cd8ec34f240884cf7ec44e1a4cac12c167ecb2 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 9 Feb 2012 16:56:48 +0100 Subject: vmwgfx: Move function declaration to correct header Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 12 ------------ drivers/gpu/drm/vmwgfx/vmwgfx_fence.h | 8 ++++++-- 2 files changed, 6 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/drm/vmwgfx') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 28664156a1d8..a393bdcfd4b3 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -661,18 +661,6 @@ int vmw_overlay_unref(struct vmw_private *dev_priv, uint32_t stream_id); int vmw_overlay_num_overlays(struct vmw_private *dev_priv); int vmw_overlay_num_free_overlays(struct vmw_private *dev_priv); -/** - * Fence function - vmwgfx_fence.c - */ - -int vmw_event_fence_action_queue(struct drm_file *file_priv, - struct vmw_fence_obj *fence, - struct drm_pending_event *event, - uint32_t *tv_sec, - uint32_t *tv_usec, - bool interruptible); - - /** * GMR Id manager */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h index 8767fc13265d..faf2e7873860 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h @@ -111,6 +111,10 @@ extern int vmw_fence_event_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern void vmw_event_fence_fpriv_gone(struct vmw_fence_manager *fman, struct list_head *event_list); - - +extern int vmw_event_fence_action_queue(struct drm_file *filee_priv, + struct vmw_fence_obj *fence, + struct drm_pending_event *event, + uint32_t *tv_sec, + uint32_t *tv_usec, + bool interruptible); #endif /* _VMWGFX_FENCE_H_ */ -- cgit v1.2.3 From 0a240ec43667c6e1005a566dde60863b9c16cc21 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 9 Feb 2012 16:56:49 +0100 Subject: drm/vmwgfx: Bump driver minor Bump driver minor to signal availability of the page-flip ioctl. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/vmwgfx') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index a393bdcfd4b3..d0f2c079ee27 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -40,9 +40,9 @@ #include "ttm/ttm_module.h" #include "vmwgfx_fence.h" -#define VMWGFX_DRIVER_DATE "20111025" +#define VMWGFX_DRIVER_DATE "20120209" #define VMWGFX_DRIVER_MAJOR 2 -#define VMWGFX_DRIVER_MINOR 3 +#define VMWGFX_DRIVER_MINOR 4 #define VMWGFX_DRIVER_PATCHLEVEL 0 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024) -- cgit v1.2.3 From 466e69b8b03b8c1987367912782bc12988ad8794 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 19 Dec 2011 11:15:29 +0000 Subject: drm: move pci bus master enable into driver. The current enabling of bus mastering in the drm midlayer allows a large race condition under kexec. When a kexec'ed kernel re-enables bus mastering for the GPU, previously setup dma blocks may cause writes to random pieces of memory. On radeon the writeback mechanism can cause these sorts of issues. This patch doesn't fix the problem, but it moves the bus master enable under the individual drivers control so they can move enabling it until later in their load cycle and close the race. Fix for radeon kms driver will be in a follow-up patch. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_pci.c | 2 -- drivers/gpu/drm/gma500/psb_drv.c | 2 ++ drivers/gpu/drm/i810/i810_dma.c | 2 ++ drivers/gpu/drm/i915/i915_dma.c | 2 ++ drivers/gpu/drm/mga/mga_dma.c | 2 ++ drivers/gpu/drm/nouveau/nouveau_state.c | 2 ++ drivers/gpu/drm/r128/r128_drv.c | 1 + drivers/gpu/drm/radeon/radeon_cp.c | 2 ++ drivers/gpu/drm/radeon/radeon_kms.c | 2 ++ drivers/gpu/drm/sis/sis_drv.c | 2 ++ drivers/gpu/drm/via/via_map.c | 2 ++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 2 ++ 12 files changed, 21 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/vmwgfx') diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index d4d10b7880cf..13f3d936472f 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -324,8 +324,6 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, if (ret) goto err_g1; - pci_set_master(pdev); - dev->pdev = pdev; dev->dev = &pdev->dev; diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index f14768f2b364..1f57aac2cf80 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -283,6 +283,8 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->dev = dev; dev->dev_private = (void *) dev_priv; + pci_set_master(dev->pdev); + if (!IS_PSB(dev)) { if (pci_enable_msi(dev->pdev)) dev_warn(dev->dev, "Enabling MSI failed!\n"); diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index 7f4b4e10246e..64a989ed5b8f 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -1208,6 +1208,8 @@ int i810_driver_load(struct drm_device *dev, unsigned long flags) dev->types[8] = _DRM_STAT_SECONDARY; dev->types[9] = _DRM_STAT_DMA; + pci_set_master(dev->pdev); + return 0; } diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 8919dcc07ed8..a8081f2efaea 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1933,6 +1933,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto free_priv; } + pci_set_master(dev->pdev); + /* overlay on gen2 is broken and can't address above 1G */ if (IS_GEN2(dev)) dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(30)); diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c index 5ccb65deb83c..507aa3df0168 100644 --- a/drivers/gpu/drm/mga/mga_dma.c +++ b/drivers/gpu/drm/mga/mga_dma.c @@ -403,6 +403,8 @@ int mga_driver_load(struct drm_device *dev, unsigned long flags) dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT; dev_priv->chipset = flags; + pci_set_master(dev->pdev); + dev_priv->mmio_base = pci_resource_start(dev->pdev, 1); dev_priv->mmio_size = pci_resource_len(dev->pdev, 1); diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index f80c5e0762ff..912839c2bc16 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -1002,6 +1002,8 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) dev->dev_private = dev_priv; dev_priv->dev = dev; + pci_set_master(dev->pdev); + dev_priv->flags = flags & NOUVEAU_FLAGS; NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n", diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c index 6a5f4395838f..88718fad5d6d 100644 --- a/drivers/gpu/drm/r128/r128_drv.c +++ b/drivers/gpu/drm/r128/r128_drv.c @@ -85,6 +85,7 @@ static struct drm_driver driver = { int r128_driver_load(struct drm_device *dev, unsigned long flags) { + pci_set_master(dev->pdev); return drm_vblank_init(dev, 1); } diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index 72ae8266b8e9..0ebb7d4796fa 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -2115,6 +2115,8 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) break; } + pci_set_master(dev->pdev); + if (drm_pci_device_is_agp(dev)) dev_priv->flags |= RADEON_IS_AGP; else if (pci_is_pcie(dev->pdev)) diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index d3352889a870..1986ebae1ef2 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -57,6 +57,8 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) } dev->dev_private = (void *)rdev; + pci_set_master(dev->pdev); + /* update BUS flag */ if (drm_pci_device_is_agp(dev)) { flags |= RADEON_IS_AGP; diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index 573220cc5269..30d98d14b5c5 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -41,6 +41,8 @@ static int sis_driver_load(struct drm_device *dev, unsigned long chipset) { drm_sis_private_t *dev_priv; + pci_set_master(dev->pdev); + dev_priv = kzalloc(sizeof(drm_sis_private_t), GFP_KERNEL); if (dev_priv == NULL) return -ENOMEM; diff --git a/drivers/gpu/drm/via/via_map.c b/drivers/gpu/drm/via/via_map.c index a2ab34365151..1f182254e81e 100644 --- a/drivers/gpu/drm/via/via_map.c +++ b/drivers/gpu/drm/via/via_map.c @@ -106,6 +106,8 @@ int via_driver_load(struct drm_device *dev, unsigned long chipset) idr_init(&dev->object_name_idr); + pci_set_master(dev->pdev); + ret = drm_vblank_init(dev, 1); if (ret) { kfree(dev_priv); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index f076f66b1153..1760aba9ecef 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -439,6 +439,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) } memset(dev_priv, 0, sizeof(*dev_priv)); + pci_set_master(dev->pdev); + dev_priv->dev = dev; dev_priv->vmw_chipset = chipset; dev_priv->last_read_seqno = (uint32_t) -100; -- cgit v1.2.3 From 1c9c20f60230bd5a6195d41f9dd2dfa60874b1da Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Fri, 25 Nov 2011 23:14:20 +0800 Subject: drm: remove the second argument of k[un]map_atomic() Signed-off-by: Cong Wang --- drivers/gpu/drm/drm_cache.c | 8 ++++---- drivers/gpu/drm/ttm/ttm_tt.c | 16 ++++++++-------- drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c | 6 +++--- 3 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm/vmwgfx') diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c index 592865381c6e..4b8653b932f9 100644 --- a/drivers/gpu/drm/drm_cache.c +++ b/drivers/gpu/drm/drm_cache.c @@ -41,10 +41,10 @@ drm_clflush_page(struct page *page) if (unlikely(page == NULL)) return; - page_virtual = kmap_atomic(page, KM_USER0); + page_virtual = kmap_atomic(page); for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) clflush(page_virtual + i); - kunmap_atomic(page_virtual, KM_USER0); + kunmap_atomic(page_virtual); } static void drm_cache_flush_clflush(struct page *pages[], @@ -87,10 +87,10 @@ drm_clflush_pages(struct page *pages[], unsigned long num_pages) if (unlikely(page == NULL)) continue; - page_virtual = kmap_atomic(page, KM_USER0); + page_virtual = kmap_atomic(page); flush_dcache_range((unsigned long)page_virtual, (unsigned long)page_virtual + PAGE_SIZE); - kunmap_atomic(page_virtual, KM_USER0); + kunmap_atomic(page_virtual); } #else printk(KERN_ERR "Architecture has no drm_cache.c support\n"); diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 2f75d203a2bf..c10cf5e2443a 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -309,11 +309,11 @@ int ttm_tt_swapin(struct ttm_tt *ttm) goto out_err; preempt_disable(); - from_virtual = kmap_atomic(from_page, KM_USER0); - to_virtual = kmap_atomic(to_page, KM_USER1); + from_virtual = kmap_atomic(from_page); + to_virtual = kmap_atomic(to_page); memcpy(to_virtual, from_virtual, PAGE_SIZE); - kunmap_atomic(to_virtual, KM_USER1); - kunmap_atomic(from_virtual, KM_USER0); + kunmap_atomic(to_virtual); + kunmap_atomic(from_virtual); preempt_enable(); page_cache_release(from_page); } @@ -365,11 +365,11 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage) goto out_err; } preempt_disable(); - from_virtual = kmap_atomic(from_page, KM_USER0); - to_virtual = kmap_atomic(to_page, KM_USER1); + from_virtual = kmap_atomic(from_page); + to_virtual = kmap_atomic(to_page); memcpy(to_virtual, from_virtual, PAGE_SIZE); - kunmap_atomic(to_virtual, KM_USER1); - kunmap_atomic(from_virtual, KM_USER0); + kunmap_atomic(to_virtual); + kunmap_atomic(from_virtual); preempt_enable(); set_page_dirty(to_page); mark_page_accessed(to_page); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c index f4e7763a7694..51c9ba5cd2fb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c @@ -136,10 +136,10 @@ static int vmw_gmr_build_descriptors(struct list_head *desc_pages, if (likely(page_virtual != NULL)) { desc_virtual->ppn = page_to_pfn(page); - kunmap_atomic(page_virtual, KM_USER0); + kunmap_atomic(page_virtual); } - page_virtual = kmap_atomic(page, KM_USER0); + page_virtual = kmap_atomic(page); desc_virtual = page_virtual - 1; prev_pfn = ~(0UL); @@ -169,7 +169,7 @@ static int vmw_gmr_build_descriptors(struct list_head *desc_pages, } if (likely(page_virtual != NULL)) - kunmap_atomic(page_virtual, KM_USER0); + kunmap_atomic(page_virtual); return 0; out_err: -- cgit v1.2.3