* Supporting flash that powers up locked
@ 2004-11-23 22:25 Todd Poynor
2004-11-24 13:07 ` Josh Boyer
2004-11-24 13:57 ` David Woodhouse
0 siblings, 2 replies; 10+ messages in thread
From: Todd Poynor @ 2004-11-23 22:25 UTC (permalink / raw)
To: linux-mtd
Flash chips that power up with all blocks locked (such as K3
StrataFlash) seem to be showing up on more and more platforms. At the
risk of being a pest, I'd like to push for some agreement on how to
handle this and possibly get the support into linux-mtd.
Below is a patch to the partition driver to use the partition map as the
source of information for whether a partition is to be writeable and to
unlock blocks upon write if the block is found to be locked when this
was not intended. It intercepts an EROFS return from the chip driver on
a write/erase, unlocks blocks, and retries the write/erase, if the
partition is marked writeable. If the partition is not writeable, or if
the partition has been explicitly locked, then the locked blocks are
left alone and the EROFS is returned to the caller.
This avoids the need to detect whether the chip has the property that
blocks intended to be writeable may be locked at boot or system resume
time (and you wouldn't want to do it for all chips due to complications
of some other flash chips), and avoids the overhead of unlocking every
writeable block (if not actually written to). Also note that some
platforms power cycle the flash device during a system suspend,
reverting blocks to all locked state at system resume time, so a resume
time action is needed as well. Also note that the code to read the
current state of lock bits might not be functioning properly for all
chips.
In order to allow a writeable partition to be setup but still explicitly
locked via flash_lock, a partition lock flag is added that is
set/cleared by flash_lock/unlock. Blocks in a partition locked via
flash_lock will not be written to. flash_lock/unlock thus dynamically
enable/disable software locking, a la a runtime settable MTD_WRITEABLE
flag.
If anyone has any suggestions or comments as to why this wouldn't work
for their device or usage model or why this isn't the right way to go
about things then I'd appreciate it, thanks. -- Todd
Index: drivers/mtd/mtdpart.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/mtdpart.c,v
retrieving revision 1.51
diff -u -r1.51 mtdpart.c
--- drivers/mtd/mtdpart.c 16 Nov 2004 18:28:59 -0000 1.51
+++ drivers/mtd/mtdpart.c 23 Nov 2004 01:55:42 -0000
@@ -33,8 +33,11 @@
int index;
struct list_head list;
int registered;
+ int flags;
};
+#define PART_LOCKED 1
+
/*
* Given a pointer to the MTD object in the mtd_part structure, we can retrieve
* the pointer to that structure with this macro.
@@ -124,23 +127,40 @@
len, retlen, buf);
}
+static int part_do_write (struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
+{
+ struct mtd_part *part = PART(mtd);
+
+ if (part->master->write_ecc == NULL)
+ return part->master->write (part->master, to + part->offset,
+ len, retlen, buf);
+ else
+ return part->master->write_ecc (part->master, to + part->offset,
+ len, retlen, buf, NULL,
+ &mtd->oobinfo);
+}
+
static int part_write (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf)
{
struct mtd_part *part = PART(mtd);
- if (!(mtd->flags & MTD_WRITEABLE))
+ int ret;
+ if (! (mtd->flags & MTD_WRITEABLE) || part->flags & PART_LOCKED)
return -EROFS;
if (to >= mtd->size)
len = 0;
else if (to + len > mtd->size)
len = mtd->size - to;
- if (part->master->write_ecc == NULL)
- return part->master->write (part->master, to + part->offset,
- len, retlen, buf);
- else
- return part->master->write_ecc (part->master, to + part->offset,
- len, retlen, buf, NULL, &mtd->oobinfo);
-
+
+ if (((ret = part_do_write (mtd, to, len, retlen, buf)) == -EROFS) &&
+ part->master->unlock) {
+ loff_t baddr = (to + part->offset) & ~(mtd->erasesize - 1);
+ if (! part->master->unlock (part->master, baddr,
+ mtd->erasesize))
+ ret = part_do_write (mtd, to, len, retlen, buf);
+ }
+ return ret;
}
static int part_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
@@ -148,7 +168,8 @@
u_char *eccbuf, struct nand_oobinfo *oobsel)
{
struct mtd_part *part = PART(mtd);
- if (!(mtd->flags & MTD_WRITEABLE))
+ int ret;
+ if (! (mtd->flags & MTD_WRITEABLE) || part->flags & PART_LOCKED)
return -EROFS;
if (oobsel == NULL)
oobsel = &mtd->oobinfo;
@@ -156,22 +177,44 @@
len = 0;
else if (to + len > mtd->size)
len = mtd->size - to;
- return part->master->write_ecc (part->master, to + part->offset,
- len, retlen, buf, eccbuf, oobsel);
+ if (((ret = part->master->write_ecc (part->master, to + part->offset,
+ len, retlen, buf, eccbuf,
+ oobsel)) == -EROFS) &&
+ part->master->unlock) {
+ loff_t baddr = (to + part->offset) & ~(mtd->erasesize - 1);
+ if (! part->master->unlock (part->master, baddr,
+ mtd->erasesize))
+ ret = part->master->write_ecc (part->master,
+ to + part->offset,
+ len, retlen, buf,
+ eccbuf, oobsel);
+ }
+ return ret;
}
static int part_write_oob (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf)
{
struct mtd_part *part = PART(mtd);
- if (!(mtd->flags & MTD_WRITEABLE))
+ int ret;
+ if (! (mtd->flags & MTD_WRITEABLE) || part->flags & PART_LOCKED)
return -EROFS;
if (to >= mtd->size)
len = 0;
else if (to + len > mtd->size)
len = mtd->size - to;
- return part->master->write_oob (part->master, to + part->offset,
- len, retlen, buf);
+ if (((ret = part->master->write_oob (part->master, to + part->offset,
+ len, retlen, buf)) == -EROFS) &&
+ part->master->unlock) {
+ loff_t baddr = (to + part->offset) & ~(mtd->erasesize - 1);
+ if (! part->master->unlock (part->master, baddr,
+ mtd->erasesize))
+ ret = part->master->write_oob (part->master,
+ to + part->offset, len,
+ retlen, buf);
+ }
+
+ return ret;
}
static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
@@ -182,12 +225,10 @@
len, retlen, buf);
}
-static int part_writev (struct mtd_info *mtd, const struct kvec *vecs,
- unsigned long count, loff_t to, size_t *retlen)
+static int part_do_writev (struct mtd_info *mtd, const struct kvec *vecs,
+ unsigned long count, loff_t to, size_t *retlen)
{
struct mtd_part *part = PART(mtd);
- if (!(mtd->flags & MTD_WRITEABLE))
- return -EROFS;
if (part->master->writev_ecc == NULL)
return part->master->writev (part->master, vecs, count,
to + part->offset, retlen);
@@ -197,6 +238,24 @@
NULL, &mtd->oobinfo);
}
+static int part_writev (struct mtd_info *mtd, const struct kvec *vecs,
+ unsigned long count, loff_t to, size_t *retlen)
+{
+ struct mtd_part *part = PART(mtd);
+ int ret;
+ if (! (mtd->flags & MTD_WRITEABLE) || part->flags & PART_LOCKED)
+ return -EROFS;
+
+ if (((ret = part_do_writev (mtd, vecs, count, to, retlen)) == -EROFS)
+ && part->master->unlock) {
+ loff_t baddr = (to + part->offset) & ~(mtd->erasesize - 1);
+ if (! part->master->unlock (part->master, baddr,
+ mtd->erasesize))
+ ret = part_do_writev (mtd, vecs, count, to, retlen);
+ }
+ return ret;
+}
+
static int part_readv (struct mtd_info *mtd, struct kvec *vecs,
unsigned long count, loff_t from, size_t *retlen)
{
@@ -215,13 +274,25 @@
u_char *eccbuf, struct nand_oobinfo *oobsel)
{
struct mtd_part *part = PART(mtd);
- if (!(mtd->flags & MTD_WRITEABLE))
+ int ret;
+ if (! (mtd->flags & MTD_WRITEABLE) || part->flags & PART_LOCKED)
return -EROFS;
if (oobsel == NULL)
oobsel = &mtd->oobinfo;
- return part->master->writev_ecc (part->master, vecs, count,
- to + part->offset, retlen,
- eccbuf, oobsel);
+ if (((ret = part->master->writev_ecc (part->master, vecs, count,
+ to + part->offset, retlen,
+ eccbuf, oobsel)) == -EROFS) &&
+ part->master->unlock) {
+ loff_t baddr = (to + part->offset) & ~(mtd->erasesize - 1);
+ if (! part->master->unlock (part->master, baddr,
+ mtd->erasesize))
+ ret = part->master->writev_ecc (part->master, vecs,
+ count,
+ to + part->offset,
+ retlen, eccbuf, oobsel);
+ }
+ return ret;
+
}
static int part_readv_ecc (struct mtd_info *mtd, struct kvec *vecs,
@@ -240,12 +311,17 @@
{
struct mtd_part *part = PART(mtd);
int ret;
- if (!(mtd->flags & MTD_WRITEABLE))
+ if (! (mtd->flags & MTD_WRITEABLE) || part->flags & PART_LOCKED)
return -EROFS;
if (instr->addr >= mtd->size)
return -EINVAL;
instr->addr += part->offset;
- ret = part->master->erase(part->master, instr);
+ if ((ret = part->master->erase(part->master, instr) == -EROFS) &&
+ part->master->unlock &&
+ (! part->master->unlock (part->master, instr->addr,
+ mtd->erasesize)))
+ ret = part->master->erase(part->master, instr);
+
return ret;
}
@@ -268,6 +344,7 @@
struct mtd_part *part = PART(mtd);
if ((len + ofs) > mtd->size)
return -EINVAL;
+ part->flags |= PART_LOCKED;
return part->master->lock(part->master, ofs + part->offset, len);
}
@@ -276,6 +353,7 @@
struct mtd_part *part = PART(mtd);
if ((len + ofs) > mtd->size)
return -EINVAL;
+ part->flags &= ~PART_LOCKED;
return part->master->unlock(part->master, ofs + part->offset, len);
}
@@ -309,7 +387,7 @@
static int part_block_markbad (struct mtd_info *mtd, loff_t ofs)
{
struct mtd_part *part = PART(mtd);
- if (!(mtd->flags & MTD_WRITEABLE))
+ if (! (mtd->flags & MTD_WRITEABLE) || part->flags & PART_LOCKED)
return -EROFS;
if (ofs >= mtd->size)
return -EINVAL;
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Supporting flash that powers up locked
2004-11-23 22:25 Supporting flash that powers up locked Todd Poynor
@ 2004-11-24 13:07 ` Josh Boyer
2004-11-25 0:37 ` Todd Poynor
2004-11-24 13:57 ` David Woodhouse
1 sibling, 1 reply; 10+ messages in thread
From: Josh Boyer @ 2004-11-24 13:07 UTC (permalink / raw)
To: Todd Poynor; +Cc: linux-mtd
On Tue, 2004-11-23 at 16:25, Todd Poynor wrote:
<snip>
>
> If anyone has any suggestions or comments as to why this wouldn't work
> for their device or usage model or why this isn't the right way to go
> about things then I'd appreciate it, thanks. -- Todd
Not everyone uses mtd partitions...
josh
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Supporting flash that powers up locked
2004-11-23 22:25 Supporting flash that powers up locked Todd Poynor
2004-11-24 13:07 ` Josh Boyer
@ 2004-11-24 13:57 ` David Woodhouse
2004-11-25 1:15 ` Todd Poynor
1 sibling, 1 reply; 10+ messages in thread
From: David Woodhouse @ 2004-11-24 13:57 UTC (permalink / raw)
To: Todd Poynor; +Cc: linux-mtd
On Tue, 2004-11-23 at 14:25 -0800, Todd Poynor wrote:
> Flash chips that power up with all blocks locked (such as K3
> StrataFlash) seem to be showing up on more and more platforms. At the
> risk of being a pest, I'd like to push for some agreement on how to
> handle this and possibly get the support into linux-mtd.
>
> Below is a patch to the partition driver to use the partition map as the
> source of information for whether a partition is to be writeable and to
> unlock blocks upon write if the block is found to be locked when this
> was not intended. It intercepts an EROFS return from the chip driver on
> a write/erase, unlocks blocks, and retries the write/erase, if the
> partition is marked writeable. If the partition is not writeable, or if
> the partition has been explicitly locked, then the locked blocks are
> left alone and the EROFS is returned to the caller.
We already have a bit to set in the partition flags to show that a
partition should be read-only.
I'd rather do this with a blacklist of the chips which lock themselves,
and have the chip driver automatically unlock it at boot time and
suspend time (or automatically as required).
--
dwmw2
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Supporting flash that powers up locked
2004-11-24 13:07 ` Josh Boyer
@ 2004-11-25 0:37 ` Todd Poynor
0 siblings, 0 replies; 10+ messages in thread
From: Todd Poynor @ 2004-11-25 0:37 UTC (permalink / raw)
To: Josh Boyer; +Cc: linux-mtd
Josh Boyer wrote:
> On Tue, 2004-11-23 at 16:25, Todd Poynor wrote:
>
> <snip>
>
>>If anyone has any suggestions or comments as to why this wouldn't work
>>for their device or usage model or why this isn't the right way to go
>>about things then I'd appreciate it, thanks. -- Todd
>
>
> Not everyone uses mtd partitions...
Unfortunately options for doing anything terribly intelligent about it
seem to be few in such a case. If somebody wants MTD to automatically
figure out what the proper locking status is for these chips then the
partition map is the only thing we've got to go on (at present anyhow).
So it could be argued that by not using partitions you've decided to
handle it yourself (such as explicit flash_unlock of needed ranges after
userspace startup). I'm guessing that some new way of specifying what
areas of flash are intended to be writeable vs. read-only, apart from
the existing partition maps, would not be well received. But if there
is some nifty way of doing this outside the partition framework then I'm
interested. And doing nothing or doing something simplistic are
certainly options as well. Thanks,
--
Todd
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Supporting flash that powers up locked
2004-11-24 13:57 ` David Woodhouse
@ 2004-11-25 1:15 ` Todd Poynor
2004-11-25 9:36 ` David Woodhouse
0 siblings, 1 reply; 10+ messages in thread
From: Todd Poynor @ 2004-11-25 1:15 UTC (permalink / raw)
To: David Woodhouse; +Cc: linux-mtd
David Woodhouse wrote:
> We already have a bit to set in the partition flags to show that a
> partition should be read-only.
Yeah I saw that the bit is really an amalgam of
MTD_CLEAR_BITS|MTD_SET_BITS that are also involved in other capability
combos (MTD_CAP_NANDFLASH, et al) and wasn't sure if there were other
side effects of messing with those at runtime.
> I'd rather do this with a blacklist of the chips which lock themselves,
> and have the chip driver automatically unlock it at boot time and
> suspend time (or automatically as required).
I did receive some pushback when I previously tried to do something
similar, since we'd often be unlocking bootloader firmware and such.
It may be better to err on the side of caution and make it the
responsibility of userspace to unlock the needed portions. Assuming the
root fs is read-only then boot time probably isn't a problem. System
resume time could be a problem, since we can't guarantee nothing will
write to previously-writeable filesystems before the "restore flash
state" script runs. So if the dangers of unlocking bootloaders etc.
aren't felt to be that important then unlocking all blocks is the easier
solution.
Another option suggested previously was to require userspace to unlock
needed blocks, but keep a bitmap of unlocked blocks and restore the
flash to the same state at mtd resume, so writeable file systems
continue to be writeable at resume time (and no userspace callback is
needed at resume time).
If, all in all, unlocking the whole chip is still the best way to go
then I'll send a proposed patch for Intel K3 StrataFlash. Thanks,
--
Todd
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Supporting flash that powers up locked
2004-11-25 1:15 ` Todd Poynor
@ 2004-11-25 9:36 ` David Woodhouse
2004-12-01 3:50 ` Todd Poynor
0 siblings, 1 reply; 10+ messages in thread
From: David Woodhouse @ 2004-11-25 9:36 UTC (permalink / raw)
To: Todd Poynor; +Cc: linux-mtd
On Wed, 2004-11-24 at 17:15 -0800, Todd Poynor wrote:
> David Woodhouse wrote:
> > We already have a bit to set in the partition flags to show that a
> > partition should be read-only.
>
> Yeah I saw that the bit is really an amalgam of
> MTD_CLEAR_BITS|MTD_SET_BITS that are also involved in other capability
> combos (MTD_CAP_NANDFLASH, et al) and wasn't sure if there were other
> side effects of messing with those at runtime.
No, we have it separately for partitions.
> > I'd rather do this with a blacklist of the chips which lock themselves,
> > and have the chip driver automatically unlock it at boot time and
> > suspend time (or automatically as required).
>
> I did receive some pushback when I previously tried to do something
> similar, since we'd often be unlocking bootloader firmware and such.
Look at the use of MTD_WRITEABLE in, e.g., solutionengine.c. We already
have a way to prevent accidental access to the bootloader.
When they made the locking automatic instead of remembering the previous
state, the whole point of it changed. It's no longer useful for
protecting bootloaders all by itself; you can't infer anything useful
from the fact that you found the flash locked.
On the new chips of which you speak, all the locking can do is give us a
little more protection against random read/write cycles causing damage
to the contents of the flash. So let's use it for that. Leave the flash
locked at most times, and unlock a sector as we need to use it.
--
dwmw2
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Supporting flash that powers up locked
2004-11-25 9:36 ` David Woodhouse
@ 2004-12-01 3:50 ` Todd Poynor
0 siblings, 0 replies; 10+ messages in thread
From: Todd Poynor @ 2004-12-01 3:50 UTC (permalink / raw)
To: David Woodhouse; +Cc: linux-mtd
On Thu, Nov 25, 2004 at 09:36:21AM +0000, David Woodhouse wrote:
> On the new chips of which you speak, all the locking can do is give us a
> little more protection against random read/write cycles causing damage
> to the contents of the flash. So let's use it for that. Leave the flash
> locked at most times, and unlock a sector as we need to use it.
To that end here's a new version of the patch that unlocks blocks as
written to, if a write to a writeable partition incurs EROFS. If we
really wanted to go with that spirit, could relock afterwards. This
patch drops the previous explicit partition lock flag.
Another possibility would be to add a quirk for these flashes that
rectifies the unlock status with the partition map (unlock all blocks
intended to be writeable) at init time and mtd resume time. Or to add a
quirk that unlocks and relocks around writes, possibly in the chip
driver if we don't want to rely on the partition map for whether it's OK
to do so.
Suggestions? Thanks -- Todd
Index: drivers/mtd/mtdpart.c
===================================================================
RCS file: /cvsdev/mvl-kernel/linux/drivers/mtd/mtdpart.c,v
retrieving revision 1.2.14.2.10.2
diff -u -r1.2.14.2.10.2 mtdpart.c
--- drivers/mtd/mtdpart.c 26 Aug 2004 22:07:09 -0000 1.2.14.2.10.2
+++ drivers/mtd/mtdpart.c 1 Dec 2004 02:45:39 -0000
@@ -124,23 +124,40 @@
len, retlen, buf);
}
+static int part_do_write (struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
+{
+ struct mtd_part *part = PART(mtd);
+
+ if (part->master->write_ecc == NULL)
+ return part->master->write (part->master, to + part->offset,
+ len, retlen, buf);
+ else
+ return part->master->write_ecc (part->master, to + part->offset,
+ len, retlen, buf, NULL,
+ &mtd->oobinfo);
+}
+
static int part_write (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf)
{
struct mtd_part *part = PART(mtd);
+ int ret;
if (!(mtd->flags & MTD_WRITEABLE))
return -EROFS;
if (to >= mtd->size)
len = 0;
else if (to + len > mtd->size)
len = mtd->size - to;
- if (part->master->write_ecc == NULL)
- return part->master->write (part->master, to + part->offset,
- len, retlen, buf);
- else
- return part->master->write_ecc (part->master, to + part->offset,
- len, retlen, buf, NULL, &mtd->oobinfo);
-
+
+ if (((ret = part_do_write (mtd, to, len, retlen, buf)) == -EROFS) &&
+ part->master->unlock) {
+ loff_t baddr = (to + part->offset) & ~(mtd->erasesize - 1);
+ if (! part->master->unlock (part->master, baddr,
+ mtd->erasesize))
+ ret = part_do_write (mtd, to, len, retlen, buf);
+ }
+ return ret;
}
static int part_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
@@ -148,6 +165,7 @@
u_char *eccbuf, struct nand_oobinfo *oobsel)
{
struct mtd_part *part = PART(mtd);
+ int ret;
if (!(mtd->flags & MTD_WRITEABLE))
return -EROFS;
if (oobsel == NULL)
@@ -156,22 +174,44 @@
len = 0;
else if (to + len > mtd->size)
len = mtd->size - to;
- return part->master->write_ecc (part->master, to + part->offset,
- len, retlen, buf, eccbuf, oobsel);
+ if (((ret = part->master->write_ecc (part->master, to + part->offset,
+ len, retlen, buf, eccbuf,
+ oobsel)) == -EROFS) &&
+ part->master->unlock) {
+ loff_t baddr = (to + part->offset) & ~(mtd->erasesize - 1);
+ if (! part->master->unlock (part->master, baddr,
+ mtd->erasesize))
+ ret = part->master->write_ecc (part->master,
+ to + part->offset,
+ len, retlen, buf,
+ eccbuf, oobsel);
+ }
+ return ret;
}
static int part_write_oob (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf)
{
struct mtd_part *part = PART(mtd);
+ int ret;
if (!(mtd->flags & MTD_WRITEABLE))
return -EROFS;
if (to >= mtd->size)
len = 0;
else if (to + len > mtd->size)
len = mtd->size - to;
- return part->master->write_oob (part->master, to + part->offset,
- len, retlen, buf);
+ if (((ret = part->master->write_oob (part->master, to + part->offset,
+ len, retlen, buf)) == -EROFS) &&
+ part->master->unlock) {
+ loff_t baddr = (to + part->offset) & ~(mtd->erasesize - 1);
+ if (! part->master->unlock (part->master, baddr,
+ mtd->erasesize))
+ ret = part->master->write_oob (part->master,
+ to + part->offset, len,
+ retlen, buf);
+ }
+
+ return ret;
}
static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
@@ -182,12 +222,10 @@
len, retlen, buf);
}
-static int part_writev (struct mtd_info *mtd, const struct kvec *vecs,
- unsigned long count, loff_t to, size_t *retlen)
+static int part_do_writev (struct mtd_info *mtd, const struct kvec *vecs,
+ unsigned long count, loff_t to, size_t *retlen)
{
struct mtd_part *part = PART(mtd);
- if (!(mtd->flags & MTD_WRITEABLE))
- return -EROFS;
if (part->master->writev_ecc == NULL)
return part->master->writev (part->master, vecs, count,
to + part->offset, retlen);
@@ -197,6 +235,24 @@
NULL, &mtd->oobinfo);
}
+static int part_writev (struct mtd_info *mtd, const struct kvec *vecs,
+ unsigned long count, loff_t to, size_t *retlen)
+{
+ struct mtd_part *part = PART(mtd);
+ int ret;
+ if (!(mtd->flags & MTD_WRITEABLE))
+ return -EROFS;
+
+ if (((ret = part_do_writev (mtd, vecs, count, to, retlen)) == -EROFS)
+ && part->master->unlock) {
+ loff_t baddr = (to + part->offset) & ~(mtd->erasesize - 1);
+ if (! part->master->unlock (part->master, baddr,
+ mtd->erasesize))
+ ret = part_do_writev (mtd, vecs, count, to, retlen);
+ }
+ return ret;
+}
+
static int part_readv (struct mtd_info *mtd, struct kvec *vecs,
unsigned long count, loff_t from, size_t *retlen)
{
@@ -215,13 +271,25 @@
u_char *eccbuf, struct nand_oobinfo *oobsel)
{
struct mtd_part *part = PART(mtd);
+ int ret;
if (!(mtd->flags & MTD_WRITEABLE))
return -EROFS;
if (oobsel == NULL)
oobsel = &mtd->oobinfo;
- return part->master->writev_ecc (part->master, vecs, count,
- to + part->offset, retlen,
- eccbuf, oobsel);
+ if (((ret = part->master->writev_ecc (part->master, vecs, count,
+ to + part->offset, retlen,
+ eccbuf, oobsel)) == -EROFS) &&
+ part->master->unlock) {
+ loff_t baddr = (to + part->offset) & ~(mtd->erasesize - 1);
+ if (! part->master->unlock (part->master, baddr,
+ mtd->erasesize))
+ ret = part->master->writev_ecc (part->master, vecs,
+ count,
+ to + part->offset,
+ retlen, eccbuf, oobsel);
+ }
+ return ret;
+
}
static int part_readv_ecc (struct mtd_info *mtd, struct kvec *vecs,
@@ -245,7 +313,12 @@
if (instr->addr >= mtd->size)
return -EINVAL;
instr->addr += part->offset;
- ret = part->master->erase(part->master, instr);
+ if ((ret = part->master->erase(part->master, instr) == -EROFS) &&
+ part->master->unlock &&
+ (! part->master->unlock (part->master, instr->addr,
+ mtd->erasesize)))
+ ret = part->master->erase(part->master, instr);
+
return ret;
}
^ permalink raw reply [flat|nested] 10+ messages in thread
* supporting flash that powers up locked
@ 2007-03-19 8:44 Rodolfo Giometti
2007-03-21 13:25 ` Josh Boyer
0 siblings, 1 reply; 10+ messages in thread
From: Rodolfo Giometti @ 2007-03-19 8:44 UTC (permalink / raw)
To: linux-mtd
[-- Attachment #1: Type: text/plain, Size: 548 bytes --]
Hello,
I noticed that this topic has been issued several times during last
years. I found several solutions but no one has been reported into the
main line.
Can you please tell me current work around? I'm using strataflash
Intel P30.
Thanks in advance,
Rodolfo
--
GNU/Linux Solutions e-mail: giometti@enneenne.com
Linux Device Driver giometti@gnudd.com
Embedded Systems giometti@linux.it
UNIX programming phone: +39 349 2432127
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: supporting flash that powers up locked
2007-03-19 8:44 supporting " Rodolfo Giometti
@ 2007-03-21 13:25 ` Josh Boyer
2007-03-21 15:09 ` Rodolfo Giometti
0 siblings, 1 reply; 10+ messages in thread
From: Josh Boyer @ 2007-03-21 13:25 UTC (permalink / raw)
To: Rodolfo Giometti; +Cc: linux-mtd
On Mon, 2007-03-19 at 09:44 +0100, Rodolfo Giometti wrote:
> Hello,
>
> I noticed that this topic has been issued several times during last
> years. I found several solutions but no one has been reported into the
> main line.
Actually, there was one recently. The MTD_STUPID_LOCK flag was added,
and if the chip driver sets that for a particular chip the core will
unlock them when add_mtd_device is called.
> Can you please tell me current work around? I'm using strataflash
> Intel P30.
You'd need to add a fixup to cfi_cmdset_0001.c for P30 to set that flag.
See the fixup_use_amtel_lock function in cfi_cmdset_0002.c for an
example.
josh
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: supporting flash that powers up locked
2007-03-21 13:25 ` Josh Boyer
@ 2007-03-21 15:09 ` Rodolfo Giometti
0 siblings, 0 replies; 10+ messages in thread
From: Rodolfo Giometti @ 2007-03-21 15:09 UTC (permalink / raw)
To: Josh Boyer; +Cc: linux-mtd
On Wed, Mar 21, 2007 at 08:25:38AM -0500, Josh Boyer wrote:
> You'd need to add a fixup to cfi_cmdset_0001.c for P30 to set that flag.
> See the fixup_use_amtel_lock function in cfi_cmdset_0002.c for an
> example.
Ok, that could resolve problem during boot but not during
suspend/resume cycle.
However I'm working on it and I'll propose a patch.
Thanks,
Rodolfo
--
GNU/Linux Solutions e-mail: giometti@enneenne.com
Linux Device Driver giometti@gnudd.com
Embedded Systems giometti@linux.it
UNIX programming phone: +39 349 2432127
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2007-03-21 15:08 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-11-23 22:25 Supporting flash that powers up locked Todd Poynor
2004-11-24 13:07 ` Josh Boyer
2004-11-25 0:37 ` Todd Poynor
2004-11-24 13:57 ` David Woodhouse
2004-11-25 1:15 ` Todd Poynor
2004-11-25 9:36 ` David Woodhouse
2004-12-01 3:50 ` Todd Poynor
-- strict thread matches above, loose matches on Subject: below --
2007-03-19 8:44 supporting " Rodolfo Giometti
2007-03-21 13:25 ` Josh Boyer
2007-03-21 15:09 ` Rodolfo Giometti
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox