aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPaul Parsons <lost.distance@yahoo.com>2012-03-07 09:12:08 -0500
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-03-26 19:52:28 -0400
commit876fe76d793d03077eb61ba3afab4a383f46c554 (patch)
treefb7d98bd746ebd1c3c5919f10a998e8f2dbd9e8b /drivers
parente7d9377e0440c25805dcc5b0af189a87beb69f5e (diff)
mtd: maps: physmap: 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 physmap_set_vpp() calls to be nested by adding a reference counter. omap1_set_vpp() already used a reference counter. Since it is called from physmap_set_vpp(), omap1_set_vpp() can now be simplified. simtec_nor_vpp() already disabled hard interrupts. Since it is called from physmap_set_vpp(), simtec_nor_vpp() can now be simplified. 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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/maps/physmap.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index abc562653b31..7e9233c503ab 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -27,6 +27,8 @@ struct physmap_flash_info {
27 struct mtd_info *mtd[MAX_RESOURCES]; 27 struct mtd_info *mtd[MAX_RESOURCES];
28 struct mtd_info *cmtd; 28 struct mtd_info *cmtd;
29 struct map_info map[MAX_RESOURCES]; 29 struct map_info map[MAX_RESOURCES];
30 spinlock_t vpp_lock;
31 int vpp_refcnt;
30}; 32};
31 33
32static int physmap_flash_remove(struct platform_device *dev) 34static int physmap_flash_remove(struct platform_device *dev)
@@ -63,12 +65,26 @@ static void physmap_set_vpp(struct map_info *map, int state)
63{ 65{
64 struct platform_device *pdev; 66 struct platform_device *pdev;
65 struct physmap_flash_data *physmap_data; 67 struct physmap_flash_data *physmap_data;
68 struct physmap_flash_info *info;
69 unsigned long flags;
66 70
67 pdev = (struct platform_device *)map->map_priv_1; 71 pdev = (struct platform_device *)map->map_priv_1;
68 physmap_data = pdev->dev.platform_data; 72 physmap_data = pdev->dev.platform_data;
69 73
70 if (physmap_data->set_vpp) 74 if (!physmap_data->set_vpp)
71 physmap_data->set_vpp(pdev, state); 75 return;
76
77 info = platform_get_drvdata(pdev);
78
79 spin_lock_irqsave(&info->vpp_lock, flags);
80 if (state) {
81 if (++info->vpp_refcnt == 1) /* first nested 'on' */
82 physmap_data->set_vpp(pdev, 1);
83 } else {
84 if (--info->vpp_refcnt == 0) /* last nested 'off' */
85 physmap_data->set_vpp(pdev, 0);
86 }
87 spin_unlock_irqrestore(&info->vpp_lock, flags);
72} 88}
73 89
74static const char *rom_probe_types[] = { 90static const char *rom_probe_types[] = {
@@ -172,6 +188,8 @@ static int physmap_flash_probe(struct platform_device *dev)
172 if (err) 188 if (err)
173 goto err_out; 189 goto err_out;
174 190
191 spin_lock_init(&info->vpp_lock);
192
175 part_types = physmap_data->part_probe_types ? : part_probe_types; 193 part_types = physmap_data->part_probe_types ? : part_probe_types;
176 194
177 mtd_device_parse_register(info->cmtd, part_types, 0, 195 mtd_device_parse_register(info->cmtd, part_types, 0,