All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Richard J. Broberg" <rjb@ayrnetworks.com>
To: David Woodhouse <dwmw2@infradead.org>
Cc: linux-mtd@lists.infradead.org
Subject: Is there any interest in providing a query lock to go with lock and unlock?
Date: Mon, 5 Aug 2002 08:19:40 -0700	[thread overview]
Message-ID: <200208050819.40628.rjb@ayrnetworks.com> (raw)

We have a parochial need which I have met in a heavy
handed way by adding a mtd vector and an ioctl.

The files changed in our 2.4.16 kernel are

drivers/mtd/mtdchar.c
drivers/mtd/chips/amd_flash.c
drivers/mtd/chips/cfi_cmdset_0001.c
include/linux/mtd/mtd.h

If somebody has a less invasive way, I would love to hear
about it.

If some others find this approach useful, I will try to get an
acceptable patch.

Thanks,
	Dick Broberg

===================================================================
RCS file: /cvs/public/linux/drivers/mtd/mtdchar.c,v
retrieving revision 1.3
diff -c -b -B -r1.3 mtdchar.c
*** drivers/mtd/mtdchar.c       2002/04/16 20:01:07     1.3
--- drivers/mtd/mtdchar.c       2002/08/01 21:08:33
***************
*** 282,287 ****
--- 282,323 ----
                break;
        }
  

+       case MEMGETREGIONLOCKS:
+       {
+               int                     blocks,i,es;
+               char                   *stati;
+               struct region_info_lock ul;
+ 
+               if (copy_from_user(     &ul, 
+                                       (struct region_info_lock *)arg, 
+                                       sizeof(struct region_info_lock))) {
+                       ret = -EFAULT;
+               } else if (ul.regionindex >= mtd->numeraseregions) {
+                       ret = -EINVAL;
+               } else {
+                       blocks = mtd->eraseregions[ul.regionindex].numblocks;
+                       es = mtd->eraseregions[ul.regionindex].erasesize;
+                       stati = kmalloc(blocks,GFP_KERNEL);
+                       if (!stati) {
+                               ret = -ENOMEM;
+                       } else {
+                               memset(stati,0,blocks);
+                               if (mtd->is_it_locked) {
+                                       for (i = 0; i < blocks; i++) {
+                                               stati[i] = mtd->is_it_locked(mtd,
+                                                                            i * es,
+                                                                            es);
+                                       }
+                               }
+                               if (copy_to_user(ul.block_stati,stati,blocks)) {
+                                       ret = -EFAULT;
+                               }
+                               kfree(stati);
+                       }
+               }
+               break;
+       }
+ 
        case MEMGETINFO:
                if (copy_to_user((struct mtd_info *)arg, mtd,
                                 sizeof(struct mtd_info_user)))
Index: drivers/mtd/chips/amd_flash.c
===================================================================
RCS file: /cvs/public/linux/drivers/mtd/chips/amd_flash.c,v
retrieving revision 1.2
diff -c -b -B -r1.2 amd_flash.c
*** drivers/mtd/chips/amd_flash.c       2002/03/15 00:29:21     1.2
--- drivers/mtd/chips/amd_flash.c       2002/08/01 21:08:33
***************
*** 295,300 ****
--- 295,332 ----
        return amd_flash_do_unlock(mtd, ofs, len, 1);
  }
  

