Hello Everyone, This is my first post to this list, so hopefully I read all the instructions correctly and am posting to the correct list. I have a driver which maps some kernel allocated memory to user space which works, and now I am trying to set that memory non-cacheable, on a power PC using the Denx ELDK (linux-2.6.24) on a PPC460ex. I have attempted several ways of doing this: 1. Calling the macro SetPageUncached() in linux/page-flags.h. This fails because for some reason the bit PG_uncached is only defined for processors whose BITS_PER_LONG > 32. 2. Calling the macro pgprot_noncached() in asm/pgtable-ppc32.h. This just doesn't seem to have any effect. 3. Setting flags in the struct vm_area_struct->vm_flags before calling remap_pfn_range(). This doesn't work because the flag I expected to find VM_NONCACHED is not defined anywhere. 4. Calling the function dma_alloc_coherent() instead of kmalloc() to allocate the memory(). This causes some kind of bus error or exception in the kernel - I believe because I passed in NULL for the device which I read is a bug with the kernel. Has anyone done this successfuly on a PPC440 or PPC460? Any tips would be appreciated. Code snippets below... Thanks! // // allocating the memory in the kernel // static int __init mapper_init_module(void) { int rc; unsigned int i = 0; phys_addr_t phys_addr; MDEBUG("Initializing module...\n"); /* allocate the memory and pad with pages so that we can * make sure to page align */ km.raw = kmalloc((2*PAGE_COUNT+1)*PAGE_SIZE, GFP_KERNEL); if (!km.raw) return -ENOMEM; /* now need to adjust our other pointer to page align to 64 Kb boundary*/ /* Note, that we just do the mal and set pal to it since if it is 64Kb aligned * then it is also page aligned */ km.mal = (int *)((((unsigned long)km.raw) + ((1<<16) - 1)) & 0xFFFF0000); /*km.pal = (int *)((((unsigned long)km.raw) + (PAGE_SIZE - 1)) & PAGE_MASK);*/ km.pal = km.mal; MDEBUG("Allocated %ld bytes of kernel space for driver at kernel logical address %p...\n", PAGE_COUNT*PAGE_SIZE, km.raw); MDEBUG("page aligned = %p 64k aligned = %p\n", km.pal, km.mal); MDEBUG("Physical address = 0x%lx...\n", __pa(km.raw)); . . . . /* lock down / reserve the pages in memory */ { int k; for (k=0; k<PAGE_COUNT*PAGE_SIZE; k+=PAGE_SIZE) { struct page* pg = virt_to_page(((unsigned long)km.pal) + k); SetPageReserved(pg); //SetPageUncached(pg); } } . . . . } // // mapping the kernel space to user space // static int mapper_mmap(struct file *fip, struct vm_area_struct *vma) { int rc; /* * make sure to allocate the proper number of pages when using * mmap. We check it for correctness here. */ unsigned long len = vma->vm_end - vma->vm_start; /* if user tries to map bigger space than we have, error */ if (PAGE_COUNT * PAGE_SIZE < len) return -EIO; pgprot_noncached(vma->vm_page_prot); //vma->vm_flags |= VM_NONCACHED | VM_RESERVED; vma->vm_flags |= VM_RESERVED; /* map the physical area into one buffer */ rc = remap_pfn_range(vma, vma->vm_start, virt_to_phys( (void*)km.pal)>>PAGE_SHIFT, len, vma->vm_page_prot); MDEBUG("Mapped %ld bytes at virt address 0x%lx to mapper file descriptor...\n", len, vma->vm_start); /* return an error to the caller if remap fails */ return (rc < 0 ? rc : 0); }
_______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev