[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