+ static int amd_flash_is_it_locked(struct mtd_info *mtd, loff_t ofs, size_t len)
+ {
+       struct map_info *map = mtd->priv;
+       struct mtd_erase_region_info *merip;
+       int eraseoffset, erasesize, eraseblocks;
+       int i;
+       int lock_status = 0;
+ 
+       /* Pass the whole chip through sector by sector and check for each
+          sector if the sector and the given interval overlap */
+       for(i = 0; i < mtd->numeraseregions; i++) {
+               merip = &mtd->eraseregions[i];
+ 
+               eraseoffset = merip->offset;
+               erasesize = merip->erasesize;
+               eraseblocks = merip->numblocks;
+ 
+               if (ofs > eraseoffset + erasesize)
+                       continue;
+               while (eraseblocks > 0) {
+                       if (ofs < eraseoffset + erasesize && ofs + len > eraseoffset) {
+                               lock_status = is_sector_locked(map, eraseoffset);
+                               goto have_lock_status;
+                       }
+                       eraseoffset += erasesize;
+                       eraseblocks --;
+               }
+       }
+  have_lock_status:
+       return lock_status;
+ }
+ 
  static int amd_flash_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
  {
        return amd_flash_do_unlock(mtd, ofs, len, 0);
***************
*** 748,753 ****
--- 780,786 ----
        mtd->resume = amd_flash_resume; 
        mtd->lock = amd_flash_lock;
        mtd->unlock = amd_flash_unlock;
+       mtd->is_it_locked = amd_flash_is_it_locked;
  

        private = kmalloc(sizeof(*private) + (sizeof(struct flchip) *
                                              temp.numchips), GFP_KERNEL);
Index: drivers/mtd/chips/cfi_cmdset_0001.c
===================================================================
RCS file: /cvs/public/linux/drivers/mtd/chips/cfi_cmdset_0001.c,v
retrieving revision 1.3
diff -c -b -B -r1.3 cfi_cmdset_0001.c
*** drivers/mtd/chips/cfi_cmdset_0001.c 2002/03/27 23:35:42     1.3
--- drivers/mtd/chips/cfi_cmdset_0001.c 2002/08/01 21:08:33
***************
*** 51,56 ****
--- 51,57 ----
  struct mtd_info *cfi_cmdset_0001(struct map_info *, int);
  

  static struct mtd_info *cfi_intelext_setup (struct map_info *);
+ static int cfi_is_it_locked(struct mtd_info *mtd, loff_t ofs, size_t len);
  

  static struct mtd_chip_driver cfi_intelext_chipdrv = {
        probe: NULL, /* Not usable directly */
***************
*** 264,269 ****
--- 265,271 ----
      mtd->sync = cfi_intelext_sync;
      mtd->lock = cfi_intelext_lock;
      mtd->unlock = cfi_intelext_unlock;
+     mtd->is_it_locked = cfi_is_it_locked;
      mtd->suspend = cfi_intelext_suspend;
      mtd->resume = cfi_intelext_resume;
      mtd->flags = MTD_CAP_NORFLASH;
***************
*** 1067,1084 ****
  

        return 0;
  }
- 
- typedef int (*varsize_frob_t)(struct map_info *map, struct flchip *chip,
-                             unsigned long adr, void *thunk);
  

! static int cfi_intelext_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
!                                    loff_t ofs, size_t len, void *thunk)
  {
!       struct map_info *map = mtd->priv;
!       struct cfi_private *cfi = map->fldrv_priv;
!       unsigned long adr;
!       int chipnum, ret = 0;
!       int i, first;
        struct mtd_erase_region_info *regions = mtd->eraseregions;
  

        if (ofs > mtd->size)
--- 1068,1077 ----
  

        return 0;
  }
  

! static int get_region_index(struct mtd_info *mtd, loff_t ofs, size_t len, int *first)
  {
!         int i;
        struct mtd_erase_region_info *regions = mtd->eraseregions;
  

        if (ofs > mtd->size)
***************
*** 1087,1101 ****
        if ((len + ofs) > mtd->size)
                return -EINVAL;
  

!       /* Check that both start and end of the requested erase are
         * aligned with the erasesize at the appropriate addresses.
         */
  

        i = 0;
  

!       /* Skip all erase regions which are ended before the start of 
!          the requested erase. Actually, to save on the calculations,
!          we skip to the first erase region which starts after the
           start of the requested erase, and then go back one.
        */
        

--- 1079,1093 ----
        if ((len + ofs) > mtd->size)
                return -EINVAL;
  

!       /* Check that both start and end of the requested region are
         * aligned with the erasesize at the appropriate addresses.
         */
  

        i = 0;
  

!       /* Skip all regions which are ended before the start of 
!          the requested region. Actually, to save on the calculations,
!          we skip to the first region which starts after the
           start of the requested erase, and then go back one.
        */
        

***************
*** 1104,1111 ****
        i--;
  

        /* OK, now i is pointing at the erase region in which this 
!          erase request starts. Check the start of the requested
!          erase range is aligned with the erase size which is in
           effect here.
        */
  

--- 1096,1103 ----
        i--;
  

        /* OK, now i is pointing at the erase region in which this 
!          request starts. Check the start of the requested
!          range is aligned with the erase size which is in
           effect here.
        */
  

***************
*** 1113,1121 ****
                return -EINVAL;
  

        /* Remember the erase region we start on */
!       first = i;
  

!       /* Next, check that the end of the requested erase is aligned
         * with the erase region at that address.
         */
  

--- 1105,1115 ----
                return -EINVAL;
  

        /* Remember the erase region we start on */
! 
!       if (first)
!           *first = i;
  

!       /* Next, check that the end of the request is aligned
         * with the erase region at that address.
         */
  

***************
*** 1129,1135 ****
--- 1123,1147 ----
  

        if ((ofs + len) & (regions[i].erasesize-1))
                return -EINVAL;
+       return i;
+ }
+ 
+ typedef int (*varsize_frob_t)(struct map_info *map, struct flchip *chip,
+                             unsigned long adr, void *thunk);
+ 
+ static int cfi_intelext_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
+                                    loff_t ofs, size_t len, void *thunk)
+ {
+       struct map_info *map = mtd->priv;
+       struct cfi_private *cfi = map->fldrv_priv;
+       unsigned long adr;
+       int chipnum, ret = 0;
+       int i, first;
+       struct mtd_erase_region_info *regions = mtd->eraseregions;
  

+       if (0 > (i = get_region_index(mtd,ofs,len,&first))) 
+           return i;
+ 
        chipnum = ofs >> cfi->chipshift;
        adr = ofs - (chipnum << cfi->chipshift);
  

***************
*** 1401,1406 ****
--- 1413,1441 ----
        }
  }
  

