drm_lock.c revision d3d50737e566cade9a08d73d2af95105ac7cd960
22cc4b4e0d92019280405da9bb1b29767e85c572Brian Wellington/*
d63ae51ba337165172a9b50fd5d84805ffe50044Tinderbox User * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Use is subject to license terms.
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews */
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews/*
07fffbc8c9ea9f56c80143c70355807a1aaeec21Michael Sawyer * lock.c -- IOCTLs for locking -*- linux-c -*-
07fffbc8c9ea9f56c80143c70355807a1aaeec21Michael Sawyer * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein */
47058d17266420179fa294de6b82d8fb5b918df4Michael Sawyer/*
07fffbc8c9ea9f56c80143c70355807a1aaeec21Michael Sawyer * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
07fffbc8c9ea9f56c80143c70355807a1aaeec21Michael Sawyer * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6f710fce2d5a51b17bfc6f4a0b305c6b603c1304Brian Wellington * All Rights Reserved.
a985c480e1f2ff2ef358af4a407d3a0e40fd651eMichael Sawyer *
07fffbc8c9ea9f56c80143c70355807a1aaeec21Michael Sawyer * Permission is hereby granted, free of charge, to any person obtaining a
9ef9f6b8ae33e6e056ee721739028745dce71737David Lawrence * copy of this software and associated documentation files (the "Software"),
668bd3acee916de774c569449367fee199965ff4Brian Wellington * to deal in the Software without restriction, including without limitation
242bba8991b030b7764f0bdca3922d75c34ea51eAndreas Gustafsson * the rights to use, copy, modify, merge, publish, distribute, sublicense,
4162d3b36d1a3c25724c7e37ce839f67b2352bbbMark Andrews * and/or sell copies of the Software, and to permit persons to whom the
25a66b4e41e2b0a2af4840749bac80ae78c678bfMark Andrews * Software is furnished to do so, subject to the following conditions:
9ef9f6b8ae33e6e056ee721739028745dce71737David Lawrence *
1893b56ef9f5f2bc2a0fbe80d3c6b69df1bdc7c2Michael Sawyer * The above copyright notice and this permission notice (including the next
e560fbdf77b08ff23ab71b107f022829bcd552dbMark Andrews * paragraph) shall be included in all copies or substantial portions of the
9ef9f6b8ae33e6e056ee721739028745dce71737David Lawrence * Software.
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews *
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
668bd3acee916de774c569449367fee199965ff4Brian Wellington * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
668bd3acee916de774c569449367fee199965ff4Brian Wellington * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
668f8d91db59f4dd89a0b54206f87879354339f5Brian Wellington * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
07fffbc8c9ea9f56c80143c70355807a1aaeec21Michael Sawyer * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
83a44df0a1dcc1760c7e4ad45eae801b5144592cBrian Wellington * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrews * OTHER DEALINGS IN THE SOFTWARE.
07fffbc8c9ea9f56c80143c70355807a1aaeec21Michael Sawyer *
07fffbc8c9ea9f56c80143c70355807a1aaeec21Michael Sawyer * Authors:
07fffbc8c9ea9f56c80143c70355807a1aaeec21Michael Sawyer * Rickard E. (Rik) Faith <faith@valinux.com>
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer * Gareth Hughes <gareth@valinux.com>
fed846067d265db1037483d81d01f3651c8a3f28Brian Wellington *
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews */
07fffbc8c9ea9f56c80143c70355807a1aaeec21Michael Sawyer
2a23a625246acfbf6ff92b86a6b8b9df59dbeaa4Mark Andrews#include "drmP.h"
2a23a625246acfbf6ff92b86a6b8b9df59dbeaa4Mark Andrews
24139527f3d0d3fe743bd867329a2edd529728a6Andreas Gustafssonint
24139527f3d0d3fe743bd867329a2edd529728a6Andreas Gustafssondrm_lock_take(drm_lock_data_t *lock_data, unsigned int context)
6b3c17b9b0230eca56bb44bd61f0a43fe8ae1d32Automatic Updater{
24139527f3d0d3fe743bd867329a2edd529728a6Andreas Gustafsson unsigned int old, new;
24139527f3d0d3fe743bd867329a2edd529728a6Andreas Gustafsson volatile unsigned int *lock = &lock_data->hw_lock->lock;
24139527f3d0d3fe743bd867329a2edd529728a6Andreas Gustafsson
932b781b8178dc2876e23ddedb56294277c6ab28Michael Sawyer do {
3f79a8b6f1b50f8e1bc2f274bcfe91d6af74f161Mark Andrews old = *lock;
932b781b8178dc2876e23ddedb56294277c6ab28Michael Sawyer if (old & _DRM_LOCK_HELD)
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer new = old | _DRM_LOCK_CONT;
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyer else
0e0e575ec135a983a53c501cf48734b823361ab4Brian Wellington new = context | _DRM_LOCK_HELD;
0e0e575ec135a983a53c501cf48734b823361ab4Brian Wellington } while (!atomic_cmpset_int(lock, old, new));
0e0e575ec135a983a53c501cf48734b823361ab4Brian Wellington
3f79a8b6f1b50f8e1bc2f274bcfe91d6af74f161Mark Andrews if (_DRM_LOCKING_CONTEXT(old) == context) {
910df0c767ea973a59e866adb33bddf24b584f3dMichael Sawyer if (old & _DRM_LOCK_HELD) {
0e0e575ec135a983a53c501cf48734b823361ab4Brian Wellington if (context != DRM_KERNEL_CONTEXT) {
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrews DRM_ERROR("%d holds heavyweight lock\n",
688a4c50c2025a683d8d2bf5bb53a591556df4fcAndreas Gustafsson context);
0e0e575ec135a983a53c501cf48734b823361ab4Brian Wellington }
ec3984e9df6fd9b7811daa0dacb1b3dd1423ebf3Mark Andrews return (0);
13396661f46572d7b94703a25721aad040fbd91aMark Andrews }
464c2c673b879071da66cab5a627baf35c5e0f90Evan Hunt }
464c2c673b879071da66cab5a627baf35c5e0f90Evan Hunt if (new == (context | _DRM_LOCK_HELD)) {
464c2c673b879071da66cab5a627baf35c5e0f90Evan Hunt /* Have lock */
9a859983d7059a6eb9c877c1d2ac6a3a5b7170f7Evan Hunt return (1);
f17b62a64bec4690f7ef0263efee1fa727b66fd5Michael Sawyer }
464c2c673b879071da66cab5a627baf35c5e0f90Evan Hunt return (0);
464c2c673b879071da66cab5a627baf35c5e0f90Evan Hunt}
464c2c673b879071da66cab5a627baf35c5e0f90Evan Hunt
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*
7ca101656029196bba41ffff632f2c6903f48125Mark Andrews * This takes a lock forcibly and hands it to context. Should ONLY be used
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyer * inside *_unlock to give lock to kernel before calling *_dma_schedule.
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyer */
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyerint
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyerdrm_lock_transfer(drm_device_t *dev, drm_lock_data_t *lock_data,
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyer unsigned int context)
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyer{
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyer unsigned int old, new;
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyer volatile unsigned int *lock = &lock_data->hw_lock->lock;
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyer
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyer dev->lock.filp = NULL;
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyer do {
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyer old = *lock;
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyer new = context | _DRM_LOCK_HELD;
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyer } while (!atomic_cmpset_int(lock, old, new));
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyer
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyer return (1);
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyer}
ebbfa36a628b935891b2f8a2c5936aef48b87151Michael Sawyer
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrewsint
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrewsdrm_lock_free(drm_device_t *dev, volatile unsigned int *lock,
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrews unsigned int context)
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrews{
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrews unsigned int old, new;
07fffbc8c9ea9f56c80143c70355807a1aaeec21Michael Sawyer
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrews mutex_enter(&(dev->lock.lock_mutex));
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrews dev->lock.filp = NULL;
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrews do {
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrews old = *lock;
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrews new = 0;
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrews } while (!atomic_cmpset_int(lock, old, new));
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrews
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrews if (_DRM_LOCK_IS_HELD(old) &&
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrews (_DRM_LOCKING_CONTEXT(old) != context)) {
d302a620e0d49811874b9555ac2e4c6e05861a6bFrancis Dupont DRM_ERROR("%d freed heavyweight lock held by %d\n",
d302a620e0d49811874b9555ac2e4c6e05861a6bFrancis Dupont context, _DRM_LOCKING_CONTEXT(old));
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein mutex_exit(&(dev->lock.lock_mutex));
cc5ea458fe9f12f247e2549b6dc24fe475a824c2Michael Sawyer return (1);
8fbd23c0aaacdde1348b6457c5db14c433096fd2Andreas Gustafsson }
24139527f3d0d3fe743bd867329a2edd529728a6Andreas Gustafsson cv_broadcast(&(dev->lock.lock_cv));
9fe3676b8490319aa65182f2072cbf5086097979Michael Sawyer mutex_exit(&(dev->lock.lock_mutex));
e6c95fe56b0491b533f2ca5a3ed8e8e9f74f4fd2Mark Andrews return (0);
e6c95fe56b0491b533f2ca5a3ed8e8e9f74f4fd2Mark Andrews}
8fbd23c0aaacdde1348b6457c5db14c433096fd2Andreas Gustafsson
8fbd23c0aaacdde1348b6457c5db14c433096fd2Andreas Gustafsson/*ARGSUSED*/
debd489a44363870f96f75818e89ec27d3cab736Francis Dupontint
debd489a44363870f96f75818e89ec27d3cab736Francis Dupontdrm_lock(DRM_IOCTL_ARGS)
debd489a44363870f96f75818e89ec27d3cab736Francis Dupont{
8fbd23c0aaacdde1348b6457c5db14c433096fd2Andreas Gustafsson DRM_DEVICE;
e60b3717f0e6f28d6fb2c5124ffb3bd31cc3a746Mark Andrews drm_lock_t lock;
8fbd23c0aaacdde1348b6457c5db14c433096fd2Andreas Gustafsson int ret = 0;
8fbd23c0aaacdde1348b6457c5db14c433096fd2Andreas Gustafsson
8fbd23c0aaacdde1348b6457c5db14c433096fd2Andreas Gustafsson DRM_COPYFROM_WITH_RETURN(&lock, (void *)data, sizeof (lock));
8fbd23c0aaacdde1348b6457c5db14c433096fd2Andreas Gustafsson
8fbd23c0aaacdde1348b6457c5db14c433096fd2Andreas Gustafsson if (lock.context == DRM_KERNEL_CONTEXT) {
8fbd23c0aaacdde1348b6457c5db14c433096fd2Andreas Gustafsson DRM_ERROR("Process %d using kernel context %d\n",
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein DRM_CURRENTPID, lock.context);
e60b3717f0e6f28d6fb2c5124ffb3bd31cc3a746Mark Andrews return (EINVAL);
e60b3717f0e6f28d6fb2c5124ffb3bd31cc3a746Mark Andrews }
e60b3717f0e6f28d6fb2c5124ffb3bd31cc3a746Mark Andrews
e60b3717f0e6f28d6fb2c5124ffb3bd31cc3a746Mark Andrews DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
e60b3717f0e6f28d6fb2c5124ffb3bd31cc3a746Mark Andrews lock.context, DRM_CURRENTPID, dev->lock.hw_lock->lock,
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein lock.flags);
8fbd23c0aaacdde1348b6457c5db14c433096fd2Andreas Gustafsson if (dev->driver->use_dma_queue && lock.context < 0)
8fbd23c0aaacdde1348b6457c5db14c433096fd2Andreas Gustafsson return (EINVAL);
8fbd23c0aaacdde1348b6457c5db14c433096fd2Andreas Gustafsson
8fbd23c0aaacdde1348b6457c5db14c433096fd2Andreas Gustafsson mutex_enter(&(dev->lock.lock_mutex));
e6c95fe56b0491b533f2ca5a3ed8e8e9f74f4fd2Mark Andrews for (;;) {
92aa706a215dcc26e7ef89cddadaa124b83e06a1Andreas Gustafsson if (drm_lock_take(&dev->lock, lock.context)) {
7949dbdae1db33e6263d754e5940daa1dfba59f9Michael Sawyer dev->lock.filp = fpriv;
a5ed46c9fd270775c39770bfd0250a52d374ebf2Michael Sawyer dev->lock.lock_time = ddi_get_lbolt();
7949dbdae1db33e6263d754e5940daa1dfba59f9Michael Sawyer break; /* Got lock */
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews }
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews ret = cv_wait_sig(&(dev->lock.lock_cv),
d21d4ddac7024a00a9f1d3f360a4fb0df68982d9Mark Andrews &(dev->lock.lock_mutex));
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews if (ret == 0) {
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews mutex_exit(&(dev->lock.lock_mutex));
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews return (EINTR);
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews }
7949dbdae1db33e6263d754e5940daa1dfba59f9Michael Sawyer }
a268fec7f54a89a0772a91da0511c8eae09e6157Mark Andrews mutex_exit(&(dev->lock.lock_mutex));
e69ccf6d54db6e749470341e2c84996ecc77e5ecMichael Sawyer DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
19b037bcb900e75528bf6f2582d77c3f1a6d6714Evan Hunt
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews if (dev->driver->dma_quiescent != NULL &&
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews (lock.flags & _DRM_LOCK_QUIESCENT))
7949dbdae1db33e6263d754e5940daa1dfba59f9Michael Sawyer dev->driver->dma_quiescent(dev);
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews
7de69feda2f66658ce66a8700d64ffb88d47bb6aMark Andrews return (0);
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews}
6e7f5e8ad5e85edd28cca765c609620fba038035Mark Andrews
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews/*ARGSUSED*/
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrewsint
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrewsdrm_unlock(DRM_IOCTL_ARGS)
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews{
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews DRM_DEVICE;
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews drm_lock_t lock;
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews DRM_COPYFROM_WITH_RETURN(&lock, (void *)data, sizeof (lock));
10e1788f9f6efa471f07127ce9ff22e6e301f783Michael Sawyer
7949dbdae1db33e6263d754e5940daa1dfba59f9Michael Sawyer DRM_DEBUG("%d (pid %d) requests unlock (0x%08x), flags = 0x%08x\n",
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews lock.context, DRM_CURRENTPID, dev->lock.hw_lock->lock,
75ae74f8fd0847817bce2db7c868b179db67f019Mark Andrews lock.flags);
75ae74f8fd0847817bce2db7c868b179db67f019Mark Andrews
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews if (lock.context == DRM_KERNEL_CONTEXT) {
78d78f05d91205cbde33ca87d24b8d13aa2d8d66Brian Wellington DRM_ERROR("Process %d using kernel context %d\n",
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews DRM_CURRENTPID, lock.context);
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews return (EINVAL);
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews }
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews atomic_inc_32(&dev->counts[_DRM_STAT_UNLOCKS]);
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews DRM_LOCK();
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews if (drm_lock_free(dev, &dev->lock.hw_lock->lock, lock.context)) {
16134801ce8fffbb6c42bb54d544c3397a45ad06Mark Andrews DRM_ERROR("drm_unlock\n");
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews }
f274cbeaed0e4c5fdbde9f5c30833d7f1da37cd3Mark Andrews DRM_UNLOCK();
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews return (0);
6552f33198438390724c5823b8dbcf477ec9638cEvan Hunt}
b399f4e5684a66123e2f38e0f7e254f0f3ca0cc6Mark Andrews