diff options
| author | Richard Cochran <richardcochran@gmail.com> | 2010-06-14 12:10:33 -0400 |
|---|---|---|
| committer | David Woodhouse <David.Woodhouse@intel.com> | 2010-08-02 04:03:41 -0400 |
| commit | 9938424f0c4d208883cbf32083ec2bfcc220f85b (patch) | |
| tree | e4f7581c7543673fe63c98f9804e934a77aeb7ef | |
| parent | 1df620637fc3b252b69c92ced486b5b6b643dd1a (diff) | |
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 *); | |||
| 63 | static void cfi_intelext_sync (struct mtd_info *); | 63 | static void cfi_intelext_sync (struct mtd_info *); |
| 64 | static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); | 64 | static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); |
| 65 | static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); | 65 | static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); |
| 66 | static int cfi_intelext_is_locked(struct mtd_info *mtd, loff_t ofs, | ||
| 67 | uint64_t len); | ||
| 66 | #ifdef CONFIG_MTD_OTP | 68 | #ifdef CONFIG_MTD_OTP |
| 67 | static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 69 | static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
| 68 | static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 70 | 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) | |||
| 448 | mtd->sync = cfi_intelext_sync; | 450 | mtd->sync = cfi_intelext_sync; |
| 449 | mtd->lock = cfi_intelext_lock; | 451 | mtd->lock = cfi_intelext_lock; |
| 450 | mtd->unlock = cfi_intelext_unlock; | 452 | mtd->unlock = cfi_intelext_unlock; |
| 453 | mtd->is_locked = cfi_intelext_is_locked; | ||
| 451 | mtd->suspend = cfi_intelext_suspend; | 454 | mtd->suspend = cfi_intelext_suspend; |
| 452 | mtd->resume = cfi_intelext_resume; | 455 | mtd->resume = cfi_intelext_resume; |
| 453 | mtd->flags = MTD_CAP_NORFLASH; | 456 | mtd->flags = MTD_CAP_NORFLASH; |
| @@ -2139,6 +2142,13 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
| 2139 | return ret; | 2142 | return ret; |
| 2140 | } | 2143 | } |
| 2141 | 2144 | ||
| 2145 | static int cfi_intelext_is_locked(struct mtd_info *mtd, loff_t ofs, | ||
| 2146 | uint64_t len) | ||
| 2147 | { | ||
| 2148 | return cfi_varsize_frob(mtd, do_getlockstatus_oneblock, | ||
| 2149 | ofs, len, NULL) ? 1 : 0; | ||
| 2150 | } | ||
| 2151 | |||
| 2142 | #ifdef CONFIG_MTD_OTP | 2152 | #ifdef CONFIG_MTD_OTP |
| 2143 | 2153 | ||
| 2144 | typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip, | 2154 | 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, | |||
| 676 | break; | 676 | break; |
| 677 | } | 677 | } |
| 678 | 678 | ||
| 679 | case MEMISLOCKED: | ||
| 680 | { | ||
| 681 | struct erase_info_user einfo; | ||
| 682 | |||
| 683 | if (copy_from_user(&einfo, argp, sizeof(einfo))) | ||
| 684 | return -EFAULT; | ||
| 685 | |||
| 686 | if (!mtd->is_locked) | ||
| 687 | ret = -EOPNOTSUPP; | ||
| 688 | else | ||
| 689 | ret = mtd->is_locked(mtd, einfo.start, einfo.length); | ||
| 690 | break; | ||
| 691 | } | ||
| 692 | |||
| 679 | /* Legacy interface */ | 693 | /* Legacy interface */ |
| 680 | case MEMGETOOBSEL: | 694 | case MEMGETOOBSEL: |
| 681 | { | 695 | { |
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) | |||
| 264 | return part->master->unlock(part->master, ofs + part->offset, len); | 264 | return part->master->unlock(part->master, ofs + part->offset, len); |
| 265 | } | 265 | } |
| 266 | 266 | ||
| 267 | static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) | ||
| 268 | { | ||
| 269 | struct mtd_part *part = PART(mtd); | ||
| 270 | if ((len + ofs) > mtd->size) | ||
| 271 | return -EINVAL; | ||
| 272 | return part->master->is_locked(part->master, ofs + part->offset, len); | ||
| 273 | } | ||
| 274 | |||
| 267 | static void part_sync(struct mtd_info *mtd) | 275 | static void part_sync(struct mtd_info *mtd) |
| 268 | { | 276 | { |
| 269 | struct mtd_part *part = PART(mtd); | 277 | struct mtd_part *part = PART(mtd); |
| @@ -402,6 +410,8 @@ static struct mtd_part *add_one_partition(struct mtd_info *master, | |||
| 402 | slave->mtd.lock = part_lock; | 410 | slave->mtd.lock = part_lock; |
| 403 | if (master->unlock) | 411 | if (master->unlock) |
| 404 | slave->mtd.unlock = part_unlock; | 412 | slave->mtd.unlock = part_unlock; |
| 413 | if (master->is_locked) | ||
| 414 | slave->mtd.is_locked = part_is_locked; | ||
| 405 | if (master->block_isbad) | 415 | if (master->block_isbad) |
| 406 | slave->mtd.block_isbad = part_block_isbad; | 416 | slave->mtd.block_isbad = part_block_isbad; |
| 407 | if (master->block_markbad) | 417 | 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 { | |||
| 216 | /* Chip-supported device locking */ | 216 | /* Chip-supported device locking */ |
| 217 | int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); | 217 | int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); |
| 218 | int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); | 218 | int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); |
| 219 | int (*is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len); | ||
| 219 | 220 | ||
| 220 | /* Power Management functions */ | 221 | /* Power Management functions */ |
| 221 | int (*suspend) (struct mtd_info *mtd); | 222 | 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 { | |||
| 110 | #define MEMERASE64 _IOW('M', 20, struct erase_info_user64) | 110 | #define MEMERASE64 _IOW('M', 20, struct erase_info_user64) |
| 111 | #define MEMWRITEOOB64 _IOWR('M', 21, struct mtd_oob_buf64) | 111 | #define MEMWRITEOOB64 _IOWR('M', 21, struct mtd_oob_buf64) |
| 112 | #define MEMREADOOB64 _IOWR('M', 22, struct mtd_oob_buf64) | 112 | #define MEMREADOOB64 _IOWR('M', 22, struct mtd_oob_buf64) |
| 113 | #define MEMISLOCKED _IOR('M', 23, struct erase_info_user) | ||
| 113 | 114 | ||
| 114 | /* | 115 | /* |
| 115 | * Obsolete legacy interface. Keep it in order not to break userspace | 116 | * Obsolete legacy interface. Keep it in order not to break userspace |
