]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
video: tegra: nvmap: track dirty page count within handle
authorSri Krishna chowdary <schowdary@nvidia.com>
Thu, 2 Jul 2015 06:57:01 +0000 (12:27 +0530)
committermobile promotions <svcmobile_promotions@nvidia.com>
Wed, 8 Jul 2015 16:26:33 +0000 (09:26 -0700)
tracking ndirty can help in optimizing on cache clean
and zap operations.

Bug 200092803

Change-Id: Ic54aad1cbeaa61664e9e7429f5967d0f6f832aa2
Signed-off-by: Sri Krishna chowdary <schowdary@nvidia.com>
Reviewed-on: http://git-master/r/762274
Reviewed-by: Krishna Reddy <vdumpa@nvidia.com>
drivers/video/tegra/nvmap/nvmap_dev.c
drivers/video/tegra/nvmap/nvmap_priv.h

index 5bf594479cba972e2d3df8f9cf5e77a7848b7453..0bca070ae6e0be09c1aca22ea4c5a960bea5f521 100644 (file)
@@ -890,7 +890,13 @@ static int nvmap_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                if (nvmap_page_reserved(priv->handle->pgalloc.pages[offs]))
                        return VM_FAULT_SIGBUS;
                page = nvmap_to_page(priv->handle->pgalloc.pages[offs]);
-               nvmap_page_mkdirty(&priv->handle->pgalloc.pages[offs]);
+
+               if (nvmap_handle_track_dirty(priv->handle)) {
+                       mutex_lock(&priv->handle->lock);
+                       if (nvmap_page_mkdirty(&priv->handle->pgalloc.pages[offs]))
+                               atomic_inc(&priv->handle->pgalloc.ndirty);
+                       mutex_unlock(&priv->handle->lock);
+               }
        }
 
        if (page)
index adb746188392d99cf99aab5475493ff62f20581e..6192da947b76c6e198e040448fe080ffa06cdd8b 100644 (file)
@@ -471,14 +471,20 @@ static inline bool nvmap_page_dirty(struct page *page)
        return (unsigned long)page & 1UL;
 }
 
-static inline void nvmap_page_mkdirty(struct page **page)
+static inline bool nvmap_page_mkdirty(struct page **page)
 {
+       if (nvmap_page_dirty(*page))
+               return false;
        *page = (struct page *)((unsigned long)*page | 1UL);
+       return true;
 }
 
-static inline void nvmap_page_mkclean(struct page **page)
+static inline bool nvmap_page_mkclean(struct page **page)
 {
+       if (!nvmap_page_dirty(*page))
+               return false;
        *page = (struct page *)((unsigned long)*page & ~1UL);
+       return true;
 }
 
 static inline bool nvmap_page_reserved(struct page *page)
@@ -486,38 +492,49 @@ static inline bool nvmap_page_reserved(struct page *page)
        return !!((unsigned long)page & 2UL);
 }
 
-static inline void nvmap_page_mkreserved(struct page **page)
+static inline bool nvmap_page_mkreserved(struct page **page)
 {
+       if (nvmap_page_reserved(*page))
+               return false;
        *page = (struct page *)((unsigned long)*page | 2UL);
+       return true;
 }
 
-static inline void nvmap_page_mkunreserved(struct page **page)
+static inline bool nvmap_page_mkunreserved(struct page **page)
 {
+       if (!nvmap_page_reserved(*page))
+               return false;
        *page = (struct page *)((unsigned long)*page & ~2UL);
+       return true;
 }
 
 /*
  * FIXME: assume user space requests for reserve operations
  * are page aligned
  */
-static inline void nvmap_handle_mk(struct nvmap_handle *h,
-                                  u32 offset, u32 size,
-                                  void (*fn)(struct page **))
+static inline int nvmap_handle_mk(struct nvmap_handle *h,
+                                 u32 offset, u32 size,
+                                 bool (*fn)(struct page **))
 {
-       int i;
+       int i, nchanged = 0;
        int start_page = PAGE_ALIGN(offset) >> PAGE_SHIFT;
        int end_page = (offset + size) >> PAGE_SHIFT;
 
+       mutex_lock(&h->lock);
        if (h->heap_pgalloc) {
                for (i = start_page; i < end_page; i++)
-                       fn(&h->pgalloc.pages[i]);
+                       nchanged += fn(&h->pgalloc.pages[i]) ? 1 : 0;
        }
+       mutex_unlock(&h->lock);
+       return nchanged;
 }
 
 static inline void nvmap_handle_mkclean(struct nvmap_handle *h,
                                        u32 offset, u32 size)
 {
-       nvmap_handle_mk(h, offset, size, nvmap_page_mkclean);
+       int nchanged = nvmap_handle_mk(h, offset, size, nvmap_page_mkclean);
+       if (h->heap_pgalloc)
+               atomic_sub(nchanged, &h->pgalloc.ndirty);
 }
 
 static inline void nvmap_handle_mkunreserved(struct nvmap_handle *h,
@@ -611,6 +628,14 @@ static inline void nvmap_lru_reset(struct nvmap_handle *h)
        spin_unlock(&nvmap_dev->lru_lock);
 }
 
+static inline bool nvmap_handle_track_dirty(struct nvmap_handle *h)
+{
+       if (!h->heap_pgalloc)
+               return false;
+
+       return h->userflags & NVMAP_HANDLE_CACHE_SYNC;
+}
+
 void nvmap_dmabuf_release_stashed_maps(struct dma_buf *dmabuf);
 
 #endif /* __VIDEO_TEGRA_NVMAP_NVMAP_H */