1254885Sdumbbell/* 2254885Sdumbbell * Copyright 2011 Christian K��nig. 3254885Sdumbbell * All Rights Reserved. 4254885Sdumbbell * 5254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a 6254885Sdumbbell * copy of this software and associated documentation files (the 7254885Sdumbbell * "Software"), to deal in the Software without restriction, including 8254885Sdumbbell * without limitation the rights to use, copy, modify, merge, publish, 9254885Sdumbbell * distribute, sub license, and/or sell copies of the Software, and to 10254885Sdumbbell * permit persons to whom the Software is furnished to do so, subject to 11254885Sdumbbell * the following conditions: 12254885Sdumbbell * 13254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 16254885Sdumbbell * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 17254885Sdumbbell * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 18254885Sdumbbell * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 19254885Sdumbbell * USE OR OTHER DEALINGS IN THE SOFTWARE. 20254885Sdumbbell * 21254885Sdumbbell * The above copyright notice and this permission notice (including the 22254885Sdumbbell * next paragraph) shall be included in all copies or substantial portions 23254885Sdumbbell * of the Software. 24254885Sdumbbell * 25254885Sdumbbell */ 26254885Sdumbbell 27254885Sdumbbell#include <sys/cdefs.h> 28254885Sdumbbell__FBSDID("$FreeBSD$"); 29254885Sdumbbell 30254885Sdumbbell/* 31254885Sdumbbell * Authors: 32254885Sdumbbell * Christian K��nig <deathsimple@vodafone.de> 33254885Sdumbbell */ 34254885Sdumbbell#include <dev/drm2/drmP.h> 35254885Sdumbbell#include "radeon.h" 36254885Sdumbbell 37254885Sdumbbell 38254885Sdumbbellint radeon_semaphore_create(struct radeon_device *rdev, 39254885Sdumbbell struct radeon_semaphore **semaphore) 40254885Sdumbbell{ 41254885Sdumbbell int r; 42254885Sdumbbell 43254885Sdumbbell *semaphore = malloc(sizeof(struct radeon_semaphore), 44280183Sdumbbell DRM_MEM_DRIVER, M_NOWAIT); 45254885Sdumbbell if (*semaphore == NULL) { 46254885Sdumbbell return -ENOMEM; 47254885Sdumbbell } 48254885Sdumbbell r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, 49254885Sdumbbell &(*semaphore)->sa_bo, 8, 8, true); 50254885Sdumbbell if (r) { 51254885Sdumbbell free(*semaphore, DRM_MEM_DRIVER); 52254885Sdumbbell *semaphore = NULL; 53254885Sdumbbell return r; 54254885Sdumbbell } 55254885Sdumbbell (*semaphore)->waiters = 0; 56254885Sdumbbell (*semaphore)->gpu_addr = radeon_sa_bo_gpu_addr((*semaphore)->sa_bo); 57254885Sdumbbell *((uint64_t*)radeon_sa_bo_cpu_addr((*semaphore)->sa_bo)) = 0; 58254885Sdumbbell return 0; 59254885Sdumbbell} 60254885Sdumbbell 61254885Sdumbbellvoid radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring, 62254885Sdumbbell struct radeon_semaphore *semaphore) 63254885Sdumbbell{ 64254885Sdumbbell --semaphore->waiters; 65254885Sdumbbell radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, false); 66254885Sdumbbell} 67254885Sdumbbell 68254885Sdumbbellvoid radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, 69254885Sdumbbell struct radeon_semaphore *semaphore) 70254885Sdumbbell{ 71254885Sdumbbell ++semaphore->waiters; 72254885Sdumbbell radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, true); 73254885Sdumbbell} 74254885Sdumbbell 75254885Sdumbbell/* caller must hold ring lock */ 76254885Sdumbbellint radeon_semaphore_sync_rings(struct radeon_device *rdev, 77254885Sdumbbell struct radeon_semaphore *semaphore, 78254885Sdumbbell int signaler, int waiter) 79254885Sdumbbell{ 80254885Sdumbbell int r; 81254885Sdumbbell 82254885Sdumbbell /* no need to signal and wait on the same ring */ 83254885Sdumbbell if (signaler == waiter) { 84254885Sdumbbell return 0; 85254885Sdumbbell } 86254885Sdumbbell 87254885Sdumbbell /* prevent GPU deadlocks */ 88254885Sdumbbell if (!rdev->ring[signaler].ready) { 89254885Sdumbbell dev_err(rdev->dev, "Trying to sync to a disabled ring!"); 90254885Sdumbbell return -EINVAL; 91254885Sdumbbell } 92254885Sdumbbell 93254885Sdumbbell r = radeon_ring_alloc(rdev, &rdev->ring[signaler], 8); 94254885Sdumbbell if (r) { 95254885Sdumbbell return r; 96254885Sdumbbell } 97254885Sdumbbell radeon_semaphore_emit_signal(rdev, signaler, semaphore); 98254885Sdumbbell radeon_ring_commit(rdev, &rdev->ring[signaler]); 99254885Sdumbbell 100254885Sdumbbell /* we assume caller has already allocated space on waiters ring */ 101254885Sdumbbell radeon_semaphore_emit_wait(rdev, waiter, semaphore); 102254885Sdumbbell 103254885Sdumbbell /* for debugging lockup only, used by sysfs debug files */ 104254885Sdumbbell rdev->ring[signaler].last_semaphore_signal_addr = semaphore->gpu_addr; 105254885Sdumbbell rdev->ring[waiter].last_semaphore_wait_addr = semaphore->gpu_addr; 106254885Sdumbbell 107254885Sdumbbell return 0; 108254885Sdumbbell} 109254885Sdumbbell 110254885Sdumbbellvoid radeon_semaphore_free(struct radeon_device *rdev, 111254885Sdumbbell struct radeon_semaphore **semaphore, 112254885Sdumbbell struct radeon_fence *fence) 113254885Sdumbbell{ 114254885Sdumbbell if (semaphore == NULL || *semaphore == NULL) { 115254885Sdumbbell return; 116254885Sdumbbell } 117254885Sdumbbell if ((*semaphore)->waiters > 0) { 118254885Sdumbbell dev_err(rdev->dev, "semaphore %p has more waiters than signalers," 119254885Sdumbbell " hardware lockup imminent!\n", *semaphore); 120254885Sdumbbell } 121254885Sdumbbell radeon_sa_bo_free(rdev, &(*semaphore)->sa_bo, fence); 122254885Sdumbbell free(*semaphore, DRM_MEM_DRIVER); 123254885Sdumbbell *semaphore = NULL; 124254885Sdumbbell} 125