|
@@ -15,6 +15,8 @@
|
|
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
*/
|
|
|
|
|
|
+#include <linux/sync_file.h>
|
|
|
+
|
|
|
#include "msm_drv.h"
|
|
|
#include "msm_gpu.h"
|
|
|
#include "msm_gem.h"
|
|
@@ -361,6 +363,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
|
|
|
struct msm_file_private *ctx = file->driver_priv;
|
|
|
struct msm_gem_submit *submit;
|
|
|
struct msm_gpu *gpu = priv->gpu;
|
|
|
+ struct fence *in_fence = NULL;
|
|
|
+ struct sync_file *sync_file = NULL;
|
|
|
+ int out_fence_fd = -1;
|
|
|
unsigned i;
|
|
|
int ret;
|
|
|
|
|
@@ -370,13 +375,24 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
|
|
|
/* for now, we just have 3d pipe.. eventually this would need to
|
|
|
* be more clever to dispatch to appropriate gpu module:
|
|
|
*/
|
|
|
- if (args->pipe != MSM_PIPE_3D0)
|
|
|
+ if (MSM_PIPE_ID(args->flags) != MSM_PIPE_3D0)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (MSM_PIPE_FLAGS(args->flags) & ~MSM_SUBMIT_FLAGS)
|
|
|
return -EINVAL;
|
|
|
|
|
|
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
+ if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
|
|
|
+ out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
|
|
|
+ if (out_fence_fd < 0) {
|
|
|
+ ret = out_fence_fd;
|
|
|
+ goto out_unlock;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
submit = submit_create(dev, gpu, args->nr_bos, args->nr_cmds);
|
|
|
if (!submit) {
|
|
|
ret = -ENOMEM;
|
|
@@ -391,9 +407,32 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
|
|
|
if (ret)
|
|
|
goto out;
|
|
|
|
|
|
- ret = submit_fence_sync(submit);
|
|
|
- if (ret)
|
|
|
- goto out;
|
|
|
+ if (args->flags & MSM_SUBMIT_FENCE_FD_IN) {
|
|
|
+ in_fence = sync_file_get_fence(args->fence_fd);
|
|
|
+
|
|
|
+ if (!in_fence) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* TODO if we get an array-fence due to userspace merging multiple
|
|
|
+ * fences, we need a way to determine if all the backing fences
|
|
|
+ * are from our own context..
|
|
|
+ */
|
|
|
+
|
|
|
+ if (in_fence->context != gpu->fctx->context) {
|
|
|
+ ret = fence_wait(in_fence, true);
|
|
|
+ if (ret)
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!(args->fence & MSM_SUBMIT_NO_IMPLICIT)) {
|
|
|
+ ret = submit_fence_sync(submit);
|
|
|
+ if (ret)
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
|
|
|
ret = submit_pin_objects(submit);
|
|
|
if (ret)
|
|
@@ -459,15 +498,39 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
|
|
|
|
|
|
submit->nr_cmds = i;
|
|
|
|
|
|
- ret = msm_gpu_submit(gpu, submit, ctx);
|
|
|
+ submit->fence = msm_fence_alloc(gpu->fctx);
|
|
|
+ if (IS_ERR(submit->fence)) {
|
|
|
+ ret = PTR_ERR(submit->fence);
|
|
|
+ submit->fence = NULL;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
|
|
|
+ sync_file = sync_file_create(submit->fence);
|
|
|
+ if (!sync_file) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ msm_gpu_submit(gpu, submit, ctx);
|
|
|
|
|
|
args->fence = submit->fence->seqno;
|
|
|
|
|
|
+ if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
|
|
|
+ fd_install(out_fence_fd, sync_file->file);
|
|
|
+ args->fence_fd = out_fence_fd;
|
|
|
+ }
|
|
|
+
|
|
|
out:
|
|
|
+ if (in_fence)
|
|
|
+ fence_put(in_fence);
|
|
|
submit_cleanup(submit);
|
|
|
if (ret)
|
|
|
msm_gem_submit_free(submit);
|
|
|
out_unlock:
|
|
|
+ if (ret && (out_fence_fd >= 0))
|
|
|
+ put_unused_fd(out_fence_fd);
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
return ret;
|
|
|
}
|