17e102996Smaya/*
27e102996Smaya * Copyright (C) 2012-2018 Rob Clark <robclark@freedesktop.org>
37e102996Smaya *
47e102996Smaya * Permission is hereby granted, free of charge, to any person obtaining a
57e102996Smaya * copy of this software and associated documentation files (the "Software"),
67e102996Smaya * to deal in the Software without restriction, including without limitation
77e102996Smaya * the rights to use, copy, modify, merge, publish, distribute, sublicense,
87e102996Smaya * and/or sell copies of the Software, and to permit persons to whom the
97e102996Smaya * Software is furnished to do so, subject to the following conditions:
107e102996Smaya *
117e102996Smaya * The above copyright notice and this permission notice (including the next
127e102996Smaya * paragraph) shall be included in all copies or substantial portions of the
137e102996Smaya * Software.
147e102996Smaya *
157e102996Smaya * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167e102996Smaya * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177e102996Smaya * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
187e102996Smaya * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
197e102996Smaya * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
207e102996Smaya * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
217e102996Smaya * SOFTWARE.
227e102996Smaya *
237e102996Smaya * Authors:
247e102996Smaya *    Rob Clark <robclark@freedesktop.org>
257e102996Smaya */
267e102996Smaya
277e102996Smaya#include <unistd.h>
287ec681f3Smrg#include <sys/stat.h>
297ec681f3Smrg#include <sys/types.h>
307e102996Smaya
317e102996Smaya#include "msm_priv.h"
327e102996Smaya
337ec681f3Smrgstatic void
347ec681f3Smrgmsm_device_destroy(struct fd_device *dev)
357e102996Smaya{
367ec681f3Smrg   struct msm_device *msm_dev = to_msm_device(dev);
377ec681f3Smrg   if (util_queue_is_initialized(&msm_dev->submit_queue)) {
387ec681f3Smrg      util_queue_destroy(&msm_dev->submit_queue);
397ec681f3Smrg   }
407ec681f3Smrg   free(msm_dev);
417e102996Smaya}
427e102996Smaya
437e102996Smayastatic const struct fd_device_funcs funcs = {
447ec681f3Smrg   .bo_new_handle = msm_bo_new_handle,
457ec681f3Smrg   .bo_from_handle = msm_bo_from_handle,
467ec681f3Smrg   .pipe_new = msm_pipe_new,
477ec681f3Smrg   .destroy = msm_device_destroy,
487e102996Smaya};
497e102996Smaya
507ec681f3Smrgstruct fd_device *
517ec681f3Smrgmsm_device_new(int fd, drmVersionPtr version)
527e102996Smaya{
537ec681f3Smrg   struct msm_device *msm_dev;
547ec681f3Smrg   struct fd_device *dev;
557ec681f3Smrg
567ec681f3Smrg   STATIC_ASSERT(FD_BO_PREP_READ == MSM_PREP_READ);
577ec681f3Smrg   STATIC_ASSERT(FD_BO_PREP_WRITE == MSM_PREP_WRITE);
587ec681f3Smrg   STATIC_ASSERT(FD_BO_PREP_NOSYNC == MSM_PREP_NOSYNC);
597ec681f3Smrg
607ec681f3Smrg   msm_dev = calloc(1, sizeof(*msm_dev));
617ec681f3Smrg   if (!msm_dev)
627ec681f3Smrg      return NULL;
637ec681f3Smrg
647ec681f3Smrg   dev = &msm_dev->base;
657ec681f3Smrg   dev->funcs = &funcs;
667ec681f3Smrg
677ec681f3Smrg   /* async submit_queue currently only used for msm_submit_sp: */
687ec681f3Smrg   if (version->version_minor >= FD_VERSION_SOFTPIN) {
697ec681f3Smrg      /* Note the name is intentionally short to avoid the queue
707ec681f3Smrg       * thread's comm truncating the interesting part of the
717ec681f3Smrg       * process name.
727ec681f3Smrg       */
737ec681f3Smrg      util_queue_init(&msm_dev->submit_queue, "sq", 8, 1, 0, NULL);
747ec681f3Smrg   }
757ec681f3Smrg
767ec681f3Smrg   if (version->version_minor >= FD_VERSION_CACHED_COHERENT) {
777ec681f3Smrg      struct drm_msm_gem_new new_req = {
787ec681f3Smrg         .size = 0x1000,
797ec681f3Smrg         .flags = MSM_BO_CACHED_COHERENT,
807ec681f3Smrg      };
817e102996Smaya
827ec681f3Smrg      /* The kernel is new enough to support MSM_BO_CACHED_COHERENT,
837ec681f3Smrg       * but that is not a guarantee that the device we are running
847ec681f3Smrg       * on supports it.  So do a test allocation to find out.
857ec681f3Smrg       */
867ec681f3Smrg      if (!drmCommandWriteRead(fd, DRM_MSM_GEM_NEW,
877ec681f3Smrg                               &new_req, sizeof(new_req))) {
887ec681f3Smrg         struct drm_gem_close close_req = {
897ec681f3Smrg            .handle = new_req.handle,
907ec681f3Smrg         };
917ec681f3Smrg         drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &close_req);
927e102996Smaya
937ec681f3Smrg         dev->has_cached_coherent = true;
947ec681f3Smrg      }
957ec681f3Smrg   }
967e102996Smaya
977ec681f3Smrg   dev->bo_size = sizeof(struct msm_bo);
987e102996Smaya
997ec681f3Smrg   return dev;
1007e102996Smaya}
101