Re: [RFC] MTD driver for MMC cards

2007-04-15 Thread Jörn Engel
On Mon, 16 April 2007 01:33:17 +0200, Arnd Bergmann wrote:
> 
> There is also still some need for performance testing. Jörn
> brought up the point that if a specific card can't have multiple
> open erase block simulateously, it's rather pointless for
> logfs. It might still be useful to use jffs2 on those cards,
> because IFAIK that only writes to one erase block at any
> time.

This appears to be a problem for practically all consumer-available
flash media.  They spend a lot of effort trying to hide any flash
properties from their users.  And while this is a decent strategy for
FAT, ext3, ntfs and similar, it is actually very inefficient for a flash
filesystem.

After talking to several manufacturers, most seemed to be fairly
open-minded towards supporting an alternate interface with raw flash
access.  So much for the good news.  Bad news is that such an elternate
interface still needs to be defined.

Jörn

-- 
Courage is not the absence of fear, but rather the judgement that
something else is more important than fear.
-- Ambrose Redmoon
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC] MTD driver for MMC cards

2007-04-15 Thread Arnd Bergmann
This is a new version of the driver I posted back in January. I now
have hardware to test it and fixed a number of bugs, most of which
are the ones that Pierre told me about in the first place.

It now seems to work fine with the mtdblock driver, which of course
it entirely pointless.

I've tried using it with jffs2 once, but get an immediate oops,
which still needs some investigation.

I'm also not sure what to do about SDHC media, but probably the
easiest solutions is to disallow them with this driver -- the
mtd layer doesn't deal with media larger than 4GB anyway at
this point.

There is also still some need for performance testing. Jörn
brought up the point that if a specific card can't have multiple
open erase block simulateously, it's rather pointless for
logfs. It might still be useful to use jffs2 on those cards,
because IFAIK that only writes to one erase block at any
time.

Signed-off-by: Arnd Bergmann <[EMAIL PROTECTED]>

---

