diff options
author | Richard Cochran <richardcochran@gmail.com> | 2010-06-14 18:10:33 +0200 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2010-08-02 09:03:41 +0100 |
commit | 9938424f0c4d208883cbf32083ec2bfcc220f85b (patch) | |
tree | e4f7581c7543673fe63c98f9804e934a77aeb7ef | |
parent | 1df620637fc3b252b69c92ced486b5b6b643dd1a (diff) | |
download | linux-9938424f0c4d208883cbf32083ec2bfcc220f85b.tar.bz2 |
mtd: add an ioctl to query the lock status of a flash sector
This patchs adds a way for user space programs to find out whether a
flash sector is locked. An optional driver method in the mtd_info struct
provides the information.
Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0001.c | 10 | ||||
-rw-r--r-- | drivers/mtd/mtdchar.c | 14 | ||||
-rw-r--r-- | drivers/mtd/mtdpart.c | 10 | ||||
-rw-r--r-- | include/linux/mtd/mtd.h | 1 | ||||
-rw-r--r-- | include/mtd/mtd-abi.h | 1 |
5 files changed, 36 insertions, 0 deletions
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 62f3ea9de848..2fadb0239ba3 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -63,6 +63,8 @@ static int cfi_intelext_erase_varsize(struct mtd_info *, struct erase_info *); static void cfi_intelext_sync (struct mtd_info *); static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); +static int cfi_intelext_is_locked(struct mtd_info *mtd, loff_t ofs, + uint64_t len); #ifdef CONFIG_MTD_OTP static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); @@ -448,6 +450,7 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) mtd->sync = cfi_intelext_sync; mtd->lock = cfi_intelext_lock; mtd->unlock = cfi_intelext_unlock; + mtd->is_locked = cfi_intelext_is_locked; mtd->suspend = cfi_intelext_suspend; mtd->resume = cfi_intelext_resume; mtd->flags = MTD_CAP_NORFLASH; @@ -2139,6 +2142,13 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) return ret; } +static int cfi_intelext_is_locked(struct mtd_info *mtd, loff_t ofs, + uint64_t len) +{ + return cfi_varsize_frob(mtd, do_getlockstatus_oneblock, + ofs, len, NULL) ? 1 : 0; +} + #ifdef CONFIG_MTD_OTP typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip, diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 8b223c0343ee..a8e69dd2b2e4 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -676,6 +676,20 @@ static int mtd_ioctl(struct inode *inode, struct file *file, break; } + case MEMISLOCKED: + { + struct erase_info_user einfo; + + if (copy_from_user(&einfo, argp, sizeof(einfo))) + return -EFAULT; + + if (!mtd->is_locked) + ret = -EOPNOTSUPP; + else + ret = mtd->is_locked(mtd, einfo.start, einfo.length); + break; + } + /* Legacy interface */ case MEMGETOOBSEL: { diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index b8043a9ba32d..4c539ded0b70 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -264,6 +264,14 @@ static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) return part->master->unlock(part->master, ofs + part->offset, len); } +static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) +{ + struct mtd_part *part = PART(mtd); + if ((len + ofs) > mtd->size) + return -EINVAL; + return part->master->is_locked(part->master, ofs + part->offset, len); +} + static void part_sync(struct mtd_info *mtd) { struct mtd_part *part = PART(mtd); @@ -402,6 +410,8 @@ static struct mtd_part *add_one_partition(struct mtd_info *master, slave->mtd.lock = part_lock; if (master->unlock) slave->mtd.unlock = part_unlock; + if (master->is_locked) + slave->mtd.is_locked = part_is_locked; if (master->block_isbad) slave->mtd.block_isbad = part_block_isbad; if (master->block_markbad) diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 5326435a7571..43b7d72c6116 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -216,6 +216,7 @@ struct mtd_info { /* Chip-supported device locking */ int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); + int (*is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len); /* Power Management functions */ int (*suspend) (struct mtd_info *mtd); diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h index be51ae2bd0ff..e12872e3c694 100644 --- a/include/mtd/mtd-abi.h +++ b/include/mtd/mtd-abi.h @@ -110,6 +110,7 @@ struct otp_info { #define MEMERASE64 _IOW('M', 20, struct erase_info_user64) #define MEMWRITEOOB64 _IOWR('M', 21, struct mtd_oob_buf64) #define MEMREADOOB64 _IOWR('M', 22, struct mtd_oob_buf64) +#define MEMISLOCKED _IOR('M', 23, struct erase_info_user) /* * Obsolete legacy interface. Keep it in order not to break userspace |