/*
* mods_mem.c - This file is part of NVIDIA MODS kernel driver.
*
* Copyright (c) 2008-2018, NVIDIA CORPORATION. All rights reserved.
*
* NVIDIA MODS kernel driver is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* NVIDIA MODS kernel driver is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NVIDIA MODS kernel driver.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "mods_internal.h"
#include <linux/pagemap.h>
#ifdef CONFIG_BIGPHYS_AREA
#include <linux/bigphysarea.h>
#endif
#if defined(MODS_HAS_SET_DMA_MASK)
#include <linux/dma-mapping.h>
#include <linux/of.h>
#endif
static int mods_post_alloc(struct MODS_PHYS_CHUNK *pt,
u64 phys_addr,
struct MODS_MEM_INFO *p_mem_info);
static void mods_pre_free(struct MODS_PHYS_CHUNK *pt,
struct MODS_MEM_INFO *p_mem_info);
static u64 mods_compress_nvlink_addr(struct pci_dev *dev, u64 addr);
static u64 mods_expand_nvlink_addr(struct pci_dev *dev, u64 addr47);
/****************************
* DMA MAP HELPER FUNCTIONS *
****************************/
/* Unmap a page if it was mapped */
static void mods_dma_unmap_page(struct MODS_DMA_MAP *p_dma_map,
struct MODS_MAP_CHUNK *pm)
{
if (!pm->pt)
return;
pm->map_addr = mods_expand_nvlink_addr(p_dma_map->dev, pm->map_addr);
pci_unmap_page(p_dma_map->dev,
pm->map_addr,
(1U<<pm->pt->order)*PAGE_SIZE,
DMA_BIDIRECTIONAL);
mods_debug_printk(DEBUG_MEM_DETAILED,
"Unmapped map_addr=0x%llx dma_addr=0x%llx on dev %x:%x:%x.%x\n",
(unsigned long long)pm->map_addr,
(unsigned long long)pm->pt->dma_addr,
pci_domain_nr(p_dma_map->dev->bus),
p_dma_map->dev->bus->number,
PCI_SLOT(p_dma_map->dev->devfn),
PCI_FUNC(p_dma_map->dev->devfn));
}
/* Unmap and delete the specified DMA mapping */
static int mods_dma_unmap_and_free(struct MODS_MEM_INFO *p_mem_info,
struct MODS_DMA_MAP *p_del_map)
{
struct MODS_DMA_MAP *p_dma_map;
struct list_head *head;
|