Understanding OOB data read implementation

David Peverley pev at sketchymonkey.com
Fri Oct 15 07:13:11 EDT 2010


Hello!

I've been adding OOB data read support into a driver I'm working with
and I'm trying to understand how the offset works. As a starting point
I picked the doc2000.c driver (From the latest kernel.org 2.6.35.7
kernel)

The following happens in the driver :
    static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
                            struct mtd_oob_ops *ops)
    {
            ...
            ofs += ops->ooboffs;
            ...

This is what I don't understand - why does ofs have ooboffs added? In
the MTD char driver mtdchar.c the oob's read gets set up thus :
    static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
            uint32_t length, void __user *ptr, uint32_t __user *retp)
    {
        ...
        ops.ooboffs = start & (mtd->oobsize - 1);
        ...
        start &= ~((uint64_t)mtd->oobsize - 1);
        ret = mtd->read_oob(mtd, start, &ops);
        ...

So... my reading of this is that the requested OOB read offset is
passed into mtd_do_readoob() as the "start" parameter. This is then
copied into the ops structure and passed in to read_oob() as two
copies (via start and again inside the ops structure). This same logic
is also followed in doc2001.c and doc2001plus.c.

If that's the case, I don't understand why in doc2000.c it's being
added - is this not effectively using *double* the requested offset?

Also as a side note I suspect that mtd_do_readoob() would be a smidge
clearer if the above was re-factored to avoid the duplication of the
masking to oobsize :
    static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
            uint32_t length, void __user *ptr, uint32_t __user *retp)
    {
        ...
        start &= ~((uint64_t)mtd->oobsize - 1);
        ...
        ops.ooboffs = start;
        ...
        ret = mtd->read_oob(mtd, start, &ops);
        ...

Cheers all!

~Pev



More information about the linux-mtd mailing list