Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mtd: maps: l440gx: Add reference counter to set_vpp()

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>

authored by

Paul Parsons and committed by
David Woodhouse
5fbabf3f 876fe76d

+9 -5
+9 -5
drivers/mtd/maps/l440gx.c
··· 27 27 28 28 29 29 /* Is this really the vpp port? */ 30 + static DEFINE_SPINLOCK(l440gx_vpp_lock); 31 + static int l440gx_vpp_refcnt; 30 32 static void l440gx_set_vpp(struct map_info *map, int vpp) 31 33 { 32 - unsigned long l; 34 + unsigned long flags; 33 35 34 - l = inl(VPP_PORT); 36 + spin_lock_irqsave(&l440gx_vpp_lock, flags); 35 37 if (vpp) { 36 - l |= 1; 38 + if (++l440gx_vpp_refcnt == 1) /* first nested 'on' */ 39 + outl(inl(VPP_PORT) | 1, VPP_PORT); 37 40 } else { 38 - l &= ~1; 41 + if (--l440gx_vpp_refcnt == 0) /* last nested 'off' */ 42 + outl(inl(VPP_PORT) & ~1, VPP_PORT); 39 43 } 40 - outl(l, VPP_PORT); 44 + spin_unlock_irqrestore(&l440gx_vpp_lock, flags); 41 45 } 42 46 43 47 static struct map_info l440gx_map = {