return page;
}
-static void svm_migrate_put_sys_page(unsigned long addr)
-{
- struct page *page;
-
- page = pfn_to_page(addr >> PAGE_SHIFT);
- unlock_page(page);
- put_page(page);
-}
-
static unsigned long svm_migrate_successful_pages(struct migrate_vma *migrate)
{
unsigned long mpages = 0;
dma_addr_t *scratch, u64 npages)
{
struct device *dev = adev->dev;
- u64 *src;
+ struct page *dpage = NULL;
dma_addr_t *dst;
- struct page *dpage;
+ u64 *src;
+
u64 i = 0, j;
u64 addr;
int r = 0;
r = dma_mapping_error(dev, dst[i]);
if (r) {
dev_err(adev->dev, "%s: fail %d dma_map_page\n", __func__, r);
+ dst[i] = 0;
goto out_oom;
}
dst[i] >> PAGE_SHIFT, page_to_pfn(dpage));
migrate->dst[i] = migrate_pfn(page_to_pfn(dpage));
+
+ dpage = NULL;
j++;
}
- r = svm_migrate_copy_memory_gart(adev, dst + i - j, src + i - j, j,
- FROM_VRAM_TO_RAM, mfence);
-
+ if (j > 0)
+ r = svm_migrate_copy_memory_gart(adev, dst + i - j, src + i - j, j,
+ FROM_VRAM_TO_RAM, mfence);
out_oom:
if (r) {
pr_debug("failed %d copy to ram\n", r);
+
+ /* first release current dpage when dma_map_page fail */
+ if (dpage) {
+ unlock_page(dpage);
+ put_page(dpage);
+ }
+
+ /* release previous allocated sys pages and unmap dma address */
while (i--) {
- svm_migrate_put_sys_page(dst[i]);
+
+ if (dst[i]) {
+ dma_unmap_page(dev, dst[i], PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
+ dst[i] = 0;
+ }
+
+ dpage = migrate_pfn_to_page(migrate->dst[i]);
+ if (!dpage)
+ continue;
+
+ unlock_page(dpage);
+ put_page(dpage);
migrate->dst[i] = 0;
}
}