mtd: maps: l440gx: Add reference counter to set_vpp()
authorPaul Parsons <lost.distance@yahoo.com>
Wed, 7 Mar 2012 14:12:50 +0000 (14:12 +0000)
committerDavid Woodhouse <David.Woodhouse@intel.com>
Mon, 26 Mar 2012 23:52:49 +0000 (00:52 +0100)
This patch is part of a set which fixes unnecessary flash erase and write errors
resulting from the MTD CFI driver turning off vpp while an erase is in progress.
This patch allows l440gx_set_vpp() calls to be nested by adding a reference
counter.

Signed-off-by: Paul Parsons <lost.distance@yahoo.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
drivers/mtd/maps/l440gx.c

index dd0360ba2412b646e27dd05fd11fbe29c37e211a..74bd98ee635fa96e60973490f1f54650f54cfca3 100644 (file)
@@ -27,17 +27,21 @@ static struct mtd_info *mymtd;
 
 
 /* Is this really the vpp port? */
+static DEFINE_SPINLOCK(l440gx_vpp_lock);
+static int l440gx_vpp_refcnt;
 static void l440gx_set_vpp(struct map_info *map, int vpp)
 {
-       unsigned long l;
+       unsigned long flags;
 
-       l = inl(VPP_PORT);
+       spin_lock_irqsave(&l440gx_vpp_lock, flags);
        if (vpp) {
-               l |= 1;
+               if (++l440gx_vpp_refcnt == 1)   /* first nested 'on' */
+                       outl(inl(VPP_PORT) | 1, VPP_PORT);
        } else {
-               l &= ~1;
+               if (--l440gx_vpp_refcnt == 0)   /* last nested 'off' */
+                       outl(inl(VPP_PORT) & ~1, VPP_PORT);
        }
-       outl(l, VPP_PORT);
+       spin_unlock_irqrestore(&l440gx_vpp_lock, flags);
 }
 
 static struct map_info l440gx_map = {