On Fri, 2009-03-06 at 12:19 +0530, Vishal Thanki wrote: > Hello, > > I have implemented a write() call for my character driver. I need to get > the page address of the "__user" buffer passed in write() call from user > space. The idea is to get the actual physical address corresponding to > user address and then do DMA operations using that physical address. But > for that I will require page address first. Is there any way I can get > the corresponding page address of a "__user" buffer?? Hi Vishal, Below is the code snippet which is doing something similar you want. Key function you want is "page_address". I don't think you can directly do DMA on user space buffers. You will have to map them in kernel space first. (experts correct me if I am wrong). /* * Get your caller's mm to hold lock on its vm object and map the pages * to kernel space. */ mm = current->mm; /* * Calculate the pages fom the buffer size given by user. The get_user_pages * needs the count in pages */ pgcount = ((unsigned long)buf+count+PAGE_SIZE-1)/PAGE_SIZE - (unsigned long)buf/PAGE_SIZE; if (pgcount >= MAX_SPI_TRANSFERS) { printk(KERN_ERR "spidev: page count more than spi transfers!\n"); kfree(list); return -EFBIG; } /* allocate mapped pages list. */ maplist = kmalloc (pgcount * sizeof (struct page *), GFP_KERNEL); if (!maplist) { up(&gReadWriteLock); printk(KERN_ERR "spidev: cannot allocate maplist!\n"); kfree(list); return -ENOMEM; } flush_cache_all(); /* * acquire the semaphore for mm structure of process. get_user_pages * *thinks* we have acquired this semaphore. We are not sleeping * interruptible. Once we are in sleep user won't be able to kill us. */ down_read(&mm->mmap_sem); /* * map the pages: They are mapped and locked, so we can directly hand the * address over to DMA for direct transfers */ err= get_user_pages(current, mm, (unsigned long)buf, pgcount, 1, 0, maplist, NULL); /* release */ up_read(&mm->mmap_sem); if (err < 0) { printk(KERN_ERR "spidev: Can't get user pages!\n"); /* do you clean ups and return */ } pgcount = err; /* What I am preparing here is a spi transfer list. This list has physical page * addresses for which DMA controller can be programmed. */ for (i = 0; i < pgcount; i++) { flush_dcache_page(maplist[i]); /* Your page address */ list->tx[i] = list->rx[i] = page_address(maplist[i]) + ofs; list->txlen[i] = list->rxlen[i] = pagelen; ofs = 0; /* all subsequent transfers start at beginning of a page */ count = count - pagelen; pagelen = (count < PAGE_SIZE) ? count : PAGE_SIZE; } list->nr_transfers = pgcount; /* doing some other SPI transfer inits */ ...... <snip> /* * release each page one by one. Note: we are not marking the pages as dirty. * Because the data is transferred and we don't need to swap it now */ while (pgcount--) { page_cache_release (maplist[pgcount]); } ------------ Hope this would help. Regards Chauhan -- To unsubscribe from this list: send an email with "unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx Please read the FAQ at http://kernelnewbies.org/FAQ