clear-pkgs-linux-iot-lts2018/0841-media-ici-Add-handler-...

161 lines
5.0 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "Yin.Zhiye" <zhiyeyix@intel.com>
Date: Tue, 11 Dec 2018 11:10:14 +0800
Subject: [PATCH] media: ici: Add handler to clear dma mapped buffers with dma
free
When dma free buffer, a handler is invoke where allocated pages are
zeroed, and that any kernel direct-mapped region is invalidated.
Change-Id: Ifd91f46f567ccf4608fa02f8b74727d13b011210
Tracked-On: OAM-72610
Tracked-On: OAM-73475
Tracked-On: OAM-72129
Tracked-On: OAM-72053
Signed-off-by: Yin.ZhiyeX <zhiyeyix@intel.com>
---
drivers/media/pci/intel/ici/ici-dma.c | 48 ++++++++++++++++++-
drivers/media/pci/intel/ici/ici-isys-stream.c | 6 ++-
2 files changed, 51 insertions(+), 3 deletions(-)
diff --git a/drivers/media/pci/intel/ici/ici-dma.c b/drivers/media/pci/intel/ici/ici-dma.c
index da501a2e8744..430ece88af69 100644
--- a/drivers/media/pci/intel/ici/ici-dma.c
+++ b/drivers/media/pci/intel/ici/ici-dma.c
@@ -18,6 +18,45 @@
#include "ipu-dma.h"
#include "ipu-mmu.h"
+static void ici_dma_clear_buffer(struct page *page, size_t size,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)
+ struct dma_attrs *attrs
+#else
+ unsigned long attrs
+#endif
+ )
+{
+ /*
+ * Ensure that the allocated pages are zeroed, and that any data
+ * lurking in the kernel direct-mapped region is invalidated.
+ */
+ if (PageHighMem(page)) {
+ for (; size > 0; page++, size -= PAGE_SIZE) {
+ void *ptr = kmap_atomic(page);
+
+ memset(ptr, 0, PAGE_SIZE);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)
+ if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+#else
+ if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
+#endif
+ clflush_cache_range(ptr, PAGE_SIZE);
+ kunmap_atomic(ptr);
+ }
+ } else {
+ void *ptr = page_address(page);
+
+ memset(ptr, 0, size);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)
+ if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+#else
+ if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
+#endif
+ clflush_cache_range(ptr, size);
+ }
+}
+
+
static struct page **__intel_ipu4_dma_alloc(struct device *dev,
size_t buf_size,
gfp_t gfp,
@@ -58,6 +97,7 @@ static struct page **__intel_ipu4_dma_alloc(struct device *dev,
page_list[i + j] = page_list[i] + j;
}
+ ici_dma_clear_buffer(page_list[i], PAGE_SIZE << order, attrs);
i += 1 << order;
num_pages -= 1 << order;
}
@@ -89,6 +129,7 @@ static int __intel_ipu4_dma_free(struct device *dev, struct page **page_list,
for (i = 0; i < num_pages; i++) {
if (page_list[i]) {
+ ici_dma_clear_buffer(page_list[i], PAGE_SIZE, attrs);
__free_pages(page_list[i], 0);
}
}
@@ -189,11 +230,11 @@ static void *intel_ipu4_dma_alloc(struct device *dev, size_t size,
vunmap(area->addr);
out_unmap:
- __intel_ipu4_dma_free(dev, pages, size, attrs);
for (i--; i >= 0; i--) {
iommu_unmap(mmu->dmap->domain, (iova->pfn_lo + i) << PAGE_SHIFT,
PAGE_SIZE);
}
+ __intel_ipu4_dma_free(dev, pages, size, attrs);
out_free_iova:
__free_iova(&mmu->dmap->iovad, iova);
@@ -212,6 +253,7 @@ static void intel_ipu4_dma_free(struct device *dev, size_t size, void *vaddr,
struct device *aiommu = to_ipu_bus_device(dev)->iommu;
struct ipu_mmu *mmu = dev_get_drvdata(aiommu);
struct vm_struct *area = find_vm_area(vaddr);
+ struct page **pages;
struct iova *iova = find_iova(&mmu->dmap->iovad,
dma_handle >> PAGE_SHIFT);
@@ -225,12 +267,14 @@ static void intel_ipu4_dma_free(struct device *dev, size_t size, void *vaddr,
size = PAGE_ALIGN(size);
+ pages = area->pages;
+
vunmap(vaddr);
iommu_unmap(mmu->dmap->domain, iova->pfn_lo << PAGE_SHIFT,
(iova->pfn_hi - iova->pfn_lo + 1) << PAGE_SHIFT);
- __intel_ipu4_dma_free(dev, area->pages, size, attrs);
+ __intel_ipu4_dma_free(dev, pages, size, attrs);
__free_iova(&mmu->dmap->iovad, iova);
diff --git a/drivers/media/pci/intel/ici/ici-isys-stream.c b/drivers/media/pci/intel/ici/ici-isys-stream.c
index 8d4ac4c1bf03..dc17cfbc0290 100644
--- a/drivers/media/pci/intel/ici/ici-isys-stream.c
+++ b/drivers/media/pci/intel/ici/ici-isys-stream.c
@@ -140,13 +140,15 @@ static int intel_ipu4_isys_library_close(struct ici_isys *isys)
{
struct device *dev = &isys->adev->dev;
int rval;
-
+ unsigned long flags;
/*
* Ask library to stop the isys fw. Actual close takes
* some time as the FW must stop its actions including code fetch
* to SP icache.
*/
+ spin_lock_irqsave(&isys->power_lock, flags);
rval = ipu_lib_call(device_close, isys);
+ spin_unlock_irqrestore(&isys->power_lock, flags);
if (rval)
dev_err(dev, "Device close failure: %d\n", rval);
@@ -155,10 +157,12 @@ static int intel_ipu4_isys_library_close(struct ici_isys *isys)
1000 * IPU_ISYS_TURNOFF_DELAY_US);
rval = ipu_lib_call_notrace(device_release, isys, 0);
+ spin_lock_irqsave(&isys->power_lock, flags);
if (!rval)
isys->fwcom = NULL; /* No further actions needed */
else
dev_err(dev, "Device release time out %d\n", rval);
+ spin_unlock_irqrestore(&isys->power_lock, flags);
return rval;
}
--
https://clearlinux.org