[PATCH] mtd: OneNAND: samsung: Write DMA support
Kyungmin Park
kmpark at infradead.org
Wed Jun 29 03:22:01 EDT 2011
Hi Artem,
There's missing patch, can you add l2-mtd tree?
Thank you,
Kyungmin Park
On Wed, Jun 8, 2011 at 7:18 PM, Kyungmin Park <kmpark at infradead.org> wrote:
> From: Kyungmin Park <kyungmin.park at samsung.com>
>
> Implement the write DMA feature. It can reduce the CPU usage when write.
>
> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
> ---
> diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
> index 3306b5b..f24cb6f 100644
> --- a/drivers/mtd/onenand/samsung.c
> +++ b/drivers/mtd/onenand/samsung.c
> @@ -712,6 +712,74 @@ normal:
> return 0;
> }
>
> +static int s5pc110_write_bufferram(struct mtd_info *mtd, int area,
> + const unsigned char *buffer, int offset, size_t count)
> +{
> + struct onenand_chip *this = mtd->priv;
> + struct device *dev = &onenand->pdev->dev;
> + void __iomem *p;
> + void *buf = (void *) buffer;
> + dma_addr_t dma_src, dma_dst;
> + int err, ofs, page_dma = 0;
> +
> + p = this->base + area;
> + if (ONENAND_CURRENT_BUFFERRAM(this)) {
> + if (area == ONENAND_DATARAM)
> + p += this->writesize;
> + else
> + p += mtd->oobsize;
> + }
> +
> + if (count != mtd->writesize || offset & 3 || (size_t) buf & 3)
> + goto normal;
> +
> + /* Handle vmalloc address */
> + if (buf >= high_memory) {
> + struct page *page;
> +
> + if (((size_t) buf & PAGE_MASK) !=
> + ((size_t) (buf + count - 1) & PAGE_MASK))
> + goto normal;
> +
> + page = vmalloc_to_page(buf);
> + if (unlikely(!page))
> + goto normal;
> +
> + /* Page offset */
> + ofs = ((size_t) buf & ~PAGE_MASK);
> + page_dma = 1;
> +
> + /* DMA routine */
> + dma_src = dma_map_page(dev, page, ofs, count, DMA_TO_DEVICE);
> + dma_dst = onenand->phys_base + (p - this->base);
> + } else {
> + /* DMA routine */
> + dma_src = dma_map_single(dev, buf, count, DMA_TO_DEVICE);
> + dma_dst = onenand->phys_base + (p - this->base);
> + }
> +
> + if (dma_mapping_error(dev, dma_src)) {
> + dev_err(dev, "Couldn't map a %d byte buffer for DMA\n", count);
> + goto normal;
> + }
> +
> + err = s5pc110_dma_ops((void *) dma_dst, (void *) dma_src,
> + count, S5PC110_DMA_DIR_WRITE);
> +
> + if (page_dma)
> + dma_unmap_page(dev, dma_src, count, DMA_TO_DEVICE);
> + else
> + dma_unmap_single(dev, dma_src, count, DMA_TO_DEVICE);
> +
> + if (!err)
> + return 0;
> +
> +normal:
> + memcpy(p + offset, buffer, count);
> +
> + return 0;
> +}
> +
> static int s5pc110_chip_probe(struct mtd_info *mtd)
> {
> /* Now just return 0 */
> @@ -844,6 +912,7 @@ static void s3c_onenand_setup(struct mtd_info *mtd)
> } else if (onenand->type == TYPE_S5PC110) {
> /* Use generic onenand functions */
> this->read_bufferram = s5pc110_read_bufferram;
> + this->write_bufferram = s5pc110_write_bufferram;
> this->chip_probe = s5pc110_chip_probe;
> return;
> } else {
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>
More information about the linux-mtd
mailing list