mtd: add an ioctl to query the lock status of a flash sector
Richard Cochran [Mon, 14 Jun 2010 16:10:33 +0000 (18:10 +0200)]
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>

drivers/mtd/chips/cfi_cmdset_0001.c
drivers/mtd/mtdchar.c
drivers/mtd/mtdpart.c
include/linux/mtd/mtd.h
include/mtd/mtd-abi.h

index 62f3ea9..2fadb02 100644 (file)
@@ -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,
index 8b223c0..a8e69dd 100644 (file)
@@ -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:
        {
index b8043a9..4c539de 100644 (file)
@@ -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)
index 5326435..43b7d72 100644 (file)
@@ -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);
index be51ae2..e12872e 100644 (file)
@@ -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