Index: olpc-2.6/drivers/mmc/mmc.c
===
--- olpc-2.6.orig/drivers/mmc/mmc.c
+++ olpc-2.6/drivers/mmc/mmc.c
@@ -621,6 +621,7 @@ static void mmc_decode_csd(struct mmc_ca
csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
+   csd->erase_blksize = UNSTUFF_BITS(resp, 39, 7);
break;
case 1:
/*
@@ -649,6 +650,8 @@ static void mmc_decode_csd(struct mmc_ca
csd->r2w_factor = 4; /* Unused */
csd->write_blkbits = 9;
csd->write_partial = 0;
+#warning need to read au_size for sdhc
+   csd->erase_blksize = 0; // 8192 << au_size;
break;
default:
printk("%s: unrecognised CSD structure version %d\n",
@@ -691,6 +694,8 @@ static void mmc_decode_csd(struct mmc_ca
csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
+   csd->erase_blksize = (UNSTUFF_BITS(resp, 37, 5) + 1) *
+   (UNSTUFF_BITS(resp, 42, 5) + 1);
}
 }
 
Index: olpc-2.6/include/linux/mmc/card.h
===
--- olpc-2.6.orig/include/linux/mmc/card.h
+++ olpc-2.6/include/linux/mmc/card.h
@@ -32,6 +32,7 @@ struct mmc_csd {
unsigned intmax_dtr;
unsigned intread_blkbits;
unsigned intwrite_blkbits;
+   unsigned interase_blksize;
unsigned intcapacity;
unsigned intread_partial:1,
read_misalign:1,
Index: olpc-2.6/drivers/mmc/mmc_mtd.c
===
--- /dev/null
+++ olpc-2.6/drivers/mmc/mmc_mtd.c
@@ -0,0 +1,366 @@
+/*
+ * MTD driver for MMC cards
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * check if a write command was completed correctly, must be called
+ * with host claimed.
+ */
+static int mmc_mtd_get_status(struct mmc_card *card)
+{
+   int err;
+   struct mmc_command cmd;
+
+   do {
+   cmd = (struct mmc_command) {
+   .opcode = MMC_SEND_STATUS,
+   .arg = card->rca << 16,
+   .flags = MMC_RSP_R1 | MMC_CMD_AC,
+   };
+
+   err = mmc_wait_for_cmd(card->host, , 5);
+   if (err) {
+   dev_err(>dev, "error %d requesting status\n", 
err);
+   break;
+   }
+   } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
+
+   return err;
+}
+
+/*
+ * erase a range of erase groups aligned to mtd->erase_size
+ */
+static int mmc_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+   struct mmc_card *card = mtd->priv;
+   struct mmc_command cmd[3] = { {
+   .opcode = MMC_ERASE_GROUP_START,
+   .arg = instr->addr,
+   .flags = MMC_RSP_R1 | MMC_CMD_AC,
+   }, {
+   .opcode = MMC_ERASE_GROUP_END,
+   .arg = instr->addr + instr->len,
+   .flags = MMC_RSP_R1 | MMC_CMD_AC,
+   }, {
+   .opcode = MMC_ERASE,
+   .flags = MMC_RSP_R1B | MMC_CMD_AC,
+   },
+   };
+   int err, i;
+
+   dev_dbg(>dev, "%s: from %d len %d\n", __FUNCTION__,
+   instr->addr, instr->len);
+
+   instr->state = MTD_ERASING;
+   err = 0;
+   err = mmc_card_claim_host(card);
+   if (err)
+   goto error;
+
+   

Re: [RFC] MTD driver for MMC cards

2007-04-15 Thread Arnd Bergmann
This is a new version of the driver I posted back in January. I now
have hardware to test it and fixed a number of bugs, most of which
are the ones that Pierre told me about in the first place.

It now seems to work fine with the mtdblock driver, which of course
it entirely pointless.

I've tried using it with jffs2 once, but get an immediate oops,
which still needs some investigation.

I'm also not sure what to do about SDHC media, but probably the
easiest solutions is to disallow them with this driver -- the
mtd layer doesn't deal with media larger than 4GB anyway at
this point.

There is also still some need for performance testing. Jörn
brought up the point that if a specific card can't have multiple
open erase block simulateously, it's rather pointless for
logfs. It might still be useful to use jffs2 on those cards,
because IFAIK that only writes to one erase block at any
time.

Signed-off-by: Arnd Bergmann [EMAIL PROTECTED]

---

Index: olpc-2.6/drivers/mmc/mmc.c
===
--- olpc-2.6.orig/drivers/mmc/mmc.c
+++ olpc-2.6/drivers/mmc/mmc.c
@@ -621,6 +621,7 @@ static void mmc_decode_csd(struct mmc_ca
csd-r2w_factor = UNSTUFF_BITS(resp, 26, 3);
csd-write_blkbits = UNSTUFF_BITS(resp, 22, 4);
csd-write_partial = UNSTUFF_BITS(resp, 21, 1);
+   csd-erase_blksize = UNSTUFF_BITS(resp, 39, 7);
break;
case 1:
/*
@@ -649,6 +650,8 @@ static void mmc_decode_csd(struct mmc_ca
csd-r2w_factor = 4; /* Unused */
csd-write_blkbits = 9;
csd-write_partial = 0;
+#warning need to read au_size for sdhc
+   csd-erase_blksize = 0; // 8192  au_size;
break;
default:
printk(%s: unrecognised CSD structure version %d\n,
@@ -691,6 +694,8 @@ static void mmc_decode_csd(struct mmc_ca
csd-r2w_factor = UNSTUFF_BITS(resp, 26, 3);
csd-write_blkbits = UNSTUFF_BITS(resp, 22, 4);
csd-write_partial = UNSTUFF_BITS(resp, 21, 1);
+   csd-erase_blksize = (UNSTUFF_BITS(resp, 37, 5) + 1) *
+   (UNSTUFF_BITS(resp, 42, 5) + 1);
}
 }
 
Index: olpc-2.6/include/linux/mmc/card.h
===
--- olpc-2.6.orig/include/linux/mmc/card.h
+++ olpc-2.6/include/linux/mmc/card.h
@@ -32,6 +32,7 @@ struct mmc_csd {
unsigned intmax_dtr;
unsigned intread_blkbits;
unsigned intwrite_blkbits;
+   unsigned interase_blksize;
unsigned intcapacity;
unsigned intread_partial:1,
read_misalign:1,
Index: olpc-2.6/drivers/mmc/mmc_mtd.c
===
--- /dev/null
+++ olpc-2.6/drivers/mmc/mmc_mtd.c
@@ -0,0 +1,366 @@
+/*
+ * MTD driver for MMC cards
+ */
+#include linux/init.h
+#include linux/module.h
+#include linux/mmc/card.h
+#include linux/mmc/protocol.h
+#include linux/mmc/host.h
+#include linux/scatterlist.h
+#include linux/mtd/mtd.h
+
+/*
+ * check if a write command was completed correctly, must be called
+ * with host claimed.
+ */
+static int mmc_mtd_get_status(struct mmc_card *card)
+{
+   int err;
+   struct mmc_command cmd;
+
+   do {
+   cmd = (struct mmc_command) {
+   .opcode = MMC_SEND_STATUS,
+   .arg = card-rca  16,
+   .flags = MMC_RSP_R1 | MMC_CMD_AC,
+   };
+
+   err = mmc_wait_for_cmd(card-host, cmd, 5);
+   if (err) {
+   dev_err(card-dev, error %d requesting status\n, 
err);
+   break;
+   }
+   } while (!(cmd.resp[0]  R1_READY_FOR_DATA));
+
+   return err;
+}
+
+/*
+ * erase a range of erase groups aligned to mtd-erase_size
+ */
+static int mmc_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+   struct mmc_card *card = mtd-priv;
+   struct mmc_command cmd[3] = { {
+   .opcode = MMC_ERASE_GROUP_START,
+   .arg = instr-addr,
+   .flags = MMC_RSP_R1 | MMC_CMD_AC,
+   }, {
+   .opcode = MMC_ERASE_GROUP_END,
+   .arg = instr-addr + instr-len,
+   .flags = MMC_RSP_R1 | MMC_CMD_AC,
+   }, {
+   .opcode = MMC_ERASE,
+   .flags = MMC_RSP_R1B | MMC_CMD_AC,
+   },
+   };
+   int err, i;
+
+   dev_dbg(card-dev, %s: from %d len %d\n, __FUNCTION__,
+   instr-addr, instr-len);
+
+   instr-state = MTD_ERASING;
+   err = 0;
+   

Re: [RFC] MTD driver for MMC cards

2007-04-15 Thread Jörn Engel
On Mon, 16 April 2007 01:33:17 +0200, Arnd Bergmann wrote:
 
 There is also still some need for performance testing. Jörn
 brought up the point that if a specific card can't have multiple
 open erase block simulateously, it's rather pointless for
 logfs. It might still be useful to use jffs2 on those cards,
 because IFAIK that only writes to one erase block at any
 time.

This appears to be a problem for practically all consumer-available
flash media.  They spend a lot of effort trying to hide any flash
properties from their users.  And while this is a decent strategy for
FAT, ext3, ntfs and similar, it is actually very inefficient for a flash
filesystem.

After talking to several manufacturers, most seemed to be fairly
open-minded towards supporting an alternate interface with raw flash
access.  So much for the good news.  Bad news is that such an elternate
interface still needs to be defined.

Jörn

-- 
Courage is not the absence of fear, but rather the judgement that
something else is more important than fear.
-- Ambrose Redmoon
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC] MTD driver for MMC cards

2007-01-03 Thread Pierre Ossman
Arnd Bergmann wrote:
> 
> One promising effort for a replacement is Jörn's logfs
> (http://wiki.laptop.org/go/Logfs), which should scale well to many
> gigabytes. A driver based on MMC would be a nice development tool
> for that, since it enables regular PCs as a debugging machine
> instead of having to load test kernels onto an actual embedded
> machine.
> 

A bit of a niche area, but as long as this driver doesn't look like high 
maintenance then it could be enough.

> Another thing I have been thinking about was an MTD version of
> fat16/fat32. There are a number of optimizations that you can
> do for flash media, including:
> 
> - limiting the number of writes to the FAT
> - erasing blocks when they are freed in the FS
> - always writing full erase blocks if the erase block
>   size matches the cluster size
> - optimize for wear leveling instead of avoiding
>   fragmentation
> 

These sound like they would be nicer in the block layer, to cover other devices 
where you know there is flash at the bottom.

> I read that the SD cards have some restrictions of how
> the fat fs needs to be laid out on them, presumably to
> make sure clusters are aligned with erase blocks.
> Do you have any specific information on what SD actually
> requires?
> 

No, as we don't give a rats ass about them. I don't know why they stuck a FAT 
requirement into the spec. Perhaps Microsoft wanted a chance at the 
extortio^Wlicense money for any patent issues.

> 
> ok, I'll have a look. I keep having trouble identifying the right
> specifications (physical spec sounded like it was only about wiring
> and electric properties, so I did not look at that). Maybe it would

That had me fooled for quite a while as well.

> be good if you could put pointers to the relevant documents into
> your Wiki?

Probably. I haven't really put that much time into the wiki lately. It turned 
out to be a one man show, so I'm doubting its usefulness.

>> First of all, you cannot assume that read_blkbits is a valid block
>> size when doing writes. 
> 
> Right, I see. I introduced that bug when I merged parts of the read and
> write paths.
> 
> Is it fair to assume that write_blkbits is always bigger than
> read_blkbits, so that one can be used in both cases?
> 

There is some relation, yes, but I don't remember the details right now. More 
important is that the card can only be set to one block size at any given time 
(both read and write). So unless you want
terrible latency by switching block size back and forth I'd suggest selecting 
one size and sticking with it.

As the newer cards only support a block size of 512 bytes, the most future 
proof would be to use that.

> 
> I tried to do multiple block access at first, but then took it out again.
> If it turns out valuable to have these, I'll implement it properly later.
> Does it make a difference performance-wise to do larger accesses?
> 

Yes. On my rather slow ISA device, the speedup was over 100% for writes.

Rgds
-- 
 -- Pierre Ossman

  Linux kernel, MMC maintainerhttp://www.kernel.org
  PulseAudio, core developer  http://pulseaudio.org
  rdesktop, core developer  http://www.rdesktop.org
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC] MTD driver for MMC cards

2007-01-03 Thread Pierre Ossman
Arnd Bergmann wrote:
 
 One promising effort for a replacement is Jörn's logfs
 (http://wiki.laptop.org/go/Logfs), which should scale well to many
 gigabytes. A driver based on MMC would be a nice development tool
 for that, since it enables regular PCs as a debugging machine
 instead of having to load test kernels onto an actual embedded
 machine.
 

A bit of a niche area, but as long as this driver doesn't look like high 
maintenance then it could be enough.

 Another thing I have been thinking about was an MTD version of
 fat16/fat32. There are a number of optimizations that you can
 do for flash media, including:
 
 - limiting the number of writes to the FAT
 - erasing blocks when they are freed in the FS
 - always writing full erase blocks if the erase block
   size matches the cluster size
 - optimize for wear leveling instead of avoiding
   fragmentation
 

These sound like they would be nicer in the block layer, to cover other devices 
where you know there is flash at the bottom.

 I read that the SD cards have some restrictions of how
 the fat fs needs to be laid out on them, presumably to
 make sure clusters are aligned with erase blocks.
 Do you have any specific information on what SD actually
 requires?
 

No, as we don't give a rats ass about them. I don't know why they stuck a FAT 
requirement into the spec. Perhaps Microsoft wanted a chance at the 
extortio^Wlicense money for any patent issues.

 
 ok, I'll have a look. I keep having trouble identifying the right
 specifications (physical spec sounded like it was only about wiring
 and electric properties, so I did not look at that). Maybe it would

That had me fooled for quite a while as well.

 be good if you could put pointers to the relevant documents into
 your Wiki?

Probably. I haven't really put that much time into the wiki lately. It turned 
out to be a one man show, so I'm doubting its usefulness.

 First of all, you cannot assume that read_blkbits is a valid block
 size when doing writes. 
 
 Right, I see. I introduced that bug when I merged parts of the read and
 write paths.
 
 Is it fair to assume that write_blkbits is always bigger than
 read_blkbits, so that one can be used in both cases?
 

There is some relation, yes, but I don't remember the details right now. More 
important is that the card can only be set to one block size at any given time 
(both read and write). So unless you want
terrible latency by switching block size back and forth I'd suggest selecting 
one size and sticking with it.

As the newer cards only support a block size of 512 bytes, the most future 
proof would be to use that.

 
 I tried to do multiple block access at first, but then took it out again.
 If it turns out valuable to have these, I'll implement it properly later.
 Does it make a difference performance-wise to do larger accesses?
 

Yes. On my rather slow ISA device, the speedup was over 100% for writes.

Rgds
-- 
 -- Pierre Ossman

  Linux kernel, MMC maintainerhttp://www.kernel.org
  PulseAudio, core developer  http://pulseaudio.org
  rdesktop, core developer  http://www.rdesktop.org
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC] MTD driver for MMC cards

2007-01-01 Thread David Woodhouse
On Mon, 2007-01-01 at 23:22 +0100, Arnd Bergmann wrote:
> There are multiple efforts in progress to get a jffs2 replacement. NAND
> flash in embedded devices has the same size as it has on MMC card
> potentially, so we will need one soon. David Woodhouse has pushed the
> limit that jffs2 can reasonably used to 512MB, which is the size used
> in the OLPC XO laptop. If there are ways to get beyond that (which I
> find unlikely), there will be a hard limit 2GB or 4GB because of
> limitations in the fs layout.

The main weakness of JFFS2 (at this kind of size) is that there _is_ no
fs layout -- so there isn't a hard 2GiB or 4GiB limit in the format,
because we never encode offsets anywhere but in memory.

We'll push JFFS2 further than the current 512MiB by enlarging the data
nodes -- so each node covers something like 16KiB of data instead of
only 4KiB, and then there'll be about 1/3 as many of them, which will
cut the memory usage and reduce the amount we need to read in the
"summary" blocks. But logfs is the way forward, I agree.

-- 
dwmw2

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC] MTD driver for MMC cards

2007-01-01 Thread Arnd Bergmann
On Sunday 31 December 2006 13:32, Pierre Ossman wrote:
> Arnd Bergmann wrote:
>
> I'm a complete MTD noob, but what uses does the MTD layer have besides
> JFFS2. If it's none, than this advantage isn't that big of a deal. 
>
> > * It becomes possible to use MMC cards with jffs2 even with CONFIG_BLOCK
> >   disabled, which can save a significant amount of kernel memory on
> >   small machines that have an MMC slot but no other block device.
> > 
> 
> From what I've heard, JFFS2 is close to unusuable on the sizes of modern
> SD/MMC cards. So I'd like to see some more use cases before I'm ready
> to let this in.  

There are multiple efforts in progress to get a jffs2 replacement. NAND
flash in embedded devices has the same size as it has on MMC card
potentially, so we will need one soon. David Woodhouse has pushed the
limit that jffs2 can reasonably used to 512MB, which is the size used
in the OLPC XO laptop. If there are ways to get beyond that (which I
find unlikely), there will be a hard limit 2GB or 4GB because of
limitations in the fs layout.

One promising effort for a replacement is Jörn's logfs
(http://wiki.laptop.org/go/Logfs), which should scale well to many
gigabytes. A driver based on MMC would be a nice development tool
for that, since it enables regular PCs as a debugging machine
instead of having to load test kernels onto an actual embedded
machine.

Another thing I have been thinking about was an MTD version of
fat16/fat32. There are a number of optimizations that you can
do for flash media, including:

- limiting the number of writes to the FAT
- erasing blocks when they are freed in the FS
- always writing full erase blocks if the erase block
  size matches the cluster size
- optimize for wear leveling instead of avoiding
  fragmentation

I read that the SD cards have some restrictions of how
the fat fs needs to be laid out on them, presumably to
make sure clusters are aligned with erase blocks.
Do you have any specific information on what SD actually
requires?

> > I still want to be sure that I'm on the right track with this driver
> > and did not make a conceptual mistake.
> > 
> 
> I can comment it from a MMC perspective, but the MTD stuff I will have to 
> assume is correct.

ok, that's fine. I've talked to a few MTD people about it already
and I understand much more about MTD than I do about MMC ;-)

> > @@ -616,6 +616,8 @@ static void mmc_decode_csd(struct mmc_ca
> > csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
> > csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
> > csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
> > +   csd->erase_blksize = (UNSTUFF_BITS(resp, 37, 5) + 1) *
> > +   (UNSTUFF_BITS(resp, 42, 5) + 1);
> > } else {
> > /*
> >  * We only understand CSD structure v1.1 and v1.2.
> 
> NAK. SD uses another format for erase blocks. See the simplified physical 
> spec.

ok, I'll have a look. I keep having trouble identifying the right
specifications (physical spec sounded like it was only about wiring
and electric properties, so I did not look at that). Maybe it would
be good if you could put pointers to the relevant documents into
your Wiki?

> > +/*
> > + * transfer a block to/from the card. The block needs to be aligned
> > + * to mtd->writesize. If we want to implement an mtd_writev method,
> > + * this needs to use stream operations with an appropriate stop
> > + * command as well.
> > + */
> > +static int mmc_mtd_transfer_low(struct mmc_card *card, loff_t off, size_t 
> > len,
> > +   size_t *retlen, u_char *buf, int write)
> > +{
> > +   struct scatterlist sg;
> > +   struct mmc_data data = {
> > +   .blksz = 1 << card->csd.read_blkbits,
> > +   .blocks = len >> card->csd.read_blkbits,
> 
> First of all, you cannot assume that read_blkbits is a valid block
> size when doing writes. 

Right, I see. I introduced that bug when I merged parts of the read and
write paths.

Is it fair to assume that write_blkbits is always bigger than
read_blkbits, so that one can be used in both cases?

> Secondly, the cards default in a block size of 512 bytes, so you need
> to tell the card your desired block size during probe. 

Ok.

> > +   .flags = write ? MMC_DATA_WRITE : MMC_DATA_READ,
> > +   .sg = ,
> > +   .sg_len = 1,
> > +   };
> > +   struct mmc_command cmd = {
> > +   .arg = off,
> > +   .data = ,
> > +   .flags = MMC_RSP_R1 | MMC_CMD_ADTC,
> > +   .opcode = write ? MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK,
> 
> You set .blocks above, so I have to assume it can be more than 1.
> So you need to change the opcodes accordingly. 
>
> > +   };
> > +   struct mmc_request mrq = {
> > +   .cmd = ,
> > +   .data = ,
> > +   };
> 
> And it also means you need a stop command.

I tried to do multiple block access at first, but then took it out again.
If it turns out valuable to have 

Re: [RFC] MTD driver for MMC cards

2007-01-01 Thread Arnd Bergmann
On Sunday 31 December 2006 13:32, Pierre Ossman wrote:
 Arnd Bergmann wrote:

 I'm a complete MTD noob, but what uses does the MTD layer have besides
 JFFS2. If it's none, than this advantage isn't that big of a deal. 

  * It becomes possible to use MMC cards with jffs2 even with CONFIG_BLOCK
disabled, which can save a significant amount of kernel memory on
small machines that have an MMC slot but no other block device.
  
 
 From what I've heard, JFFS2 is close to unusuable on the sizes of modern
 SD/MMC cards. So I'd like to see some more use cases before I'm ready
 to let this in.  

There are multiple efforts in progress to get a jffs2 replacement. NAND
flash in embedded devices has the same size as it has on MMC card
potentially, so we will need one soon. David Woodhouse has pushed the
limit that jffs2 can reasonably used to 512MB, which is the size used
in the OLPC XO laptop. If there are ways to get beyond that (which I
find unlikely), there will be a hard limit 2GB or 4GB because of
limitations in the fs layout.

One promising effort for a replacement is Jörn's logfs
(http://wiki.laptop.org/go/Logfs), which should scale well to many
gigabytes. A driver based on MMC would be a nice development tool
for that, since it enables regular PCs as a debugging machine
instead of having to load test kernels onto an actual embedded
machine.

Another thing I have been thinking about was an MTD version of
fat16/fat32. There are a number of optimizations that you can
do for flash media, including:

- limiting the number of writes to the FAT
- erasing blocks when they are freed in the FS
- always writing full erase blocks if the erase block
  size matches the cluster size
- optimize for wear leveling instead of avoiding
  fragmentation

I read that the SD cards have some restrictions of how
the fat fs needs to be laid out on them, presumably to
make sure clusters are aligned with erase blocks.
Do you have any specific information on what SD actually
requires?

  I still want to be sure that I'm on the right track with this driver
  and did not make a conceptual mistake.
  
 
 I can comment it from a MMC perspective, but the MTD stuff I will have to 
 assume is correct.

ok, that's fine. I've talked to a few MTD people about it already
and I understand much more about MTD than I do about MMC ;-)

  @@ -616,6 +616,8 @@ static void mmc_decode_csd(struct mmc_ca
  csd-r2w_factor = UNSTUFF_BITS(resp, 26, 3);
  csd-write_blkbits = UNSTUFF_BITS(resp, 22, 4);
  csd-write_partial = UNSTUFF_BITS(resp, 21, 1);
  +   csd-erase_blksize = (UNSTUFF_BITS(resp, 37, 5) + 1) *
  +   (UNSTUFF_BITS(resp, 42, 5) + 1);
  } else {
  /*
   * We only understand CSD structure v1.1 and v1.2.
 
 NAK. SD uses another format for erase blocks. See the simplified physical 
 spec.

ok, I'll have a look. I keep having trouble identifying the right
specifications (physical spec sounded like it was only about wiring
and electric properties, so I did not look at that). Maybe it would
be good if you could put pointers to the relevant documents into
your Wiki?

  +/*
  + * transfer a block to/from the card. The block needs to be aligned
  + * to mtd-writesize. If we want to implement an mtd_writev method,
  + * this needs to use stream operations with an appropriate stop
  + * command as well.
  + */
  +static int mmc_mtd_transfer_low(struct mmc_card *card, loff_t off, size_t 
  len,
  +   size_t *retlen, u_char *buf, int write)
  +{
  +   struct scatterlist sg;
  +   struct mmc_data data = {
  +   .blksz = 1  card-csd.read_blkbits,
  +   .blocks = len  card-csd.read_blkbits,
 
 First of all, you cannot assume that read_blkbits is a valid block
 size when doing writes. 

Right, I see. I introduced that bug when I merged parts of the read and
write paths.

Is it fair to assume that write_blkbits is always bigger than
read_blkbits, so that one can be used in both cases?

 Secondly, the cards default in a block size of 512 bytes, so you need
 to tell the card your desired block size during probe. 

Ok.

  +   .flags = write ? MMC_DATA_WRITE : MMC_DATA_READ,
  +   .sg = sg,
  +   .sg_len = 1,
  +   };
  +   struct mmc_command cmd = {
  +   .arg = off,
  +   .data = data,
  +   .flags = MMC_RSP_R1 | MMC_CMD_ADTC,
  +   .opcode = write ? MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK,
 
 You set .blocks above, so I have to assume it can be more than 1.
 So you need to change the opcodes accordingly. 

  +   };
  +   struct mmc_request mrq = {
  +   .cmd = cmd,
  +   .data = data,
  +   };
 
 And it also means you need a stop command.

I tried to do multiple block access at first, but then took it out again.
If it turns out valuable to have these, I'll implement it properly later.
Does it make a difference performance-wise to do larger accesses?

  +
  + 

Re: [RFC] MTD driver for MMC cards

2007-01-01 Thread David Woodhouse
On Mon, 2007-01-01 at 23:22 +0100, Arnd Bergmann wrote:
 There are multiple efforts in progress to get a jffs2 replacement. NAND
 flash in embedded devices has the same size as it has on MMC card
 potentially, so we will need one soon. David Woodhouse has pushed the
 limit that jffs2 can reasonably used to 512MB, which is the size used
 in the OLPC XO laptop. If there are ways to get beyond that (which I
 find unlikely), there will be a hard limit 2GB or 4GB because of
 limitations in the fs layout.

The main weakness of JFFS2 (at this kind of size) is that there _is_ no
fs layout -- so there isn't a hard 2GiB or 4GiB limit in the format,
because we never encode offsets anywhere but in memory.

We'll push JFFS2 further than the current 512MiB by enlarging the data
nodes -- so each node covers something like 16KiB of data instead of
only 4KiB, and then there'll be about 1/3 as many of them, which will
cut the memory usage and reduce the amount we need to read in the
summary blocks. But logfs is the way forward, I agree.

-- 
dwmw2

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC] MTD driver for MMC cards

2006-12-31 Thread Matthieu CASTET
On Sun, 31 Dec 2006 13:32:18 +0100, Pierre Ossman wrote:

> Arnd Bergmann wrote:
 
 
> I'm a complete MTD noob, but what uses does the MTD layer have besides
> JFFS2. If it's none, than this advantage isn't that big of a deal.
> 
AFAIK MTD is for device where erase is need to managed in "software" :
http://www.linux-mtd.infradead.org/faq/general.html


For SD card, doesn't a microcontroller on the card hide this, and make the
sd card acts like a normal block device (no need to erase a block before
writing it)?

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC] MTD driver for MMC cards

2006-12-31 Thread Pierre Ossman
Arnd Bergmann wrote:
> This is an experiment on how an SD/MMC card could be used in the MTD layer.
> I don't currently have a system set up to test this, so this driver is
> completely _untested_ and therefore you should consider it _broken_.
> 
> You can get similar functionality by using the mmc_block driver together
> with block2mtd, so you may wonder what the point of another driver is.
> IMHO, there are two separate advantages from using a special driver:
> 
> * better use of low-level interfaces: the MTD driver can detect the
>   erase block size of the card and erase sectors in advance instead of
>   blocking in the write path. The MTD file systems also expect the
>   underlying interface to be synchronous, so there is little point
>   in using extra kernel threads to operate on the card in the background.
> 

I'm a complete MTD noob, but what uses does the MTD layer have besides JFFS2. 
If it's none, than this advantage isn't that big of a deal.

> * It becomes possible to use MMC cards with jffs2 even with CONFIG_BLOCK
>   disabled, which can save a significant amount of kernel memory on
>   small machines that have an MMC slot but no other block device.
> 

>From what I've heard, JFFS2 is close to unusuable on the sizes of modern 
>SD/MMC cards. So I'd like to see some more use cases before I'm ready to let 
>this in.

> I still want to be sure that I'm on the right track with this driver
> and did not make a conceptual mistake.
> 

I can comment it from a MMC perspective, but the MTD stuff I will have to 
assume is correct.

> @@ -616,6 +616,8 @@ static void mmc_decode_csd(struct mmc_ca
>   csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
>   csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
>   csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
> + csd->erase_blksize = (UNSTUFF_BITS(resp, 37, 5) + 1) *
> + (UNSTUFF_BITS(resp, 42, 5) + 1);
>   } else {
>   /*
>* We only understand CSD structure v1.1 and v1.2.

NAK. SD uses another format for erase blocks. See the simplified physical spec.

> +/*
> + * transfer a block to/from the card. The block needs to be aligned
> + * to mtd->writesize. If we want to implement an mtd_writev method,
> + * this needs to use stream operations with an appropriate stop
> + * command as well.
> + */
> +static int mmc_mtd_transfer_low(struct mmc_card *card, loff_t off, size_t 
> len,
> + size_t *retlen, u_char *buf, int write)
> +{
> + struct scatterlist sg;
> + struct mmc_data data = {
> + .blksz = 1 << card->csd.read_blkbits,
> + .blocks = len >> card->csd.read_blkbits,

First of all, you cannot assume that read_blkbits is a valid block size when 
doing writes.

Secondly, the cards default in a block size of 512 bytes, so you need to tell 
the card your desired block size during probe.

> + .flags = write ? MMC_DATA_WRITE : MMC_DATA_READ,
> + .sg = ,
> + .sg_len = 1,
> + };
> + struct mmc_command cmd = {
> + .arg = off,
> + .data = ,
> + .flags = MMC_RSP_R1 | MMC_CMD_ADTC,
> + .opcode = write ? MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK,

You set .blocks above, so I have to assume it can be more than 1. So you need 
to change the opcodes accordingly.

> + };
> + struct mmc_request mrq = {
> + .cmd = ,
> + .data = ,
> + };

And it also means you need a stop command.

> +
> + /* copied from the block driver, don't understand why this is needed */

Now this gives me a bad feeling. Have you read any spec about the MMC protocol 
or are you just winging it?

It is needed because the card goes into programming state after a write, where 
it is very unresponsive to other commands.

> +
> + ret = mmc_card_claim_host(card);
> + if (ret) {
> + dev_warn(>dev, "%s: mmc_card_claim_host returned %d\n",
> + __FUNCTION__, ret);
> + ret = -EIO;
> + goto error;
> + }

mmc_card_claim_host() is currently very stupid in that it requires you to call 
mmc_card_release_host() on error. I intend to fix that some time in the future.

> +/*
> + * Initialize an mmc card. We create a new MTD device for each
> + * MMC card we find. The operations are rather straightforward,
> + * so we don't even need our own data structure to contain the
> + * mtd_info.
> + */
> +static int mmc_mtd_probe(struct mmc_card *card)
> +{
> + struct mtd_info *mtd;
> + int ret;
> +
> + if (!(card->csd.cmdclass & CCC_ERASE))
> + return -ENODEV;
> +

You should probably check for CCC_BLOCK_READ here.

And your driver needs to check if the card support writes (both by 
mmc_card_readonly() and CCC_BLOCK_WRITE).

Rgds
-- 
 -- Pierre Ossman

  Linux kernel, MMC maintainerhttp://www.kernel.org
  PulseAudio, core developer  

Re: [RFC] MTD driver for MMC cards

2006-12-31 Thread Pierre Ossman
Arnd Bergmann wrote:
 This is an experiment on how an SD/MMC card could be used in the MTD layer.
 I don't currently have a system set up to test this, so this driver is
 completely _untested_ and therefore you should consider it _broken_.
 
 You can get similar functionality by using the mmc_block driver together
 with block2mtd, so you may wonder what the point of another driver is.
 IMHO, there are two separate advantages from using a special driver:
 
 * better use of low-level interfaces: the MTD driver can detect the
   erase block size of the card and erase sectors in advance instead of
   blocking in the write path. The MTD file systems also expect the
   underlying interface to be synchronous, so there is little point
   in using extra kernel threads to operate on the card in the background.
 

I'm a complete MTD noob, but what uses does the MTD layer have besides JFFS2. 
If it's none, than this advantage isn't that big of a deal.

 * It becomes possible to use MMC cards with jffs2 even with CONFIG_BLOCK
   disabled, which can save a significant amount of kernel memory on
   small machines that have an MMC slot but no other block device.
 

From what I've heard, JFFS2 is close to unusuable on the sizes of modern 
SD/MMC cards. So I'd like to see some more use cases before I'm ready to let 
this in.

 I still want to be sure that I'm on the right track with this driver
 and did not make a conceptual mistake.
 

I can comment it from a MMC perspective, but the MTD stuff I will have to 
assume is correct.

 @@ -616,6 +616,8 @@ static void mmc_decode_csd(struct mmc_ca
   csd-r2w_factor = UNSTUFF_BITS(resp, 26, 3);
   csd-write_blkbits = UNSTUFF_BITS(resp, 22, 4);
   csd-write_partial = UNSTUFF_BITS(resp, 21, 1);
 + csd-erase_blksize = (UNSTUFF_BITS(resp, 37, 5) + 1) *
 + (UNSTUFF_BITS(resp, 42, 5) + 1);
   } else {
   /*
* We only understand CSD structure v1.1 and v1.2.

NAK. SD uses another format for erase blocks. See the simplified physical spec.

 +/*
 + * transfer a block to/from the card. The block needs to be aligned
 + * to mtd-writesize. If we want to implement an mtd_writev method,
 + * this needs to use stream operations with an appropriate stop
 + * command as well.
 + */
 +static int mmc_mtd_transfer_low(struct mmc_card *card, loff_t off, size_t 
 len,
 + size_t *retlen, u_char *buf, int write)
 +{
 + struct scatterlist sg;
 + struct mmc_data data = {
 + .blksz = 1  card-csd.read_blkbits,
 + .blocks = len  card-csd.read_blkbits,

First of all, you cannot assume that read_blkbits is a valid block size when 
doing writes.

Secondly, the cards default in a block size of 512 bytes, so you need to tell 
the card your desired block size during probe.

 + .flags = write ? MMC_DATA_WRITE : MMC_DATA_READ,
 + .sg = sg,
 + .sg_len = 1,
 + };
 + struct mmc_command cmd = {
 + .arg = off,
 + .data = data,
 + .flags = MMC_RSP_R1 | MMC_CMD_ADTC,
 + .opcode = write ? MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK,

You set .blocks above, so I have to assume it can be more than 1. So you need 
to change the opcodes accordingly.

 + };
 + struct mmc_request mrq = {
 + .cmd = cmd,
 + .data = data,
 + };

And it also means you need a stop command.

 +
 + /* copied from the block driver, don't understand why this is needed */

Now this gives me a bad feeling. Have you read any spec about the MMC protocol 
or are you just winging it?

It is needed because the card goes into programming state after a write, where 
it is very unresponsive to other commands.

 +
 + ret = mmc_card_claim_host(card);
 + if (ret) {
 + dev_warn(card-dev, %s: mmc_card_claim_host returned %d\n,
 + __FUNCTION__, ret);
 + ret = -EIO;
 + goto error;
 + }

mmc_card_claim_host() is currently very stupid in that it requires you to call 
mmc_card_release_host() on error. I intend to fix that some time in the future.

 +/*
 + * Initialize an mmc card. We create a new MTD device for each
 + * MMC card we find. The operations are rather straightforward,
 + * so we don't even need our own data structure to contain the
 + * mtd_info.
 + */
 +static int mmc_mtd_probe(struct mmc_card *card)
 +{
 + struct mtd_info *mtd;
 + int ret;
 +
 + if (!(card-csd.cmdclass  CCC_ERASE))
 + return -ENODEV;
 +

You should probably check for CCC_BLOCK_READ here.

And your driver needs to check if the card support writes (both by 
mmc_card_readonly() and CCC_BLOCK_WRITE).

Rgds
-- 
 -- Pierre Ossman

  Linux kernel, MMC maintainerhttp://www.kernel.org
  PulseAudio, core developer  http://pulseaudio.org
  rdesktop, core developer  http://www.rdesktop.org
-
To 

Re: [RFC] MTD driver for MMC cards

2006-12-31 Thread Matthieu CASTET
On Sun, 31 Dec 2006 13:32:18 +0100, Pierre Ossman wrote:

 Arnd Bergmann wrote:
 
 
 I'm a complete MTD noob, but what uses does the MTD layer have besides
 JFFS2. If it's none, than this advantage isn't that big of a deal.
 
AFAIK MTD is for device where erase is need to managed in software :
http://www.linux-mtd.infradead.org/faq/general.html


For SD card, doesn't a microcontroller on the card hide this, and make the
sd card acts like a normal block device (no need to erase a block before
writing it)?

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC] MTD driver for MMC cards

2006-12-28 Thread Arnd Bergmann
This is an experiment on how an SD/MMC card could be used in the MTD layer.
I don't currently have a system set up to test this, so this driver is
completely _untested_ and therefore you should consider it _broken_.

You can get similar functionality by using the mmc_block driver together
with block2mtd, so you may wonder what the point of another driver is.
IMHO, there are two separate advantages from using a special driver:

* better use of low-level interfaces: the MTD driver can detect the
  erase block size of the card and erase sectors in advance instead of
  blocking in the write path. The MTD file systems also expect the
  underlying interface to be synchronous, so there is little point
  in using extra kernel threads to operate on the card in the background.

* It becomes possible to use MMC cards with jffs2 even with CONFIG_BLOCK
  disabled, which can save a significant amount of kernel memory on
  small machines that have an MMC slot but no other block device.

I still want to be sure that I'm on the right track with this driver
and did not make a conceptual mistake.

Signed-off-by: Arnd Bergmann <[EMAIL PROTECTED]>

---

Index: linux-cg/drivers/mmc/mmc.c
===
--- linux-cg.orig/drivers/mmc/mmc.c
+++ linux-cg/drivers/mmc/mmc.c
@@ -616,6 +616,8 @@ static void mmc_decode_csd(struct mmc_ca
csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
+   csd->erase_blksize = (UNSTUFF_BITS(resp, 37, 5) + 1) *
+   (UNSTUFF_BITS(resp, 42, 5) + 1);
} else {
/*
 * We only understand CSD structure v1.1 and v1.2.
@@ -651,6 +653,8 @@ static void mmc_decode_csd(struct mmc_ca
csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
+   csd->erase_blksize = (UNSTUFF_BITS(resp, 37, 5) + 1) *
+   (UNSTUFF_BITS(resp, 42, 5) + 1);
}
 }
 
Index: linux-cg/include/linux/mmc/card.h
===
--- linux-cg.orig/include/linux/mmc/card.h
+++ linux-cg/include/linux/mmc/card.h
@@ -32,6 +32,7 @@ struct mmc_csd {
unsigned intmax_dtr;
unsigned intread_blkbits;
unsigned intwrite_blkbits;
+   unsigned interase_blksize;
unsigned intcapacity;
unsigned intread_partial:1,
read_misalign:1,
Index: linux-cg/drivers/mmc/mmc_mtd.c
===
--- /dev/null
+++ linux-cg/drivers/mmc/mmc_mtd.c
@@ -0,0 +1,274 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * erase a range of erase groups aligned to mtd->erase_size
+ */
+static int mmc_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+   struct mmc_card *card = mtd->priv;
+   struct mmc_command cmd[3] = { {
+   .opcode = MMC_ERASE_GROUP_START,
+   .arg = instr->addr,
+   .flags = MMC_RSP_R1 | MMC_CMD_AC,
+   }, {
+   .opcode = MMC_ERASE_GROUP_END,
+   .arg = instr->addr + instr->len,
+   .flags = MMC_RSP_R1 | MMC_CMD_AC,
+   }, {
+   .opcode = MMC_ERASE,
+   .flags = MMC_RSP_R1B | MMC_CMD_AC,
+   },
+   };
+   int err, i;
+
+   dev_dbg(card->dev, "%s: from %ld len %ld\n", __FUNCTION__, from, len);
+
+   instr->state = MTD_ERASING;
+   err = mmc_card_claim_host(card);
+   if (err)
+   goto error;
+
+   for (i=0; i<3; i++) {
+   err = mmc_wait_for_cmd(card->host, cmd, 5);
+   if (err) {
+   dev_err(>dev, "%s: error %d in stage %d\n",
+   __FUNCTION__, err, i);
+   break;
+   }
+   }
+   mmc_card_release_host(card);
+   mtd_erase_callback(instr);
+error:
+   instr->state = err ? MTD_ERASE_FAILED : MTD_ERASE_DONE;
+   return err;
+}
+
+/*
+ * check if a write command was completed correctly
+ */
+static int mmc_mtd_get_status(struct mmc_card *card)
+{
+   int err;
+   struct mmc_command cmd;
+
+   err = mmc_card_claim_host(card);
+   if (err)
+   goto error;
+
+   do {
+   cmd = (struct mmc_command) {
+   .opcode = MMC_SEND_STATUS,
+   .arg = card->rca << 16,
+   .flags = MMC_RSP_R1 | MMC_CMD_AC,
+   };
+
+   err = mmc_wait_for_cmd(card->host, , 5);
+ 

[RFC] MTD driver for MMC cards

2006-12-28 Thread Arnd Bergmann
This is an experiment on how an SD/MMC card could be used in the MTD layer.
I don't currently have a system set up to test this, so this driver is
completely _untested_ and therefore you should consider it _broken_.

You can get similar functionality by using the mmc_block driver together
with block2mtd, so you may wonder what the point of another driver is.
IMHO, there are two separate advantages from using a special driver:

* better use of low-level interfaces: the MTD driver can detect the
  erase block size of the card and erase sectors in advance instead of
  blocking in the write path. The MTD file systems also expect the
  underlying interface to be synchronous, so there is little point
  in using extra kernel threads to operate on the card in the background.

* It becomes possible to use MMC cards with jffs2 even with CONFIG_BLOCK
  disabled, which can save a significant amount of kernel memory on
  small machines that have an MMC slot but no other block device.

I still want to be sure that I'm on the right track with this driver
and did not make a conceptual mistake.

Signed-off-by: Arnd Bergmann [EMAIL PROTECTED]

---

Index: linux-cg/drivers/mmc/mmc.c
===
--- linux-cg.orig/drivers/mmc/mmc.c
+++ linux-cg/drivers/mmc/mmc.c
@@ -616,6 +616,8 @@ static void mmc_decode_csd(struct mmc_ca
csd-r2w_factor = UNSTUFF_BITS(resp, 26, 3);
csd-write_blkbits = UNSTUFF_BITS(resp, 22, 4);
csd-write_partial = UNSTUFF_BITS(resp, 21, 1);
+   csd-erase_blksize = (UNSTUFF_BITS(resp, 37, 5) + 1) *
+   (UNSTUFF_BITS(resp, 42, 5) + 1);
} else {
/*
 * We only understand CSD structure v1.1 and v1.2.
@@ -651,6 +653,8 @@ static void mmc_decode_csd(struct mmc_ca
csd-r2w_factor = UNSTUFF_BITS(resp, 26, 3);
csd-write_blkbits = UNSTUFF_BITS(resp, 22, 4);
csd-write_partial = UNSTUFF_BITS(resp, 21, 1);
+   csd-erase_blksize = (UNSTUFF_BITS(resp, 37, 5) + 1) *
+   (UNSTUFF_BITS(resp, 42, 5) + 1);
}
 }
 
Index: linux-cg/include/linux/mmc/card.h
===
--- linux-cg.orig/include/linux/mmc/card.h
+++ linux-cg/include/linux/mmc/card.h
@@ -32,6 +32,7 @@ struct mmc_csd {
unsigned intmax_dtr;
unsigned intread_blkbits;
unsigned intwrite_blkbits;
+   unsigned interase_blksize;
unsigned intcapacity;
unsigned intread_partial:1,
read_misalign:1,
Index: linux-cg/drivers/mmc/mmc_mtd.c
===
--- /dev/null
+++ linux-cg/drivers/mmc/mmc_mtd.c
@@ -0,0 +1,274 @@
+#include linux/init.h
+#include linux/module.h
+#include linux/mmc/card.h
+#include linux/mmc/protocol.h
+#include linux/mtd/mtd.h
+#include linux/scatterlist.h
+
+/*
+ * erase a range of erase groups aligned to mtd-erase_size
+ */
+static int mmc_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+   struct mmc_card *card = mtd-priv;
+   struct mmc_command cmd[3] = { {
+   .opcode = MMC_ERASE_GROUP_START,
+   .arg = instr-addr,
+   .flags = MMC_RSP_R1 | MMC_CMD_AC,
+   }, {
+   .opcode = MMC_ERASE_GROUP_END,
+   .arg = instr-addr + instr-len,
+   .flags = MMC_RSP_R1 | MMC_CMD_AC,
+   }, {
+   .opcode = MMC_ERASE,
+   .flags = MMC_RSP_R1B | MMC_CMD_AC,
+   },
+   };
+   int err, i;
+
+   dev_dbg(card-dev, %s: from %ld len %ld\n, __FUNCTION__, from, len);
+
+   instr-state = MTD_ERASING;
+   err = mmc_card_claim_host(card);
+   if (err)
+   goto error;
+
+   for (i=0; i3; i++) {
+   err = mmc_wait_for_cmd(card-host, cmd, 5);
+   if (err) {
+   dev_err(card-dev, %s: error %d in stage %d\n,
+   __FUNCTION__, err, i);
+   break;
+   }
+   }
+   mmc_card_release_host(card);
+   mtd_erase_callback(instr);
+error:
+   instr-state = err ? MTD_ERASE_FAILED : MTD_ERASE_DONE;
+   return err;
+}
+
+/*
+ * check if a write command was completed correctly
+ */
+static int mmc_mtd_get_status(struct mmc_card *card)
+{
+   int err;
+   struct mmc_command cmd;
+
+   err = mmc_card_claim_host(card);
+   if (err)
+   goto error;
+
+   do {
+   cmd = (struct mmc_command) {
+   .opcode = MMC_SEND_STATUS,
+   .arg = card-rca  16,
+   .flags = MMC_RSP_R1 | MMC_CMD_AC,
+