Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2017 Red Hat Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  */
0022 #include "vmm.h"
0023 
0024 #include <subdev/timer.h>
0025 
0026 static void
0027 nv41_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
0028          u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr)
0029 {
0030     u32 data = (addr >> 7) | 0x00000001; /* VALID. */
0031     while (ptes--) {
0032         VMM_WO032(pt, vmm, ptei++ * 4, data);
0033         data += 0x00000020;
0034     }
0035 }
0036 
0037 static void
0038 nv41_vmm_pgt_sgl(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
0039          u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
0040 {
0041     VMM_MAP_ITER_SGL(vmm, pt, ptei, ptes, map, nv41_vmm_pgt_pte);
0042 }
0043 
0044 static void
0045 nv41_vmm_pgt_dma(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
0046          u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
0047 {
0048 #if PAGE_SHIFT == 12
0049     nvkm_kmap(pt->memory);
0050     while (ptes--) {
0051         const u32 data = (*map->dma++ >> 7) | 0x00000001;
0052         VMM_WO032(pt, vmm, ptei++ * 4, data);
0053     }
0054     nvkm_done(pt->memory);
0055 #else
0056     VMM_MAP_ITER_DMA(vmm, pt, ptei, ptes, map, nv41_vmm_pgt_pte);
0057 #endif
0058 }
0059 
0060 static void
0061 nv41_vmm_pgt_unmap(struct nvkm_vmm *vmm,
0062            struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes)
0063 {
0064     VMM_FO032(pt, vmm, ptei * 4, 0, ptes);
0065 }
0066 
0067 static const struct nvkm_vmm_desc_func
0068 nv41_vmm_desc_pgt = {
0069     .unmap = nv41_vmm_pgt_unmap,
0070     .dma = nv41_vmm_pgt_dma,
0071     .sgl = nv41_vmm_pgt_sgl,
0072 };
0073 
0074 static const struct nvkm_vmm_desc
0075 nv41_vmm_desc_12[] = {
0076     { PGT, 17, 4, 0x1000, &nv41_vmm_desc_pgt },
0077     {}
0078 };
0079 
0080 static void
0081 nv41_vmm_flush(struct nvkm_vmm *vmm, int level)
0082 {
0083     struct nvkm_device *device = vmm->mmu->subdev.device;
0084 
0085     mutex_lock(&vmm->mmu->mutex);
0086     nvkm_wr32(device, 0x100810, 0x00000022);
0087     nvkm_msec(device, 2000,
0088         if (nvkm_rd32(device, 0x100810) & 0x00000020)
0089             break;
0090     );
0091     nvkm_wr32(device, 0x100810, 0x00000000);
0092     mutex_unlock(&vmm->mmu->mutex);
0093 }
0094 
0095 static const struct nvkm_vmm_func
0096 nv41_vmm = {
0097     .valid = nv04_vmm_valid,
0098     .flush = nv41_vmm_flush,
0099     .page = {
0100         { 12, &nv41_vmm_desc_12[0], NVKM_VMM_PAGE_HOST },
0101         {}
0102     }
0103 };
0104 
0105 int
0106 nv41_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size,
0107          void *argv, u32 argc, struct lock_class_key *key, const char *name,
0108          struct nvkm_vmm **pvmm)
0109 {
0110     return nv04_vmm_new_(&nv41_vmm, mmu, 0, managed, addr, size,
0111                  argv, argc, key, name, pvmm);
0112 }