+ static int cfi_is_it_locked(struct mtd_info *mtd, loff_t ofs, size_t len)
+ {
+       struct map_info              *map = mtd->priv;
+       struct cfi_private           *cfi = map->fldrv_priv;
+       int                           ofs_factor = cfi->interleave *
+                                                  cfi->device_type;
+       unsigned long                 adr;
+       int                           chipnum;
+       int                           i;
+       int                           flags = 0;
+ 
+       if (0 > (i = get_region_index(mtd,ofs,len,0))) 
+           return i;
+       
+       chipnum = ofs >> cfi->chipshift;
+       adr = ofs - (chipnum << cfi->chipshift);
+ 
+       cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL);
+       flags = cfi_read_query(map, adr+(2*ofs_factor));
+       cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL);
+       return flags;
+ }
+ 
  #ifdef DEBUG_LOCK_BITS
  static int do_printlockstatus_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, void *thunk)
  {
***************
*** 1451,1457 ****
                /* Urgh. Chip not yet ready to talk to us. */
                if (time_after(jiffies, timeo)) {
                        spin_unlock_bh(chip->mutex);
!                       printk(KERN_ERR __FUNCTION__ ": waiting for chip to be ready timed out\n");
                        return -EIO;
                }
  

--- 1486,1494 ----
                /* Urgh. Chip not yet ready to talk to us. */
                if (time_after(jiffies, timeo)) {
                        spin_unlock_bh(chip->mutex);
!                       printk(KERN_ERR 
!                              "%s: waiting for chip to be ready timed out\n",
!                              __FUNCTION__);
                        return -EIO;
                }
  

Index: include/linux/mtd/mtd.h
===================================================================
RCS file: /cvs/public/linux/include/linux/mtd/mtd.h,v
retrieving revision 1.4
diff -c -b -B -r1.4 mtd.h
*** include/linux/mtd/mtd.h     2002/04/16 20:00:29     1.4
--- include/linux/mtd/mtd.h     2002/08/01 21:08:33
***************
*** 85,90 ****
--- 85,95 ----
        u_int32_t regionindex;
  };
  

+ struct region_info_lock {
+       u_int32_t  regionindex;
+       u_char     *block_stati;
+ };
+ 
  #define MEMGETINFO              _IOR('M', 1, struct mtd_info_user)
  #define MEMERASE                _IOW('M', 2, struct erase_info_user)
  #define MEMWRITEOOB             _IOWR('M', 3, struct mtd_oob_buf)
***************
*** 93,98 ****
--- 98,104 ----
  #define MEMUNLOCK               _IOW('M', 6, struct erase_info_user)
  #define MEMGETREGIONCOUNT     _IOR('M', 7, int)
  #define MEMGETREGIONINFO      _IOWR('M', 8, struct region_info_user)
+ #define MEMGETREGIONLOCKS     _IOWR('M', 9, struct region_info_lock)
  

  #ifndef __KERNEL__
  

***************
*** 207,212 ****
--- 213,219 ----
        /* Chip-supported device locking */
        int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len);
        int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);
+       int (*is_it_locked) (struct mtd_info *mtd, loff_t ofs, size_t len);
  

        /* Power Management functions */
        int (*suspend) (struct mtd_info *mtd);

             reply	other threads:[~2002-08-05 15:19 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-08-05 15:19 Richard J. Broberg [this message]
2002-08-06 10:09 ` Is there any interest in providing a query lock to go with lock and unlock? David Woodhouse

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200208050819.40628.rjb@ayrnetworks.com \
    --to=rjb@ayrnetworks.com \
    --cc=dwmw2@infradead.org \
    --cc=linux-mtd@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.