···11+/*22+ * Copyright (C) 2013-2016 Red Hat33+ * Author: Rob Clark <robdclark@gmail.com>44+ *55+ * This program is free software; you can redistribute it and/or modify it66+ * under the terms of the GNU General Public License version 2 as published by77+ * the Free Software Foundation.88+ *99+ * This program is distributed in the hope that it will be useful, but WITHOUT1010+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1111+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1212+ * more details.1313+ *1414+ * You should have received a copy of the GNU General Public License along with1515+ * this program. If not, see <http://www.gnu.org/licenses/>.1616+ */1717+1818+#include "msm_drv.h"1919+#include "msm_fence.h"2020+#include "msm_gpu.h"2121+2222+static inline bool fence_completed(struct drm_device *dev, uint32_t fence)2323+{2424+ struct msm_drm_private *priv = dev->dev_private;2525+ return (int32_t)(priv->completed_fence - fence) >= 0;2626+}2727+2828+int msm_wait_fence(struct drm_device *dev, uint32_t fence,2929+ ktime_t *timeout , bool interruptible)3030+{3131+ struct msm_drm_private *priv = dev->dev_private;3232+ int ret;3333+3434+ if (!priv->gpu)3535+ return 0;3636+3737+ if (fence > priv->gpu->submitted_fence) {3838+ DRM_ERROR("waiting on invalid fence: %u (of %u)\n",3939+ fence, priv->gpu->submitted_fence);4040+ return -EINVAL;4141+ }4242+4343+ if (!timeout) {4444+ /* no-wait: */4545+ ret = fence_completed(dev, fence) ? 0 : -EBUSY;4646+ } else {4747+ ktime_t now = ktime_get();4848+ unsigned long remaining_jiffies;4949+5050+ if (ktime_compare(*timeout, now) < 0) {5151+ remaining_jiffies = 0;5252+ } else {5353+ ktime_t rem = ktime_sub(*timeout, now);5454+ struct timespec ts = ktime_to_timespec(rem);5555+ remaining_jiffies = timespec_to_jiffies(&ts);5656+ }5757+5858+ if (interruptible)5959+ ret = wait_event_interruptible_timeout(priv->fence_event,6060+ fence_completed(dev, fence),6161+ remaining_jiffies);6262+ else6363+ ret = wait_event_timeout(priv->fence_event,6464+ fence_completed(dev, fence),6565+ remaining_jiffies);6666+6767+ if (ret == 0) {6868+ DBG("timeout waiting for fence: %u (completed: %u)",6969+ fence, priv->completed_fence);7070+ ret = -ETIMEDOUT;7171+ } else if (ret != -ERESTARTSYS) {7272+ ret = 0;7373+ }7474+ }7575+7676+ return ret;7777+}7878+7979+int msm_queue_fence_cb(struct drm_device *dev,8080+ struct msm_fence_cb *cb, uint32_t fence)8181+{8282+ struct msm_drm_private *priv = dev->dev_private;8383+ int ret = 0;8484+8585+ mutex_lock(&dev->struct_mutex);8686+ if (!list_empty(&cb->work.entry)) {8787+ ret = -EINVAL;8888+ } else if (fence > priv->completed_fence) {8989+ cb->fence = fence;9090+ list_add_tail(&cb->work.entry, &priv->fence_cbs);9191+ } else {9292+ queue_work(priv->wq, &cb->work);9393+ }9494+ mutex_unlock(&dev->struct_mutex);9595+9696+ return ret;9797+}9898+9999+/* called from workqueue */100100+void msm_update_fence(struct drm_device *dev, uint32_t fence)101101+{102102+ struct msm_drm_private *priv = dev->dev_private;103103+104104+ mutex_lock(&dev->struct_mutex);105105+ priv->completed_fence = max(fence, priv->completed_fence);106106+107107+ while (!list_empty(&priv->fence_cbs)) {108108+ struct msm_fence_cb *cb;109109+110110+ cb = list_first_entry(&priv->fence_cbs,111111+ struct msm_fence_cb, work.entry);112112+113113+ if (cb->fence > priv->completed_fence)114114+ break;115115+116116+ list_del_init(&cb->work.entry);117117+ queue_work(priv->wq, &cb->work);118118+ }119119+120120+ mutex_unlock(&dev->struct_mutex);121121+122122+ wake_up_all(&priv->fence_event);123123+}124124+125125+void __msm_fence_worker(struct work_struct *work)126126+{127127+ struct msm_fence_cb *cb = container_of(work, struct msm_fence_cb, work);128128+ cb->func(cb);129129+}
+43
drivers/gpu/drm/msm/msm_fence.h
···11+/*22+ * Copyright (C) 2013-2016 Red Hat33+ * Author: Rob Clark <robdclark@gmail.com>44+ *55+ * This program is free software; you can redistribute it and/or modify it66+ * under the terms of the GNU General Public License version 2 as published by77+ * the Free Software Foundation.88+ *99+ * This program is distributed in the hope that it will be useful, but WITHOUT1010+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1111+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1212+ * more details.1313+ *1414+ * You should have received a copy of the GNU General Public License along with1515+ * this program. If not, see <http://www.gnu.org/licenses/>.1616+ */1717+1818+#ifndef __MSM_FENCE_H__1919+#define __MSM_FENCE_H__2020+2121+#include "msm_drv.h"2222+2323+/* callback from wq once fence has passed: */2424+struct msm_fence_cb {2525+ struct work_struct work;2626+ uint32_t fence;2727+ void (*func)(struct msm_fence_cb *cb);2828+};2929+3030+void __msm_fence_worker(struct work_struct *work);3131+3232+#define INIT_FENCE_CB(_cb, _func) do { \3333+ INIT_WORK(&(_cb)->work, __msm_fence_worker); \3434+ (_cb)->func = _func; \3535+ } while (0)3636+3737+int msm_wait_fence(struct drm_device *dev, uint32_t fence,3838+ ktime_t *timeout, bool interruptible);3939+int msm_queue_fence_cb(struct drm_device *dev,4040+ struct msm_fence_cb *cb, uint32_t fence);4141+void msm_update_fence(struct drm_device *dev, uint32_t fence);4242+4343+#endif