In the Linux AGP/GART driver, the agp_memory struct contains a memory[] array with the physical address of every page in the block.
Currently, the elements of the memory[] array are the actual values put into the GATT, i.e., they contain the valid bit and any other bits required by the GART chipset as well as the physical address. These mangled physical addresses are used by DRM, for example in DRM(vm_nopage), where those extra chipset-specific bits have to be masked out to obtain the actual physical address. I propose a change along the lines of the following patch, which makes the elements of memory[] plain physical addresses and keeps all the chipset-specific bits encapsulated inside the AGP/GART module. The general idea is to move the "masking" (chipset-specific address mangling) from the memory allocation path to the GATT insertion path. I'm not a DRM guru, so I'm sure there are subtleties I'm missing, and I know there are some interface versioning issues to work out, but I'd appreciate any feedback on the approach and advice on how to proceed. The attached patch is against 2.4.16 with the IA64 patch applied. --- linux+ia64/drivers/char/drm/drmP.h Tue Nov 27 13:54:53 2001 +++ linux/drivers/char/drm/drmP.h Thu Dec 6 14:11:34 2001 @@ -628,7 +628,9 @@ unsigned long base; int agp_mtrr; int cant_use_aperture; +#ifdef PAGE_MASK_INTERFACE unsigned long page_mask; +#endif } drm_agp_head_t; #endif --- linux+ia64/drivers/char/drm/drm_vm.h Tue Nov 27 13:54:53 2001 +++ linux/drivers/char/drm/drm_vm.h Thu Dec 6 10:57:39 2001 @@ -115,18 +115,7 @@ * Get the page, inc the use count, and return it */ offset = (baddr - agpmem->bound) >> PAGE_SHIFT; - - /* - * This is bad. What we really want to do here is unmask - * the GART table entry held in the agp_memory structure. - * There isn't a convenient way to call agp_bridge.unmask_ - * memory from here, so hard code it for now. - */ -#if defined(__ia64__) - paddr = (agpmem->memory->memory[offset] & 0xffffff) << 12; -#else - paddr = agpmem->memory->memory[offset] & dev->agp->page_mask; -#endif + paddr = agpmem->memory->memory[offset]; page = virt_to_page(__va(paddr)); get_page(page); --- linux+ia64/drivers/char/drm/drm_agpsupport.h Tue Nov 27 13:54:53 2001 +++ linux/drivers/char/drm/drm_agpsupport.h Thu Dec 6 10:56:34 2001 @@ -321,10 +321,14 @@ } #if LINUX_VERSION_CODE <= 0x020408 head->cant_use_aperture = 0; +#ifdef PAGE_MASK_INTERFACE head->page_mask = ~(0xfff); +#endif #else head->cant_use_aperture = head->agp_info.cant_use_aperture; +#ifdef PAGE_MASK_INTERFACE head->page_mask = head->agp_info.page_mask; +#endif #endif DRM_INFO("AGP %d.%d on %s @ 0x%08lx %ZuMB\n", --- linux+ia64/drivers/char/agp/agpgart_be.c Tue Nov 27 13:54:53 2001 +++ linux/drivers/char/agp/agpgart_be.c Thu Dec 6 10:59:51 2001 @@ -212,8 +212,6 @@ if(agp_bridge.cant_use_aperture == 0) { if (curr->page_count != 0) { for (i = 0; i < curr->page_count; i++) { - curr->memory[i] = agp_bridge.unmask_memory( - curr->memory[i]); agp_bridge.agp_destroy_page((unsigned long) phys_to_virt(curr->memory[i])); } @@ -302,10 +300,7 @@ agp_free_memory(new); return NULL; } - new->memory[i] = - agp_bridge.mask_memory( - virt_to_phys((void *) new->memory[i]), - type); + new->memory[i] = virt_to_phys((void *) new->memory[i]); new->page_count++; } } else { @@ -338,7 +333,7 @@ #else paddr = pte_val(*pte) & PAGE_MASK; #endif - new->memory[i] = agp_bridge.mask_memory(paddr, type); + new->memory[i] = paddr; } new->page_count = page_count; @@ -403,10 +398,12 @@ info->current_memory = atomic_read(&agp_bridge.current_memory_agp); info->cant_use_aperture = agp_bridge.cant_use_aperture; +#ifdef PAGE_MASK_INTERFACE for(i = 0; i < agp_bridge.num_of_masks; i++) page_mask |= agp_bridge.mask_memory(page_mask, i); info->page_mask = ~page_mask; +#endif } /* End - Routine to copy over information structure */ @@ -825,7 +822,7 @@ mem->is_flushed = TRUE; } for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { - agp_bridge.gatt_table[j] = mem->memory[i]; + agp_bridge.gatt_table[j] = agp_bridge.mask_memory(mem->memory[i], mem->type); } agp_bridge.tlb_flush(mem); @@ -1067,7 +1064,8 @@ CACHE_FLUSH(); for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { OUTREG32(intel_i810_private.registers, - I810_PTE_BASE + (j * 4), mem->memory[i]); + I810_PTE_BASE + (j * 4), + agp_bridge.mask_memory(mem->memory[i], mem->type)); } CACHE_FLUSH(); @@ -1133,10 +1131,7 @@ agp_free_memory(new); return NULL; } - new->memory[0] = - agp_bridge.mask_memory( - virt_to_phys((void *) new->memory[0]), - type); + new->memory[0] = virt_to_phys((void *) new->memory[0]); new->page_count = 1; new->num_scratch_pages = 1; new->type = AGP_PHYS_MEMORY; @@ -1373,7 +1368,8 @@ CACHE_FLUSH(); for (i = 0, j = pg_start; i < mem->page_count; i++, j++) - OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (j * 4),mem->memory[i]); + OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (j * 4), + agp_bridge.mask_memory(mem->memory[i], mem->type)); CACHE_FLUSH(); @@ -1434,7 +1430,7 @@ return(NULL); } - nw->memory[0] = agp_bridge.mask_memory(virt_to_phys((void *) nw->memory[0]),type); + nw->memory[0] = virt_to_phys((void *) nw->memory[0]); nw->page_count = 1; nw->num_scratch_pages = 1; nw->type = AGP_PHYS_MEMORY; @@ -1485,10 +1481,6 @@ #endif /* CONFIG_AGP_I810 */ - #ifdef CONFIG_AGP_INTEL - -#endif /* CONFIG_AGP_I810 */ - #ifdef CONFIG_AGP_I460 /* BIOS configures the chipset so that one of two apbase registers are used */ @@ -1496,6 +1488,7 @@ /* 460 supports multiple GART page sizes, so GART pageshift is dynamic */ static u8 intel_i460_pageshift = 12; +static u32 intel_i460_pagesize; /* Keep track of which is larger, chipset or kernel page size. */ static u32 intel_i460_cpk = 1; @@ -1523,6 +1516,7 @@ /* Determine the GART page size */ pci_read_config_byte(agp_bridge.dev, INTEL_I460_GXBCTL, &temp); intel_i460_pageshift = (temp & I460_4M_PS) ? 22 : 12; + intel_i460_pagesize = 1UL << intel_i460_pageshift; values = A_SIZE_8(agp_bridge.aperture_sizes); @@ -1737,7 +1731,7 @@ { int i, j, k, num_entries; void *temp; - unsigned int hold; + unsigned long paddr; unsigned int read_back; /* @@ -1769,10 +1763,11 @@ for (i = 0, j = pg_start; i < mem->page_count; i++) { - hold = (unsigned int) (mem->memory[i]); + paddr = mem->memory[i]; - for (k = 0; k < I460_CPAGES_PER_KPAGE; k++, j++, hold++) - agp_bridge.gatt_table[j] = hold; + for (k = 0; k < I460_CPAGES_PER_KPAGE; k++, j++, paddr += intel_i460_pagesize) + agp_bridge.gatt_table[j] = (unsigned int) + agp_bridge.mask_memory(paddr, mem->type); } /* @@ -1886,6 +1881,7 @@ int num_entries; void *temp; unsigned int read_back; + unsigned long paddr; temp = agp_bridge.current_size; num_entries = A_SIZE_8(temp)->num_entries; @@ -1934,18 +1930,17 @@ for(pg = start_pg, i = 0; pg <= end_pg; pg++) { + paddr = agp_bridge.unmask_memory(agp_bridge.gatt_table[pg]); for(idx = ((pg == start_pg) ? start_offset : 0); idx < ((pg == end_pg) ? (end_offset + 1) : I460_KPAGES_PER_CPAGE); idx++, i++) { - i460_pg_detail[pg][idx] = agp_bridge.gatt_table[pg] + - ((idx * PAGE_SIZE) >> 12); + mem->memory[i] = paddr + (idx * PAGE_SIZE); + i460_pg_detail[pg][idx] = + agp_bridge.mask_memory(mem->memory[i], mem->type); + i460_pg_count[pg]++; - - /* Finally we fill in mem->memory... */ - mem->memory[i] = ((unsigned long) (0xffffff & - i460_pg_detail[pg][idx])) << 12; } } @@ -1959,7 +1954,7 @@ int num_entries; void *temp; unsigned int read_back; - unsigned long addr; + unsigned long paddr; temp = agp_bridge.current_size; num_entries = A_SIZE_8(temp)->num_entries; @@ -1986,13 +1981,11 @@ /* Free GART pages if they are unused */ if(i460_pg_count[pg] == 0) { - addr = (0xffffffUL & (unsigned long) - (agp_bridge.gatt_table[pg])) << 12; - - agp_bridge.gatt_table[pg] = 0; + paddr = agp_bridge.unmask_memory(agp_bridge.gatt_table[pg]); + agp_bridge.gatt_table[pg] = agp_bridge.scratch_page; read_back = agp_bridge.gatt_table[pg]; - intel_i460_free_large_page(pg, addr); + intel_i460_free_large_page(pg, paddr); } } _______________________________________________ Dri-devel mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/dri-devel