|
@@ -28,12 +28,54 @@
|
|
|
#include <subdev/timer.h>
|
|
|
#include <subdev/fb.h>
|
|
|
#include <subdev/vm.h>
|
|
|
+#include <subdev/ltcg.h>
|
|
|
|
|
|
struct nvc0_vmmgr_priv {
|
|
|
struct nouveau_vmmgr base;
|
|
|
spinlock_t lock;
|
|
|
};
|
|
|
|
|
|
+
|
|
|
+/* Map from compressed to corresponding uncompressed storage type.
|
|
|
+ * The value 0xff represents an invalid storage type.
|
|
|
+ */
|
|
|
+const u8 nvc0_pte_storage_type_map[256] =
|
|
|
+{
|
|
|
+ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0xff, 0x01, /* 0x00 */
|
|
|
+ 0x01, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
+ 0xff, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, /* 0x10 */
|
|
|
+ 0x11, 0x11, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x26, 0x27, /* 0x20 */
|
|
|
+ 0x28, 0x29, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x30 */
|
|
|
+ 0xff, 0xff, 0x26, 0x27, 0x28, 0x29, 0x26, 0x27,
|
|
|
+ 0x28, 0x29, 0xff, 0xff, 0xff, 0xff, 0x46, 0xff, /* 0x40 */
|
|
|
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
+ 0xff, 0x46, 0x46, 0x46, 0x46, 0xff, 0xff, 0xff, /* 0x50 */
|
|
|
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x60 */
|
|
|
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x70 */
|
|
|
+ 0xff, 0xff, 0xff, 0x7b, 0xff, 0xff, 0xff, 0xff,
|
|
|
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0x7b, /* 0x80 */
|
|
|
+ 0x7b, 0x7b, 0xff, 0x8b, 0x8c, 0x8d, 0x8e, 0xff,
|
|
|
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x90 */
|
|
|
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
+ 0xff, 0xff, 0xff, 0x8b, 0x8c, 0x8d, 0x8e, 0xa7, /* 0xa0 */
|
|
|
+ 0xa8, 0xa9, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */
|
|
|
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7,
|
|
|
+ 0xa8, 0xa9, 0xaa, 0xc3, 0xff, 0xff, 0xff, 0xff, /* 0xc0 */
|
|
|
+ 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xc3, 0xc3,
|
|
|
+ 0xc3, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xd0 */
|
|
|
+ 0xfe, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe,
|
|
|
+ 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, /* 0xe0 */
|
|
|
+ 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xfe, 0xff,
|
|
|
+ 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, /* 0xf0 */
|
|
|
+ 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfe, 0xff
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
static void
|
|
|
nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 index,
|
|
|
struct nouveau_gpuobj *pgt[2])
|
|
@@ -68,10 +110,20 @@ static void
|
|
|
nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
|
|
|
struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta)
|
|
|
{
|
|
|
- u32 next = 1 << (vma->node->type - 8);
|
|
|
+ u64 next = 1 << (vma->node->type - 8);
|
|
|
|
|
|
phys = nvc0_vm_addr(vma, phys, mem->memtype, 0);
|
|
|
pte <<= 3;
|
|
|
+
|
|
|
+ if (mem->tag) {
|
|
|
+ struct nouveau_ltcg *ltcg =
|
|
|
+ nouveau_ltcg(vma->vm->vmm->base.base.parent);
|
|
|
+ u32 tag = mem->tag->offset + (delta >> 17);
|
|
|
+ phys |= (u64)tag << (32 + 12);
|
|
|
+ next |= (u64)1 << (32 + 12);
|
|
|
+ ltcg->tags_clear(ltcg, tag, cnt);
|
|
|
+ }
|
|
|
+
|
|
|
while (cnt--) {
|
|
|
nv_wo32(pgt, pte + 0, lower_32_bits(phys));
|
|
|
nv_wo32(pgt, pte + 4, upper_32_bits(phys));
|
|
@@ -85,10 +137,12 @@ nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
|
|
|
struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
|
|
|
{
|
|
|
u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 7 : 5;
|
|
|
+ /* compressed storage types are invalid for system memory */
|
|
|
+ u32 memtype = nvc0_pte_storage_type_map[mem->memtype & 0xff];
|
|
|
|
|
|
pte <<= 3;
|
|
|
while (cnt--) {
|
|
|
- u64 phys = nvc0_vm_addr(vma, *list++, mem->memtype, target);
|
|
|
+ u64 phys = nvc0_vm_addr(vma, *list++, memtype, target);
|
|
|
nv_wo32(pgt, pte + 0, lower_32_bits(phys));
|
|
|
nv_wo32(pgt, pte + 4, upper_32_bits(phys));
|
|
|
pte += 8;
|