[PATCH,RFC] [MTD] replace MTD_NORFLASH with MTD_GENERIC_TYPE
Nicolas Pitre
nico at cam.org
Wed May 31 11:59:03 EDT 2006
On Wed, 31 May 2006, Artem B. Bityutskiy wrote:
> On Wed, 2006-05-31 at 10:01 -0400, Nicolas Pitre wrote:
> > Don't be ridiculous. There is no way you can find 20 capabilities total
> > for a generic MTD interface.
>
> I'm not sure it can't be the case.
Last time we enumerated less than 10 parameters that would cover more
than 90% of all cases in a clean and obvious way. One is
mtd->block_write_size. For most NOR flash this is 1. For Sibley this
is 1024. For ECC NOR I think it is 16. For NAND it is another value.
Etc. Why should that value be determined _each_ time at runtime based
on mtd->type using your macro proposal while it can be directly obtained
from mtd->block_write_size?
This also means that JFFS2 can use:
if (mtd->block_write_size > 1)
use_wbuf();
while your proposal would require the equivalent of:
if (mtd->type == SIBLEY || mtd->type == NAND ||
mtd->type == DATAFLASH || mtd->type == ECC_NOR || ... )
use_wbuf();
And yet wbuf() still doesn't know how big the buffer should be. Don't
you see the difference?
And if a driver for another type of flash is added to the kernel then it
only needs to initialise its own value for mtd->block_write_size and
JFFS2 will just work with no change.
Whereas with your own view the fact that mtd->type is set to GOAT_FLASH
then you need to modyfy _all_ users of the MTD interface so they learn
to also consider mtd->type == GOAT_FLASH and to hardcode its buffer size
which might well be yet another value like 8192.
Isn't that obvious enough that the mtd->type method is suboptimal and
obfuscates the code? What do you not get at this point?
> > > 2a. In general, the capabilities thing is application-dependent. And it
> > > must stay in application's area, not deep in drivers.
> >
> > Not true. The capabilities are function of the hardware not the
> > application.
> OK, I agree with you. It is a function of the hardware. But, the
> mtd->flags field anyway becomes application dependent, just because the
> number of hardware features is very large, and you introduce only those
> flags *applications* need.
So? What's the problem?
> Example. Let's consider the AG-AND flash. Some of them have a property
> when you erase some eraseblocks, but the neighboring eraseblocks get
> slowly corrupted. Is this a flash feature? - Yes. Do you have a flag for
> it? - No.
Why not?
> So, the idea is that number of features is potentially high. And there
> is a dependency on the application present in a way.
If you need to support completely fubar flash then of course the
capability model may not cover them adequately and you might have to
bastardize the application code based on
if (mtd->type == FUBAR_FLASH)
do_this_fubar_hack();
But this is maybe 10% of the cases. The other 90% will fit in the
generic model just fine.
> > > 3a: If I'm a user of MTD, and I want to add 20 new capability, do I have
> > > to change MTD itself? It's not my business to do this.
> >
> > If you want to add new capabilities, you only have to care about users
> > of those capabilities and of course users that worked without them
> > before will just continue to work if they ignore them.
> I also have to check if other flashes have these capabilities, and add
> it to them if yes. So I have to change drivers.
You don't _have_ to. Again, if the code worked fine without knowledge
of a given capability before then the addition of support for a given
capability won't break those who don't advertise that capability.
But if we consider your own view, the addition of a new MTD _user_
require that the author of that new module knows about all flash types
currently provided by MTD and cope with each of their specific
characteristics which should be deduced from mtd->type. If instead it
only needs to cope with mtd->block_write_size to use that same example
again then things are much simpler for both user module authors and
flash driver authors.
> > > 4a. How wide is the mtd->flags field? 32 bits? So, you restrict me by 32
> > > capabilities? And if I need more, I have to combine the existing ones?
> > > Why is it better then using mtd->type?
> >
> > Who said capabilities have to be only single bits?
> >
> > And even if the capability field as you insist to see it has only 32
> > bits, what prevents you from extending it in the unlikely event more
> > bits might be needed?
> Isn't it bad to have mtd->flags1, mtd->flags2, etc?
Why not? In fact it can be made into a structure bit field that the C
language already supports rather well.
struct MTD_blah {
...
int can_do_x : 1;
int can_DO_Y : 1;
INT CAN_DO_Z : 1;
...
}
ONce set those bits are always read-only so no locking issues, etc.
> > > So, this is not an extensible solution.
> > Artem you're more brilliant than that.
> Frankly, I can't get the meaning of this :-(
I'm sorry for you then.
> > > 2. OK, what do you offer instead (the question nobody asked yet)?
> > >
> > > Forget about mtd->flags. Leave alone mtd->type. Add an
> > > include/linux/mtd/flash_capabilities.h header which looks like this:
> > >
> > > /* If the flash allows to clear individual bits */
> > > #define mtd_can_clear_bits(mtd) (mtd->type == MTD_NORFLASH)
> > > /* If the goat may be milked */
> > > #define mtd_can_milk_a_goat(mtd) (bah)
> > > ....
> > > etc.
> > >
> > > So, you have your set of capabilities. You use this header in JFFS2 and
> > > clean it up. Your task is solved.
> >
> > And the runtime code is both larger and slower. And the source is
> > even more obfuscated. Isn't that great?
> >
> As to "And the source is even more obfuscated" - I do not understand
> this. Why? The same if (can_milk_a_goat()) in both cases. Or do you mean
> after gcc -E ? Then yes.
You have to dig into another header file to know what can_milk_a_goat()
actually means in the context of MTD, especially since, according to
you, this capability is always derived from mtd->type.
> I was telling about a general approach, you're telling about technical
> details. Well, if you care about code size and speed, then create
> mtd_capabilities.c, call add an init_capabilities() call which is called
> on initialization, and have variables for each feature.
I care about a general approach that [surprise surprise] also allows for
obvious code from a readability point of view and produce small and fast
runtime code.
> #define can_milk_a_goat(mtd) (mtd->priv->can_mlk_a_goat)
>
> The Idea still stays unchanged - it's a thin layer over mtd->type.
> Implement it differently.
I'm glad you say yourself that it is an extra (IMHO unneeded) layer over
mtd->type.
> I still don't see any drawback of this approach.
It is an extra layer over mtd->type. That's the drawback.
> The advantage is that
> it'll all be put in one place, and that'll be not the driver who
> initialize it.
This is nonsense. It is like saying that all architectures Linux
supports should be merged into one directory instead of arch/arm,
arch/alpha, etc. After all the code in those architecture
subdirectories is used by the same kernel scheduler.
> Finally, I don't really care now much about how capabilities are
> implemented, and I wrote this. Implement it your way - fine, it is not
> fundamental, I'm just suggesting another approach, may I?
You do so without ever acknowledging the disadvantages your approach has
over the other one which is disconcerting.
> I care more
> about the MTD_GENERIC_TYPE stuff, which is senseless in my opinion.
And I agreed with you on that point already. Did you miss it?
> I wrote about this, and don't see any reaction.
Do you ignore everything I wrote not addressed to you directly?
Nicolas
More information about the linux-mtd
mailing list