···17171818#include <linux/spinlock.h>1919#include <linux/shmem_fs.h>2020+#include <linux/dma-buf.h>20212122#include "msm_drv.h"2223#include "msm_gem.h"···7675 drm_gem_put_pages(obj, msm_obj->pages, true, false);7776 msm_obj->pages = NULL;7877 }7878+}7979+8080+struct page **msm_gem_get_pages(struct drm_gem_object *obj)8181+{8282+ struct drm_device *dev = obj->dev;8383+ struct page **p;8484+ mutex_lock(&dev->struct_mutex);8585+ p = get_pages(obj);8686+ mutex_unlock(&dev->struct_mutex);8787+ return p;8888+}8989+9090+void msm_gem_put_pages(struct drm_gem_object *obj)9191+{9292+ /* when we start tracking the pin count, then do something here */7993}80948195int msm_gem_mmap_obj(struct drm_gem_object *obj,···526510527511 drm_gem_free_mmap_offset(obj);528512529529- if (msm_obj->vaddr)530530- vunmap(msm_obj->vaddr);513513+ if (obj->import_attach) {514514+ if (msm_obj->vaddr)515515+ dma_buf_vunmap(obj->import_attach->dmabuf, msm_obj->vaddr);531516532532- put_pages(obj);517517+ /* Don't drop the pages for imported dmabuf, as they are not518518+ * ours, just free the array we allocated:519519+ */520520+ if (msm_obj->pages)521521+ drm_free_large(msm_obj->pages);522522+523523+ } else {524524+ if (msm_obj->vaddr)525525+ vunmap(msm_obj->vaddr);526526+ put_pages(obj);527527+ }533528534529 if (msm_obj->resv == &msm_obj->_resv)535530 reservation_object_fini(msm_obj->resv);···576549 return ret;577550}578551579579-struct drm_gem_object *msm_gem_new(struct drm_device *dev,580580- uint32_t size, uint32_t flags)552552+static int msm_gem_new_impl(struct drm_device *dev,553553+ uint32_t size, uint32_t flags,554554+ struct drm_gem_object **obj)581555{582556 struct msm_drm_private *priv = dev->dev_private;583557 struct msm_gem_object *msm_obj;584584- struct drm_gem_object *obj = NULL;585585- int ret;586586-587587- WARN_ON(!mutex_is_locked(&dev->struct_mutex));588588-589589- size = PAGE_ALIGN(size);590558591559 switch (flags & MSM_BO_CACHE_MASK) {592560 case MSM_BO_UNCACHED:···591569 default:592570 dev_err(dev->dev, "invalid cache flag: %x\n",593571 (flags & MSM_BO_CACHE_MASK));594594- ret = -EINVAL;595595- goto fail;572572+ return -EINVAL;596573 }597574598575 msm_obj = kzalloc(sizeof(*msm_obj), GFP_KERNEL);599599- if (!msm_obj) {600600- ret = -ENOMEM;601601- goto fail;602602- }603603-604604- obj = &msm_obj->base;605605-606606- ret = drm_gem_object_init(dev, obj, size);607607- if (ret)608608- goto fail;576576+ if (!msm_obj)577577+ return -ENOMEM;609578610579 msm_obj->flags = flags;611580···606593 INIT_LIST_HEAD(&msm_obj->submit_entry);607594 INIT_LIST_HEAD(&msm_obj->inactive_work);608595 list_add_tail(&msm_obj->mm_list, &priv->inactive_list);596596+597597+ *obj = &msm_obj->base;598598+599599+ return 0;600600+}601601+602602+struct drm_gem_object *msm_gem_new(struct drm_device *dev,603603+ uint32_t size, uint32_t flags)604604+{605605+ struct drm_gem_object *obj;606606+ int ret;607607+608608+ WARN_ON(!mutex_is_locked(&dev->struct_mutex));609609+610610+ size = PAGE_ALIGN(size);611611+612612+ ret = msm_gem_new_impl(dev, size, flags, &obj);613613+ if (ret)614614+ goto fail;615615+616616+ ret = drm_gem_object_init(dev, obj, size);617617+ if (ret)618618+ goto fail;619619+620620+ return obj;621621+622622+fail:623623+ if (obj)624624+ drm_gem_object_unreference_unlocked(obj);625625+626626+ return ERR_PTR(ret);627627+}628628+629629+struct drm_gem_object *msm_gem_import(struct drm_device *dev,630630+ uint32_t size, struct sg_table *sgt)631631+{632632+ struct msm_gem_object *msm_obj;633633+ struct drm_gem_object *obj;634634+ int ret, npages;635635+636636+ size = PAGE_ALIGN(size);637637+638638+ ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj);639639+ if (ret)640640+ goto fail;641641+642642+ drm_gem_private_object_init(dev, obj, size);643643+644644+ npages = size / PAGE_SIZE;645645+646646+ msm_obj = to_msm_bo(obj);647647+ msm_obj->sgt = sgt;648648+ msm_obj->pages = drm_malloc_ab(npages, sizeof(struct page *));649649+ if (!msm_obj->pages) {650650+ ret = -ENOMEM;651651+ goto fail;652652+ }653653+654654+ ret = drm_prime_sg_to_page_addr_arrays(sgt, msm_obj->pages, NULL, npages);655655+ if (ret)656656+ goto fail;609657610658 return obj;611659
+56
drivers/gpu/drm/msm/msm_gem_prime.c
···11+/*22+ * Copyright (C) 2013 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_gem.h"2020+2121+2222+struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj)2323+{2424+ struct msm_gem_object *msm_obj = to_msm_bo(obj);2525+ BUG_ON(!msm_obj->sgt); /* should have already pinned! */2626+ return msm_obj->sgt;2727+}2828+2929+void *msm_gem_prime_vmap(struct drm_gem_object *obj)3030+{3131+ return msm_gem_vaddr(obj);3232+}3333+3434+void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)3535+{3636+ /* TODO msm_gem_vunmap() */3737+}3838+3939+struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev,4040+ size_t size, struct sg_table *sg)4141+{4242+ return msm_gem_import(dev, size, sg);4343+}4444+4545+int msm_gem_prime_pin(struct drm_gem_object *obj)4646+{4747+ if (!obj->import_attach)4848+ msm_gem_get_pages(obj);4949+ return 0;5050+}5151+5252+void msm_gem_prime_unpin(struct drm_gem_object *obj)5353+{5454+ if (!obj->import_attach)5555+ msm_gem_put_pages(obj);5656+}