[PATCH 1/5] MTD: mtdram: properly handle the phys argument in the point method

Nicolas Pitre nicolas.pitre at linaro.org
Wed Oct 11 14:32:28 PDT 2017


On Wed, 11 Oct 2017, Richard Weinberger wrote:

> On Wed, Oct 11, 2017 at 5:26 AM, Nicolas Pitre <nicolas.pitre at linaro.org> wrote:
> > When the phys pointer is non null, the point method is expected to return
> > the physical address for the pointed area. In the case of the mtdram
> > driver we have to retrieve the physical address for the corresponding
> > vmalloc area. However, there is no guarantee that the vmalloc area is
> > made of physically contiguous pages. In that case we simply limit retlen
> > to the actually contiguous pages.
> >
> > Signed-off-by: Nicolas Pitre <nico at linaro.org>
> > ---
> >  drivers/mtd/devices/mtdram.c | 22 ++++++++++++++++++++++
> >  1 file changed, 22 insertions(+)
> >
> > diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c
> > index cbd8547d7a..7dbee8e62f 100644
> > --- a/drivers/mtd/devices/mtdram.c
> > +++ b/drivers/mtd/devices/mtdram.c
> > @@ -13,6 +13,7 @@
> >  #include <linux/slab.h>
> >  #include <linux/ioport.h>
> >  #include <linux/vmalloc.h>
> > +#include <linux/mm.h>
> >  #include <linux/init.h>
> >  #include <linux/mtd/mtd.h>
> >  #include <linux/mtd/mtdram.h>
> > @@ -69,6 +70,27 @@ static int ram_point(struct mtd_info *mtd, loff_t from, size_t len,
> >  {
> >         *virt = mtd->priv + from;
> >         *retlen = len;
> > +
> > +       if (phys) {
> > +               /* limit retlen to the number of contiguous physical pages */
> > +               unsigned long page_ofs = offset_in_page(*virt);
> > +               void *addr = *virt - page_ofs;
> > +               unsigned long pfn1, pfn0 = vmalloc_to_pfn(addr);
> > +
> > +               *phys = __pfn_to_phys(pfn0) + page_ofs;
> > +               len += page_ofs;
> > +               while (len > PAGE_SIZE) {
> > +                       len -= PAGE_SIZE;
> > +                       addr += PAGE_SIZE;
> > +                       pfn0++;
> > +                       pfn1 = vmalloc_to_pfn(addr);
> > +                       if (pfn1 != pfn0) {
> > +                               *retlen = *virt - addr;

In fact the above should be: *retlen = addr - *virt;

Let me know if I should repost.


Nicolas



More information about the linux-mtd mailing list