1ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom/************************************************************************** 2ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * 3ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * Copyright © 2011 VMware, Inc., Palo Alto, CA., USA 4ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * All Rights Reserved. 5ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * 6ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * Permission is hereby granted, free of charge, to any person obtaining a 7ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * copy of this software and associated documentation files (the 8ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * "Software"), to deal in the Software without restriction, including 9ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * without limitation the rights to use, copy, modify, merge, publish, 10ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * distribute, sub license, and/or sell copies of the Software, and to 11ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * permit persons to whom the Software is furnished to do so, subject to 12ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * the following conditions: 13ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * 14ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * The above copyright notice and this permission notice (including the 15ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * next paragraph) shall be included in all copies or substantial portions 16ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * of the Software. 17ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * 18ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 22ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * USE OR OTHER DEALINGS IN THE SOFTWARE. 25ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * 26ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom **************************************************************************/ 27ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 28ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom#include "drmP.h" 29ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom#include "vmwgfx_drv.h" 30ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 31ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom#define VMW_FENCE_WRAP (1 << 31) 32ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 33ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromstruct vmw_fence_manager { 34ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom int num_fence_objects; 35ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_private *dev_priv; 36ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spinlock_t lock; 37ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct list_head fence_list; 38ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct work_struct work; 39ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom u32 user_fence_size; 40ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom u32 fence_size; 4157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom u32 event_fence_action_size; 42ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom bool fifo_down; 43ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct list_head cleanup_list; 4457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom uint32_t pending_actions[VMW_ACTION_MAX]; 4557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct mutex goal_irq_mutex; 4657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom bool goal_irq_on; /* Protected by @goal_irq_mutex */ 4757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom bool seqno_valid; /* Protected by @lock, and may not be set to true 4857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom without the @goal_irq_mutex held. */ 49ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom}; 50ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 51ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromstruct vmw_user_fence { 52ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct ttm_base_object base; 53ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_obj fence; 54ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom}; 55ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 56ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom/** 5757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * struct vmw_event_fence_action - fence action that delivers a drm event. 58ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * 5957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @e: A struct drm_pending_event that controls the event delivery. 6057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @action: A struct vmw_fence_action to hook up to a fence. 6157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @fence: A referenced pointer to the fence to keep it alive while @action 6257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * hangs on it. 6357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @dev: Pointer to a struct drm_device so we can access the event stuff. 6457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @kref: Both @e and @action has destructors, so we need to refcount. 6557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @size: Size accounted for this object. 6657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @tv_sec: If non-null, the variable pointed to will be assigned 6757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * current time tv_sec val when the fence signals. 6857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @tv_usec: Must be set if @tv_sec is set, and the variable pointed to will 6957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * be assigned the current time tv_usec val when the fence signals. 7057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom */ 7157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstromstruct vmw_event_fence_action { 7257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct vmw_fence_action action; 736b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom struct list_head fpriv_head; 748b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz 758b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz struct drm_pending_event *event; 7657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct vmw_fence_obj *fence; 7757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct drm_device *dev; 788b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz 7957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom uint32_t *tv_sec; 8057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom uint32_t *tv_usec; 8157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom}; 8257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 8357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom/** 8457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * Note on fencing subsystem usage of irqs: 8557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * Typically the vmw_fences_update function is called 8657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * 8757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * a) When a new fence seqno has been submitted by the fifo code. 8857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * b) On-demand when we have waiters. Sleeping waiters will switch on the 8957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * ANY_FENCE irq and call vmw_fences_update function each time an ANY_FENCE 9057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * irq is received. When the last fence waiter is gone, that IRQ is masked 9157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * away. 9257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * 9357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * In situations where there are no waiters and we don't submit any new fences, 9457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * fence objects may not be signaled. This is perfectly OK, since there are 9557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * no consumers of the signaled data, but that is NOT ok when there are fence 9657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * actions attached to a fence. The fencing subsystem then makes use of the 9757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * FENCE_GOAL irq and sets the fence goal seqno to that of the next fence 9857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * which has an action attached, and each time vmw_fences_update is called, 9957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * the subsystem makes sure the fence goal seqno is updated. 10057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * 10157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * The fence goal seqno irq is on as long as there are unsignaled fence 10257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * objects with actions attached to them. 103ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom */ 104ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 105ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromstatic void vmw_fence_obj_destroy_locked(struct kref *kref) 106ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 107ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_obj *fence = 108ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom container_of(kref, struct vmw_fence_obj, kref); 109ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 110ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_manager *fman = fence->fman; 111ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom unsigned int num_fences; 112ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 113ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom list_del_init(&fence->head); 114ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom num_fences = --fman->num_fence_objects; 115ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_unlock_irq(&fman->lock); 116ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (fence->destroy) 117ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fence->destroy(fence); 118ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom else 119ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom kfree(fence); 120ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 121ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_lock_irq(&fman->lock); 122ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 123ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 124ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 125ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom/** 126ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * Execute signal actions on fences recently signaled. 127ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * This is done from a workqueue so we don't have to execute 128ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * signal actions from atomic context. 129ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom */ 130ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 131ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromstatic void vmw_fence_work_func(struct work_struct *work) 132ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 133ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_manager *fman = 134ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom container_of(work, struct vmw_fence_manager, work); 135ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct list_head list; 136ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_action *action, *next_action; 13757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom bool seqno_valid; 138ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 139ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom do { 140ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom INIT_LIST_HEAD(&list); 14157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom mutex_lock(&fman->goal_irq_mutex); 14257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 143ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_lock_irq(&fman->lock); 144ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom list_splice_init(&fman->cleanup_list, &list); 14557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom seqno_valid = fman->seqno_valid; 146ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_unlock_irq(&fman->lock); 147ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 14857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (!seqno_valid && fman->goal_irq_on) { 14957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom fman->goal_irq_on = false; 15057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom vmw_goal_waiter_remove(fman->dev_priv); 15157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } 15257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom mutex_unlock(&fman->goal_irq_mutex); 15357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 154ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (list_empty(&list)) 155ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return; 156ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 157ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom /* 158ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * At this point, only we should be able to manipulate the 159ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * list heads of the actions we have on the private list. 16057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * hence fman::lock not held. 161ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom */ 162ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 163ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom list_for_each_entry_safe(action, next_action, &list, head) { 164ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom list_del_init(&action->head); 16557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (action->cleanup) 16657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom action->cleanup(action); 167ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom } 168ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom } while (1); 169ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 170ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 171ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromstruct vmw_fence_manager *vmw_fence_manager_init(struct vmw_private *dev_priv) 172ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 173ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_manager *fman = kzalloc(sizeof(*fman), GFP_KERNEL); 174ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 175ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (unlikely(fman == NULL)) 176ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return NULL; 177ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 178ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fman->dev_priv = dev_priv; 179ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_lock_init(&fman->lock); 180ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom INIT_LIST_HEAD(&fman->fence_list); 181ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom INIT_LIST_HEAD(&fman->cleanup_list); 182ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom INIT_WORK(&fman->work, &vmw_fence_work_func); 183ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fman->fifo_down = true; 184ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fman->user_fence_size = ttm_round_pot(sizeof(struct vmw_user_fence)); 185ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fman->fence_size = ttm_round_pot(sizeof(struct vmw_fence_obj)); 18657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom fman->event_fence_action_size = 18757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom ttm_round_pot(sizeof(struct vmw_event_fence_action)); 18857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom mutex_init(&fman->goal_irq_mutex); 189ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 190ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return fman; 191ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 192ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 193ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromvoid vmw_fence_manager_takedown(struct vmw_fence_manager *fman) 194ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 195ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom unsigned long irq_flags; 196ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom bool lists_empty; 197ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 198ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom (void) cancel_work_sync(&fman->work); 199ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 200ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_lock_irqsave(&fman->lock, irq_flags); 201ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom lists_empty = list_empty(&fman->fence_list) && 202ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom list_empty(&fman->cleanup_list); 203ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_unlock_irqrestore(&fman->lock, irq_flags); 204ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 205ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom BUG_ON(!lists_empty); 206ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom kfree(fman); 207ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 208ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 209ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromstatic int vmw_fence_obj_init(struct vmw_fence_manager *fman, 210ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_obj *fence, 211ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom u32 seqno, 212ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom uint32_t mask, 213ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom void (*destroy) (struct vmw_fence_obj *fence)) 214ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 215ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom unsigned long irq_flags; 216ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom unsigned int num_fences; 217ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom int ret = 0; 218ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 219ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fence->seqno = seqno; 220ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom INIT_LIST_HEAD(&fence->seq_passed_actions); 221ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fence->fman = fman; 222ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fence->signaled = 0; 223ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fence->signal_mask = mask; 224ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom kref_init(&fence->kref); 225ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fence->destroy = destroy; 226ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom init_waitqueue_head(&fence->queue); 227ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 228ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_lock_irqsave(&fman->lock, irq_flags); 229ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (unlikely(fman->fifo_down)) { 230ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ret = -EBUSY; 231ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom goto out_unlock; 232ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom } 233ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom list_add_tail(&fence->head, &fman->fence_list); 234ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom num_fences = ++fman->num_fence_objects; 235ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 236ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromout_unlock: 237ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_unlock_irqrestore(&fman->lock, irq_flags); 238ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return ret; 239ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 240ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 241ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 242ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromstruct vmw_fence_obj *vmw_fence_obj_reference(struct vmw_fence_obj *fence) 243ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 244e93daed8e2fd5ce3dc98efe9938426127a534cccThomas Hellstrom if (unlikely(fence == NULL)) 245e93daed8e2fd5ce3dc98efe9938426127a534cccThomas Hellstrom return NULL; 246e93daed8e2fd5ce3dc98efe9938426127a534cccThomas Hellstrom 247ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom kref_get(&fence->kref); 248ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return fence; 249ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 250ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 251ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom/** 252ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * vmw_fence_obj_unreference 253ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * 254ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * Note that this function may not be entered with disabled irqs since 255ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * it may re-enable them in the destroy function. 256ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * 257ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom */ 258ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromvoid vmw_fence_obj_unreference(struct vmw_fence_obj **fence_p) 259ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 260ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_obj *fence = *fence_p; 261e93daed8e2fd5ce3dc98efe9938426127a534cccThomas Hellstrom struct vmw_fence_manager *fman; 262e93daed8e2fd5ce3dc98efe9938426127a534cccThomas Hellstrom 263e93daed8e2fd5ce3dc98efe9938426127a534cccThomas Hellstrom if (unlikely(fence == NULL)) 264e93daed8e2fd5ce3dc98efe9938426127a534cccThomas Hellstrom return; 265ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 266e93daed8e2fd5ce3dc98efe9938426127a534cccThomas Hellstrom fman = fence->fman; 267ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom *fence_p = NULL; 268ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_lock_irq(&fman->lock); 269ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom BUG_ON(atomic_read(&fence->kref.refcount) == 0); 270ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom kref_put(&fence->kref, vmw_fence_obj_destroy_locked); 271ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_unlock_irq(&fman->lock); 272ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 273ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 274ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromvoid vmw_fences_perform_actions(struct vmw_fence_manager *fman, 275ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct list_head *list) 276ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 277ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_action *action, *next_action; 278ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 279ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom list_for_each_entry_safe(action, next_action, list, head) { 280ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom list_del_init(&action->head); 28157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom fman->pending_actions[action->type]--; 282ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (action->seq_passed != NULL) 283ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom action->seq_passed(action); 284ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 285ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom /* 286ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * Add the cleanup action to the cleanup list so that 287ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * it will be performed by a worker task. 288ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom */ 289ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 29057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom list_add_tail(&action->head, &fman->cleanup_list); 29157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } 29257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom} 29357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 29457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom/** 29557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * vmw_fence_goal_new_locked - Figure out a new device fence goal 29657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * seqno if needed. 29757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * 29857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @fman: Pointer to a fence manager. 29957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @passed_seqno: The seqno the device currently signals as passed. 30057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * 30157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * This function should be called with the fence manager lock held. 30257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * It is typically called when we have a new passed_seqno, and 30357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * we might need to update the fence goal. It checks to see whether 30457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * the current fence goal has already passed, and, in that case, 30557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * scans through all unsignaled fences to get the next fence object with an 30657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * action attached, and sets the seqno of that fence as a new fence goal. 30757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * 30857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * returns true if the device goal seqno was updated. False otherwise. 30957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom */ 31057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstromstatic bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman, 31157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom u32 passed_seqno) 31257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom{ 31357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom u32 goal_seqno; 31457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom __le32 __iomem *fifo_mem; 31557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct vmw_fence_obj *fence; 31657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 31757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (likely(!fman->seqno_valid)) 31857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom return false; 31957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 32057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom fifo_mem = fman->dev_priv->mmio_virt; 32157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom goal_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE_GOAL); 32257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (likely(passed_seqno - goal_seqno >= VMW_FENCE_WRAP)) 32357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom return false; 32457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 32557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom fman->seqno_valid = false; 32657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom list_for_each_entry(fence, &fman->fence_list, head) { 32757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (!list_empty(&fence->seq_passed_actions)) { 32857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom fman->seqno_valid = true; 32957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom iowrite32(fence->seqno, 33057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom fifo_mem + SVGA_FIFO_FENCE_GOAL); 33157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom break; 33257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } 333ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom } 33457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 33557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom return true; 33657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom} 33757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 33857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 33957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom/** 34057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * vmw_fence_goal_check_locked - Replace the device fence goal seqno if 34157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * needed. 34257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * 34357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @fence: Pointer to a struct vmw_fence_obj the seqno of which should be 34457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * considered as a device fence goal. 34557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * 34657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * This function should be called with the fence manager lock held. 34757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * It is typically called when an action has been attached to a fence to 34857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * check whether the seqno of that fence should be used for a fence 34957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * goal interrupt. This is typically needed if the current fence goal is 35057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * invalid, or has a higher seqno than that of the current fence object. 35157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * 35257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * returns true if the device goal seqno was updated. False otherwise. 35357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom */ 35457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstromstatic bool vmw_fence_goal_check_locked(struct vmw_fence_obj *fence) 35557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom{ 35657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom u32 goal_seqno; 35757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom __le32 __iomem *fifo_mem; 35857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 35957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (fence->signaled & DRM_VMW_FENCE_FLAG_EXEC) 36057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom return false; 36157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 36257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom fifo_mem = fence->fman->dev_priv->mmio_virt; 36357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom goal_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE_GOAL); 36457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (likely(fence->fman->seqno_valid && 36557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom goal_seqno - fence->seqno < VMW_FENCE_WRAP)) 36657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom return false; 36757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 36857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom iowrite32(fence->seqno, fifo_mem + SVGA_FIFO_FENCE_GOAL); 36957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom fence->fman->seqno_valid = true; 37057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 37157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom return true; 372ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 373ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 37457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstromvoid vmw_fences_update(struct vmw_fence_manager *fman) 375ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 376ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom unsigned long flags; 377ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_obj *fence, *next_fence; 378ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct list_head action_list; 37957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom bool needs_rerun; 38057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom uint32_t seqno, new_seqno; 38157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom __le32 __iomem *fifo_mem = fman->dev_priv->mmio_virt; 382ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 38357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE); 38457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstromrerun: 385ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_lock_irqsave(&fman->lock, flags); 386ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom list_for_each_entry_safe(fence, next_fence, &fman->fence_list, head) { 387ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (seqno - fence->seqno < VMW_FENCE_WRAP) { 388ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom list_del_init(&fence->head); 389ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fence->signaled |= DRM_VMW_FENCE_FLAG_EXEC; 390ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom INIT_LIST_HEAD(&action_list); 391ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom list_splice_init(&fence->seq_passed_actions, 392ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom &action_list); 393ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom vmw_fences_perform_actions(fman, &action_list); 394ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom wake_up_all(&fence->queue); 39557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } else 39657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom break; 397ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom } 39857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 39957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom needs_rerun = vmw_fence_goal_new_locked(fman, seqno); 40057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 401ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (!list_empty(&fman->cleanup_list)) 402ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom (void) schedule_work(&fman->work); 403ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_unlock_irqrestore(&fman->lock, flags); 404ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 40557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom /* 40657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * Rerun if the fence goal seqno was updated, and the 40757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * hardware might have raced with that update, so that 40857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * we missed a fence_goal irq. 40957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom */ 41057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 41157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (unlikely(needs_rerun)) { 41257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom new_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE); 41357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (new_seqno != seqno) { 41457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom seqno = new_seqno; 41557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom goto rerun; 41657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } 41757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } 41857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom} 419ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 420ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrombool vmw_fence_obj_signaled(struct vmw_fence_obj *fence, 421ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom uint32_t flags) 422ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 423ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_manager *fman = fence->fman; 424ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom unsigned long irq_flags; 425ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom uint32_t signaled; 426ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 427ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_lock_irqsave(&fman->lock, irq_flags); 428ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom signaled = fence->signaled; 429ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_unlock_irqrestore(&fman->lock, irq_flags); 430ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 431ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom flags &= fence->signal_mask; 432ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if ((signaled & flags) == flags) 433ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return 1; 434ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 43557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if ((signaled & DRM_VMW_FENCE_FLAG_EXEC) == 0) 43657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom vmw_fences_update(fman); 437ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 438ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_lock_irqsave(&fman->lock, irq_flags); 439ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom signaled = fence->signaled; 440ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_unlock_irqrestore(&fman->lock, irq_flags); 441ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 442ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return ((signaled & flags) == flags); 443ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 444ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 445ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromint vmw_fence_obj_wait(struct vmw_fence_obj *fence, 446ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom uint32_t flags, bool lazy, 447ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom bool interruptible, unsigned long timeout) 448ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 449ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_private *dev_priv = fence->fman->dev_priv; 450ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom long ret; 451ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 452ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (likely(vmw_fence_obj_signaled(fence, flags))) 453ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return 0; 454ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 455ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC); 456ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom vmw_seqno_waiter_add(dev_priv); 457ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 458ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (interruptible) 459ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ret = wait_event_interruptible_timeout 460ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom (fence->queue, 461ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom vmw_fence_obj_signaled(fence, flags), 462ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom timeout); 463ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom else 464ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ret = wait_event_timeout 465ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom (fence->queue, 466ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom vmw_fence_obj_signaled(fence, flags), 467ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom timeout); 468ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 469ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom vmw_seqno_waiter_remove(dev_priv); 470ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 471ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (unlikely(ret == 0)) 472ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ret = -EBUSY; 473ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom else if (likely(ret > 0)) 474ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ret = 0; 475ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 476ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return ret; 477ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 478ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 479ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromvoid vmw_fence_obj_flush(struct vmw_fence_obj *fence) 480ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 481ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_private *dev_priv = fence->fman->dev_priv; 482ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 483ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC); 484ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 485ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 486ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromstatic void vmw_fence_destroy(struct vmw_fence_obj *fence) 487ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 488ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_manager *fman = fence->fman; 489ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 490ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom kfree(fence); 491ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom /* 492ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * Free kernel space accounting. 493ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom */ 494ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ttm_mem_global_free(vmw_mem_glob(fman->dev_priv), 495ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fman->fence_size); 496ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 497ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 498ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromint vmw_fence_create(struct vmw_fence_manager *fman, 499ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom uint32_t seqno, 500ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom uint32_t mask, 501ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_obj **p_fence) 502ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 503ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct ttm_mem_global *mem_glob = vmw_mem_glob(fman->dev_priv); 504ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_obj *fence; 505ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom int ret; 506ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 507ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ret = ttm_mem_global_alloc(mem_glob, fman->fence_size, 508ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom false, false); 509ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (unlikely(ret != 0)) 510ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return ret; 511ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 512ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fence = kzalloc(sizeof(*fence), GFP_KERNEL); 513ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (unlikely(fence == NULL)) { 514ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ret = -ENOMEM; 515ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom goto out_no_object; 516ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom } 517ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 518ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ret = vmw_fence_obj_init(fman, fence, seqno, mask, 519ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom vmw_fence_destroy); 520ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (unlikely(ret != 0)) 521ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom goto out_err_init; 522ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 523ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom *p_fence = fence; 524ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return 0; 525ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 526ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromout_err_init: 527ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom kfree(fence); 528ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromout_no_object: 529ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ttm_mem_global_free(mem_glob, fman->fence_size); 530ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return ret; 531ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 532ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 533ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 534ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromstatic void vmw_user_fence_destroy(struct vmw_fence_obj *fence) 535ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 536ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_user_fence *ufence = 537ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom container_of(fence, struct vmw_user_fence, fence); 538ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_manager *fman = fence->fman; 539ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 540ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom kfree(ufence); 541ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom /* 542ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * Free kernel space accounting. 543ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom */ 544ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ttm_mem_global_free(vmw_mem_glob(fman->dev_priv), 545ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fman->user_fence_size); 546ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 547ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 548ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromstatic void vmw_user_fence_base_release(struct ttm_base_object **p_base) 549ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 550ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct ttm_base_object *base = *p_base; 551ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_user_fence *ufence = 552ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom container_of(base, struct vmw_user_fence, base); 553ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_obj *fence = &ufence->fence; 554ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 555ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom *p_base = NULL; 556ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom vmw_fence_obj_unreference(&fence); 557ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 558ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 559ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromint vmw_user_fence_create(struct drm_file *file_priv, 560ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_manager *fman, 561ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom uint32_t seqno, 562ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom uint32_t mask, 563ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_obj **p_fence, 564ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom uint32_t *p_handle) 565ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 566ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 567ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_user_fence *ufence; 568ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_obj *tmp; 569ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct ttm_mem_global *mem_glob = vmw_mem_glob(fman->dev_priv); 570ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom int ret; 571ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 572ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom /* 573ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * Kernel memory space accounting, since this object may 574ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * be created by a user-space request. 575ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom */ 576ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 577ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ret = ttm_mem_global_alloc(mem_glob, fman->user_fence_size, 578ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom false, false); 579ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (unlikely(ret != 0)) 580ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return ret; 581ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 582ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ufence = kzalloc(sizeof(*ufence), GFP_KERNEL); 583ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (unlikely(ufence == NULL)) { 584ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ret = -ENOMEM; 585ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom goto out_no_object; 586ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom } 587ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 588ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ret = vmw_fence_obj_init(fman, &ufence->fence, seqno, 589ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom mask, vmw_user_fence_destroy); 590ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (unlikely(ret != 0)) { 591ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom kfree(ufence); 592ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom goto out_no_object; 593ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom } 594ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 595ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom /* 596ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * The base object holds a reference which is freed in 597ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * vmw_user_fence_base_release. 598ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom */ 599ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom tmp = vmw_fence_obj_reference(&ufence->fence); 600ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ret = ttm_base_object_init(tfile, &ufence->base, false, 601ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom VMW_RES_FENCE, 602ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom &vmw_user_fence_base_release, NULL); 603ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 604ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 605ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (unlikely(ret != 0)) { 606ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom /* 607ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * Free the base object's reference 608ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom */ 609ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom vmw_fence_obj_unreference(&tmp); 610ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom goto out_err; 611ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom } 612ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 613ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom *p_fence = &ufence->fence; 614ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom *p_handle = ufence->base.hash.key; 615ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 616ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return 0; 617ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromout_err: 618ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom tmp = &ufence->fence; 619ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom vmw_fence_obj_unreference(&tmp); 620ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromout_no_object: 621ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ttm_mem_global_free(mem_glob, fman->user_fence_size); 622ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return ret; 623ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 624ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 625ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 626ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom/** 627ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * vmw_fence_fifo_down - signal all unsignaled fence objects. 628ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom */ 629ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 630ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromvoid vmw_fence_fifo_down(struct vmw_fence_manager *fman) 631ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 632ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom unsigned long irq_flags; 633ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct list_head action_list; 634ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom int ret; 635ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 636ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom /* 637ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * The list may be altered while we traverse it, so always 638ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * restart when we've released the fman->lock. 639ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom */ 640ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 641ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_lock_irqsave(&fman->lock, irq_flags); 642ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fman->fifo_down = true; 643ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom while (!list_empty(&fman->fence_list)) { 644ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_obj *fence = 645ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom list_entry(fman->fence_list.prev, struct vmw_fence_obj, 646ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom head); 647ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom kref_get(&fence->kref); 648ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_unlock_irq(&fman->lock); 649ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 650ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ret = vmw_fence_obj_wait(fence, fence->signal_mask, 651ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom false, false, 652ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom VMW_FENCE_WAIT_TIMEOUT); 653ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 654ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (unlikely(ret != 0)) { 655ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom list_del_init(&fence->head); 656ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fence->signaled |= DRM_VMW_FENCE_FLAG_EXEC; 657ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom INIT_LIST_HEAD(&action_list); 658ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom list_splice_init(&fence->seq_passed_actions, 659ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom &action_list); 660ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom vmw_fences_perform_actions(fman, &action_list); 661ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom wake_up_all(&fence->queue); 662ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom } 663ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 664ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_lock_irq(&fman->lock); 665ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 666ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom BUG_ON(!list_empty(&fence->head)); 667ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom kref_put(&fence->kref, vmw_fence_obj_destroy_locked); 668ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom } 669ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_unlock_irqrestore(&fman->lock, irq_flags); 670ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 671ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 672ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromvoid vmw_fence_fifo_up(struct vmw_fence_manager *fman) 673ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 674ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom unsigned long irq_flags; 675ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 676ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_lock_irqsave(&fman->lock, irq_flags); 677ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fman->fifo_down = false; 678ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_unlock_irqrestore(&fman->lock, irq_flags); 679ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 680ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 681ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 682ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromint vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data, 683ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct drm_file *file_priv) 684ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 685ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct drm_vmw_fence_wait_arg *arg = 686ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom (struct drm_vmw_fence_wait_arg *)data; 687ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom unsigned long timeout; 688ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct ttm_base_object *base; 689ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_obj *fence; 690ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 691ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom int ret; 692ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom uint64_t wait_timeout = ((uint64_t)arg->timeout_us * HZ); 693ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 694ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom /* 695ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * 64-bit division not present on 32-bit systems, so do an 696ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * approximation. (Divide by 1000000). 697ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom */ 698ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 699ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom wait_timeout = (wait_timeout >> 20) + (wait_timeout >> 24) - 700ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom (wait_timeout >> 26); 701ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 702ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (!arg->cookie_valid) { 703ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom arg->cookie_valid = 1; 704ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom arg->kernel_cookie = jiffies + wait_timeout; 705ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom } 706ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 707ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom base = ttm_base_object_lookup(tfile, arg->handle); 708ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (unlikely(base == NULL)) { 709ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom printk(KERN_ERR "Wait invalid fence object handle " 710ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom "0x%08lx.\n", 711ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom (unsigned long)arg->handle); 712ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return -EINVAL; 713ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom } 714ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 715ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fence = &(container_of(base, struct vmw_user_fence, base)->fence); 716ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 717ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom timeout = jiffies; 718ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (time_after_eq(timeout, (unsigned long)arg->kernel_cookie)) { 719ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ret = ((vmw_fence_obj_signaled(fence, arg->flags)) ? 720ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 0 : -EBUSY); 721ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom goto out; 722ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom } 723ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 724ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom timeout = (unsigned long)arg->kernel_cookie - timeout; 725ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 726ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ret = vmw_fence_obj_wait(fence, arg->flags, arg->lazy, true, timeout); 727ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 728ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromout: 729ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ttm_base_object_unref(&base); 730ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 731ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom /* 732ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom * Optionally unref the fence object. 733ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom */ 734ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 735ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (ret == 0 && (arg->wait_options & DRM_VMW_WAIT_OPTION_UNREF)) 736ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return ttm_ref_object_base_unref(tfile, arg->handle, 737ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom TTM_REF_USAGE); 738ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return ret; 739ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 740ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 741ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromint vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data, 742ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct drm_file *file_priv) 743ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 744ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct drm_vmw_fence_signaled_arg *arg = 745ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom (struct drm_vmw_fence_signaled_arg *) data; 746ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct ttm_base_object *base; 747ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_obj *fence; 748ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_fence_manager *fman; 749ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 750ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct vmw_private *dev_priv = vmw_priv(dev); 751ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 752ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom base = ttm_base_object_lookup(tfile, arg->handle); 753ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom if (unlikely(base == NULL)) { 754ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom printk(KERN_ERR "Fence signaled invalid fence object handle " 755ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom "0x%08lx.\n", 756ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom (unsigned long)arg->handle); 757ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return -EINVAL; 758ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom } 759ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 760ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fence = &(container_of(base, struct vmw_user_fence, base)->fence); 761ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom fman = fence->fman; 762ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 763ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom arg->signaled = vmw_fence_obj_signaled(fence, arg->flags); 764ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_lock_irq(&fman->lock); 765ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 766ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom arg->signaled_flags = fence->signaled; 767ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom arg->passed_seqno = dev_priv->last_read_seqno; 768ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom spin_unlock_irq(&fman->lock); 769ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 770ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom ttm_base_object_unref(&base); 771ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 772ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return 0; 773ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 774ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 775ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 776ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstromint vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data, 777ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct drm_file *file_priv) 778ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom{ 779ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom struct drm_vmw_fence_arg *arg = 780ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom (struct drm_vmw_fence_arg *) data; 781ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom 782ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, 783ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom arg->handle, 784ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom TTM_REF_USAGE); 785ae2a104058e217548215bfe6c6c8a98752139c29Thomas Hellstrom} 78657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 7876b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom/** 7886b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom * vmw_event_fence_fpriv_gone - Remove references to struct drm_file objects 7896b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom * 7906b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom * @fman: Pointer to a struct vmw_fence_manager 7916b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom * @event_list: Pointer to linked list of struct vmw_event_fence_action objects 7926b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom * with pointers to a struct drm_file object about to be closed. 7936b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom * 7946b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom * This function removes all pending fence events with references to a 7956b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom * specific struct drm_file object about to be closed. The caller is required 7966b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom * to pass a list of all struct vmw_event_fence_action objects with such 7976b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom * events attached. This function is typically called before the 7986b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom * struct drm_file object's event management is taken down. 7996b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom */ 8006b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstromvoid vmw_event_fence_fpriv_gone(struct vmw_fence_manager *fman, 8016b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom struct list_head *event_list) 8026b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom{ 8036b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom struct vmw_event_fence_action *eaction; 8046b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom struct drm_pending_event *event; 8056b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom unsigned long irq_flags; 8066b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom 8076b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom while (1) { 8086b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom spin_lock_irqsave(&fman->lock, irq_flags); 8096b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom if (list_empty(event_list)) 8106b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom goto out_unlock; 8116b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom eaction = list_first_entry(event_list, 8126b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom struct vmw_event_fence_action, 8136b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom fpriv_head); 8146b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom list_del_init(&eaction->fpriv_head); 8156b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom event = eaction->event; 8166b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom eaction->event = NULL; 8176b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom spin_unlock_irqrestore(&fman->lock, irq_flags); 8186b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom event->destroy(event); 8196b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom } 8206b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstromout_unlock: 8216b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom spin_unlock_irqrestore(&fman->lock, irq_flags); 8226b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom} 8236b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom 82457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 82557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom/** 82657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * vmw_event_fence_action_seq_passed 82757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * 82857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @action: The struct vmw_fence_action embedded in a struct 82957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * vmw_event_fence_action. 83057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * 83157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * This function is called when the seqno of the fence where @action is 83257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * attached has passed. It queues the event on the submitter's event list. 83357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * This function is always called from atomic context, and may be called 8348b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz * from irq context. 83557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom */ 83657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstromstatic void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action) 83757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom{ 83857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct vmw_event_fence_action *eaction = 83957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom container_of(action, struct vmw_event_fence_action, action); 84057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct drm_device *dev = eaction->dev; 8416b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom struct drm_pending_event *event = eaction->event; 8426b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom struct drm_file *file_priv; 84357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom unsigned long irq_flags; 84457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 8456b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom if (unlikely(event == NULL)) 8466b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom return; 8476b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom 8486b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom file_priv = event->file_priv; 84957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom spin_lock_irqsave(&dev->event_lock, irq_flags); 85057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 85157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (likely(eaction->tv_sec != NULL)) { 85257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct timeval tv; 85357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 85457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom do_gettimeofday(&tv); 85557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom *eaction->tv_sec = tv.tv_sec; 85657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom *eaction->tv_usec = tv.tv_usec; 85757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } 85857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 8596b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom list_del_init(&eaction->fpriv_head); 8608b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz list_add_tail(&eaction->event->link, &file_priv->event_list); 8616b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom eaction->event = NULL; 86257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom wake_up_all(&file_priv->event_wait); 86357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom spin_unlock_irqrestore(&dev->event_lock, irq_flags); 86457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom} 86557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 86657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom/** 86757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * vmw_event_fence_action_cleanup 86857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * 86957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @action: The struct vmw_fence_action embedded in a struct 87057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * vmw_event_fence_action. 87157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * 87257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * This function is the struct vmw_fence_action destructor. It's typically 87357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * called from a workqueue. 87457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom */ 87557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstromstatic void vmw_event_fence_action_cleanup(struct vmw_fence_action *action) 87657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom{ 87757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct vmw_event_fence_action *eaction = 87857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom container_of(action, struct vmw_event_fence_action, action); 8796b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom struct vmw_fence_manager *fman = eaction->fence->fman; 8806b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom unsigned long irq_flags; 8816b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom 8826b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom spin_lock_irqsave(&fman->lock, irq_flags); 8836b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom list_del(&eaction->fpriv_head); 8846b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom spin_unlock_irqrestore(&fman->lock, irq_flags); 88557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 88657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom vmw_fence_obj_unreference(&eaction->fence); 8878b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz kfree(eaction); 88857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom} 88957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 89057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 89157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom/** 89257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * vmw_fence_obj_add_action - Add an action to a fence object. 89357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * 89457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @fence - The fence object. 89557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @action - The action to add. 89657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * 89757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * Note that the action callbacks may be executed before this function 89857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * returns. 89957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom */ 90057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstromvoid vmw_fence_obj_add_action(struct vmw_fence_obj *fence, 90157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct vmw_fence_action *action) 90257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom{ 90357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct vmw_fence_manager *fman = fence->fman; 90457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom unsigned long irq_flags; 90557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom bool run_update = false; 90657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 90757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom mutex_lock(&fman->goal_irq_mutex); 90857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom spin_lock_irqsave(&fman->lock, irq_flags); 90957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 91057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom fman->pending_actions[action->type]++; 91157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (fence->signaled & DRM_VMW_FENCE_FLAG_EXEC) { 91257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct list_head action_list; 91357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 91457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom INIT_LIST_HEAD(&action_list); 91557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom list_add_tail(&action->head, &action_list); 91657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom vmw_fences_perform_actions(fman, &action_list); 91757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } else { 91857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom list_add_tail(&action->head, &fence->seq_passed_actions); 91957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 92057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom /* 92157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * This function may set fman::seqno_valid, so it must 92257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * be run with the goal_irq_mutex held. 92357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom */ 92457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom run_update = vmw_fence_goal_check_locked(fence); 92557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } 92657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 92757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom spin_unlock_irqrestore(&fman->lock, irq_flags); 92857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 92957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (run_update) { 93057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (!fman->goal_irq_on) { 93157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom fman->goal_irq_on = true; 93257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom vmw_goal_waiter_add(fman->dev_priv); 93357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } 93457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom vmw_fences_update(fman); 93557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } 93657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom mutex_unlock(&fman->goal_irq_mutex); 93757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 93857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom} 93957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 94057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom/** 94157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * vmw_event_fence_action_create - Post an event for sending when a fence 94257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * object seqno has passed. 94357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * 94457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @file_priv: The file connection on which the event should be posted. 94557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @fence: The fence object on which to post the event. 94657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @event: Event to be posted. This event should've been alloced 94757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * using k[mz]alloc, and should've been completely initialized. 94857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * @interruptible: Interruptible waits if possible. 94957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * 95057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * As a side effect, the object pointed to by @event may have been 95157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * freed when this function returns. If this function returns with 95257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * an error code, the caller needs to free that object. 95357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom */ 95457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 9558b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantzint vmw_event_fence_action_queue(struct drm_file *file_priv, 9568b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz struct vmw_fence_obj *fence, 9578b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz struct drm_pending_event *event, 9588b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz uint32_t *tv_sec, 9598b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz uint32_t *tv_usec, 9608b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz bool interruptible) 96157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom{ 9620c5d37033b3a16fdf6442730cee82dd3e8465fb1Dan Carpenter struct vmw_event_fence_action *eaction; 96357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct vmw_fence_manager *fman = fence->fman; 9646b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv); 9656b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom unsigned long irq_flags; 96657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 96757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom eaction = kzalloc(sizeof(*eaction), GFP_KERNEL); 9688b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz if (unlikely(eaction == NULL)) 96957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom return -ENOMEM; 97057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 9718b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz eaction->event = event; 97257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 97357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom eaction->action.seq_passed = vmw_event_fence_action_seq_passed; 97457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom eaction->action.cleanup = vmw_event_fence_action_cleanup; 97557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom eaction->action.type = VMW_ACTION_EVENT; 97657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 97757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom eaction->fence = vmw_fence_obj_reference(fence); 97857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom eaction->dev = fman->dev_priv->dev; 97957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom eaction->tv_sec = tv_sec; 98057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom eaction->tv_usec = tv_usec; 98157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 9826b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom spin_lock_irqsave(&fman->lock, irq_flags); 9836b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom list_add_tail(&eaction->fpriv_head, &vmw_fp->fence_events); 9846b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom spin_unlock_irqrestore(&fman->lock, irq_flags); 9856b82ef50d8617f3fcd51dda9d89d973fe3bc65b8Thomas Hellstrom 98657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom vmw_fence_obj_add_action(fence, &eaction->action); 98757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 98857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom return 0; 98957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom} 99057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 9918b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantzstruct vmw_event_fence_pending { 9928b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz struct drm_pending_event base; 9938b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz struct drm_vmw_event_fence event; 9948b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz}; 9958b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz 9968b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantzint vmw_event_fence_action_create(struct drm_file *file_priv, 9978b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz struct vmw_fence_obj *fence, 9988b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz uint32_t flags, 9998b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz uint64_t user_data, 10008b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz bool interruptible) 10018b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz{ 10028b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz struct vmw_event_fence_pending *event; 10038b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz struct drm_device *dev = fence->fman->dev_priv->dev; 10048b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz unsigned long irq_flags; 10058b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz int ret; 10068b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz 10078b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz spin_lock_irqsave(&dev->event_lock, irq_flags); 10088b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz 10098b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz ret = (file_priv->event_space < sizeof(event->event)) ? -EBUSY : 0; 10108b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz if (likely(ret == 0)) 10118b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz file_priv->event_space -= sizeof(event->event); 10128b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz 10138b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz spin_unlock_irqrestore(&dev->event_lock, irq_flags); 10148b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz 10158b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz if (unlikely(ret != 0)) { 10168b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz DRM_ERROR("Failed to allocate event space for this file.\n"); 10178b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz goto out_no_space; 10188b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz } 10198b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz 10208b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz 10218b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz event = kzalloc(sizeof(event->event), GFP_KERNEL); 10228b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz if (unlikely(event == NULL)) { 10238b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz DRM_ERROR("Failed to allocate an event.\n"); 10248b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz ret = -ENOMEM; 10258b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz goto out_no_event; 10268b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz } 10278b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz 10288b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz event->event.base.type = DRM_VMW_EVENT_FENCE_SIGNALED; 10298b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz event->event.base.length = sizeof(*event); 10308b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz event->event.user_data = user_data; 10318b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz 10328b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz event->base.event = &event->event.base; 10338b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz event->base.file_priv = file_priv; 10348b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz event->base.destroy = (void (*) (struct drm_pending_event *)) kfree; 10358b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz 10368b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz 10378b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz if (flags & DRM_VMW_FE_FLAG_REQ_TIME) 10388b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz ret = vmw_event_fence_action_queue(file_priv, fence, 10398b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz &event->base, 10408b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz &event->event.tv_sec, 10418b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz &event->event.tv_usec, 10428b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz interruptible); 10438b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz else 10448b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz ret = vmw_event_fence_action_queue(file_priv, fence, 10458b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz &event->base, 10468b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz NULL, 10478b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz NULL, 10488b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz interruptible); 10498b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz if (ret != 0) 10508b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz goto out_no_queue; 10518b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz 10528b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantzout_no_queue: 10538b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz event->base.destroy(&event->base); 10548b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantzout_no_event: 10558b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz spin_lock_irqsave(&dev->event_lock, irq_flags); 10568b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz file_priv->event_space += sizeof(*event); 10578b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz spin_unlock_irqrestore(&dev->event_lock, irq_flags); 10588b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantzout_no_space: 10598b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz return ret; 10608b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz} 10618b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz 106257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstromint vmw_fence_event_ioctl(struct drm_device *dev, void *data, 106357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct drm_file *file_priv) 106457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom{ 106557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct vmw_private *dev_priv = vmw_priv(dev); 106657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct drm_vmw_fence_event_arg *arg = 106757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom (struct drm_vmw_fence_event_arg *) data; 106857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct vmw_fence_obj *fence = NULL; 106957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv); 107057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct drm_vmw_fence_rep __user *user_fence_rep = 107157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom (struct drm_vmw_fence_rep __user *)(unsigned long) 107257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom arg->fence_rep; 107357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom uint32_t handle; 107457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom int ret; 107557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 107657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom /* 107757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * Look up an existing fence object, 107857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * and if user-space wants a new reference, 107957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * add one. 108057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom */ 108157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (arg->handle) { 108257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom struct ttm_base_object *base = 108357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom ttm_base_object_lookup(vmw_fp->tfile, arg->handle); 108457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 108557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (unlikely(base == NULL)) { 108657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom DRM_ERROR("Fence event invalid fence object handle " 108757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom "0x%08lx.\n", 108857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom (unsigned long)arg->handle); 108957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom return -EINVAL; 109057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } 109157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom fence = &(container_of(base, struct vmw_user_fence, 109257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom base)->fence); 109357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom (void) vmw_fence_obj_reference(fence); 109457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 109557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (user_fence_rep != NULL) { 109657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom bool existed; 109757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 109857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom ret = ttm_ref_object_add(vmw_fp->tfile, base, 109957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom TTM_REF_USAGE, &existed); 110057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (unlikely(ret != 0)) { 110157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom DRM_ERROR("Failed to reference a fence " 110257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom "object.\n"); 110357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom goto out_no_ref_obj; 110457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } 110557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom handle = base->hash.key; 110657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } 110757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom ttm_base_object_unref(&base); 110857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } 110957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 111057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom /* 111157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom * Create a new fence object. 111257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom */ 111357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (!fence) { 111457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom ret = vmw_execbuf_fence_commands(file_priv, dev_priv, 111557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom &fence, 111657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom (user_fence_rep) ? 111757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom &handle : NULL); 111857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (unlikely(ret != 0)) { 111957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom DRM_ERROR("Fence event failed to create fence.\n"); 112057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom return ret; 112157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } 112257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } 112357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 112457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom BUG_ON(fence == NULL); 112557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 112657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (arg->flags & DRM_VMW_FE_FLAG_REQ_TIME) 112757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom ret = vmw_event_fence_action_create(file_priv, fence, 11288b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz arg->flags, 11298b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz arg->user_data, 113057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom true); 113157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom else 113257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom ret = vmw_event_fence_action_create(file_priv, fence, 11338b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz arg->flags, 11348b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz arg->user_data, 113557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom true); 113657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 113757c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (unlikely(ret != 0)) { 113857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (ret != -ERESTARTSYS) 113957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom DRM_ERROR("Failed to attach event to fence.\n"); 11408b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantz goto out_no_create; 114157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom } 114257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom 114357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep, fence, 114457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom handle); 114557c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom vmw_fence_obj_unreference(&fence); 114657c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom return 0; 11478b7de6aa84682a3396544fd88cd457f95484573aJakob Bornecrantzout_no_create: 114857c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom if (user_fence_rep != NULL) 114957c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, 115057c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom handle, TTM_REF_USAGE); 115157c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstromout_no_ref_obj: 115257c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom vmw_fence_obj_unreference(&fence); 115357c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom return ret; 115457c5ee79acba9582762c09c269e0e2ae1adf1b31Thomas Hellstrom} 1155