diff options
author | Roel Kluin <roel.kluin@gmail.com> | 2009-08-10 04:16:37 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2009-09-04 04:42:06 -0400 |
commit | 2c78c44362bc9b7c715a3c2119b89a407c1cb739 (patch) | |
tree | 2ecdf19b0bccb73b60486c6784ae7cf0c7d67350 /drivers/mtd | |
parent | fca910883324d437a24d447b08f524fa19261a94 (diff) |
mtd: pmcmsp-flash: fix error paths in init_msp_flash
Cleanin up after errors in init_msp_flash().
Also cleanup_msp_flash() attempts to determine the size of
msp_flash with `sizeof(msp_flash) / sizeof(struct mtd_info **)'
This will not work since msp_flash is not an array.
Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/maps/pmcmsp-flash.c | 76 |
1 files changed, 59 insertions, 17 deletions
diff --git a/drivers/mtd/maps/pmcmsp-flash.c b/drivers/mtd/maps/pmcmsp-flash.c index 4768bd5459d6..c8fd8da4bc87 100644 --- a/drivers/mtd/maps/pmcmsp-flash.c +++ b/drivers/mtd/maps/pmcmsp-flash.c | |||
@@ -50,7 +50,7 @@ static int fcnt; | |||
50 | 50 | ||
51 | static int __init init_msp_flash(void) | 51 | static int __init init_msp_flash(void) |
52 | { | 52 | { |
53 | int i, j; | 53 | int i, j, ret = -ENOMEM; |
54 | int offset, coff; | 54 | int offset, coff; |
55 | char *env; | 55 | char *env; |
56 | int pcnt; | 56 | int pcnt; |
@@ -75,14 +75,16 @@ static int __init init_msp_flash(void) | |||
75 | printk(KERN_NOTICE "Found %d PMC flash devices\n", fcnt); | 75 | printk(KERN_NOTICE "Found %d PMC flash devices\n", fcnt); |
76 | 76 | ||
77 | msp_flash = kmalloc(fcnt * sizeof(struct map_info *), GFP_KERNEL); | 77 | msp_flash = kmalloc(fcnt * sizeof(struct map_info *), GFP_KERNEL); |
78 | if (!msp_flash) | ||
79 | return -ENOMEM; | ||
80 | |||
78 | msp_parts = kmalloc(fcnt * sizeof(struct mtd_partition *), GFP_KERNEL); | 81 | msp_parts = kmalloc(fcnt * sizeof(struct mtd_partition *), GFP_KERNEL); |
82 | if (!msp_parts) | ||
83 | goto free_msp_flash; | ||
84 | |||
79 | msp_maps = kcalloc(fcnt, sizeof(struct mtd_info), GFP_KERNEL); | 85 | msp_maps = kcalloc(fcnt, sizeof(struct mtd_info), GFP_KERNEL); |
80 | if (!msp_flash || !msp_parts || !msp_maps) { | 86 | if (!msp_maps) |
81 | kfree(msp_maps); | 87 | goto free_msp_parts; |
82 | kfree(msp_parts); | ||
83 | kfree(msp_flash); | ||
84 | return -ENOMEM; | ||
85 | } | ||
86 | 88 | ||
87 | /* loop over the flash devices, initializing each */ | 89 | /* loop over the flash devices, initializing each */ |
88 | for (i = 0; i < fcnt; i++) { | 90 | for (i = 0; i < fcnt; i++) { |
@@ -100,13 +102,18 @@ static int __init init_msp_flash(void) | |||
100 | 102 | ||
101 | msp_parts[i] = kcalloc(pcnt, sizeof(struct mtd_partition), | 103 | msp_parts[i] = kcalloc(pcnt, sizeof(struct mtd_partition), |
102 | GFP_KERNEL); | 104 | GFP_KERNEL); |
105 | if (!msp_parts[i]) | ||
106 | goto cleanup_loop; | ||
103 | 107 | ||
104 | /* now initialize the devices proper */ | 108 | /* now initialize the devices proper */ |
105 | flash_name[5] = '0' + i; | 109 | flash_name[5] = '0' + i; |
106 | env = prom_getenv(flash_name); | 110 | env = prom_getenv(flash_name); |
107 | 111 | ||
108 | if (sscanf(env, "%x:%x", &addr, &size) < 2) | 112 | if (sscanf(env, "%x:%x", &addr, &size) < 2) { |
109 | return -ENXIO; | 113 | ret = -ENXIO; |
114 | kfree(msp_parts[i]); | ||
115 | goto cleanup_loop; | ||
116 | } | ||
110 | addr = CPHYSADDR(addr); | 117 | addr = CPHYSADDR(addr); |
111 | 118 | ||
112 | printk(KERN_NOTICE | 119 | printk(KERN_NOTICE |
@@ -122,13 +129,23 @@ static int __init init_msp_flash(void) | |||
122 | */ | 129 | */ |
123 | if (size > CONFIG_MSP_FLASH_MAP_LIMIT) | 130 | if (size > CONFIG_MSP_FLASH_MAP_LIMIT) |
124 | size = CONFIG_MSP_FLASH_MAP_LIMIT; | 131 | size = CONFIG_MSP_FLASH_MAP_LIMIT; |
132 | |||
125 | msp_maps[i].virt = ioremap(addr, size); | 133 | msp_maps[i].virt = ioremap(addr, size); |
134 | if (msp_maps[i].virt == NULL) { | ||
135 | ret = -ENXIO; | ||
136 | kfree(msp_parts[i]); | ||
137 | goto cleanup_loop; | ||
138 | } | ||
139 | |||
126 | msp_maps[i].bankwidth = 1; | 140 | msp_maps[i].bankwidth = 1; |
127 | msp_maps[i].name = strncpy(kmalloc(7, GFP_KERNEL), | 141 | msp_maps[i].name = kmalloc(7, GFP_KERNEL); |
128 | flash_name, 7); | 142 | if (!msp_maps[i].name) { |
143 | iounmap(msp_maps[i].virt); | ||
144 | kfree(msp_parts[i]); | ||
145 | goto cleanup_loop; | ||
146 | } | ||
129 | 147 | ||
130 | if (msp_maps[i].virt == NULL) | 148 | msp_maps[i].name = strncpy(msp_maps[i].name, flash_name, 7); |
131 | return -ENXIO; | ||
132 | 149 | ||
133 | for (j = 0; j < pcnt; j++) { | 150 | for (j = 0; j < pcnt; j++) { |
134 | part_name[5] = '0' + i; | 151 | part_name[5] = '0' + i; |
@@ -136,8 +153,14 @@ static int __init init_msp_flash(void) | |||
136 | 153 | ||
137 | env = prom_getenv(part_name); | 154 | env = prom_getenv(part_name); |
138 | 155 | ||
139 | if (sscanf(env, "%x:%x:%n", &offset, &size, &coff) < 2) | 156 | if (sscanf(env, "%x:%x:%n", &offset, &size, |
140 | return -ENXIO; | 157 | &coff) < 2) { |
158 | ret = -ENXIO; | ||
159 | kfree(msp_maps[i].name); | ||
160 | iounmap(msp_maps[i].virt); | ||
161 | kfree(msp_parts[i]); | ||
162 | goto cleanup_loop; | ||
163 | } | ||
141 | 164 | ||
142 | msp_parts[i][j].size = size; | 165 | msp_parts[i][j].size = size; |
143 | msp_parts[i][j].offset = offset; | 166 | msp_parts[i][j].offset = offset; |
@@ -152,18 +175,37 @@ static int __init init_msp_flash(void) | |||
152 | add_mtd_partitions(msp_flash[i], msp_parts[i], pcnt); | 175 | add_mtd_partitions(msp_flash[i], msp_parts[i], pcnt); |
153 | } else { | 176 | } else { |
154 | printk(KERN_ERR "map probe failed for flash\n"); | 177 | printk(KERN_ERR "map probe failed for flash\n"); |
155 | return -ENXIO; | 178 | ret = -ENXIO; |
179 | kfree(msp_maps[i].name); | ||
180 | iounmap(msp_maps[i].virt); | ||
181 | kfree(msp_parts[i]); | ||
182 | goto cleanup_loop; | ||
156 | } | 183 | } |
157 | } | 184 | } |
158 | 185 | ||
159 | return 0; | 186 | return 0; |
187 | |||
188 | cleanup_loop: | ||
189 | while (i--) { | ||
190 | del_mtd_partitions(msp_flash[i]); | ||
191 | map_destroy(msp_flash[i]); | ||
192 | kfree(msp_maps[i].name); | ||
193 | iounmap(msp_maps[i].virt); | ||
194 | kfree(msp_parts[i]); | ||
195 | } | ||
196 | kfree(msp_maps); | ||
197 | free_msp_parts: | ||
198 | kfree(msp_parts); | ||
199 | free_msp_flash: | ||
200 | kfree(msp_flash); | ||
201 | return ret; | ||
160 | } | 202 | } |
161 | 203 | ||
162 | static void __exit cleanup_msp_flash(void) | 204 | static void __exit cleanup_msp_flash(void) |
163 | { | 205 | { |
164 | int i; | 206 | int i; |
165 | 207 | ||
166 | for (i = 0; i < sizeof(msp_flash) / sizeof(struct mtd_info **); i++) { | 208 | for (i = 0; i < fcnt; i++) { |
167 | del_mtd_partitions(msp_flash[i]); | 209 | del_mtd_partitions(msp_flash[i]); |
168 | map_destroy(msp_flash[i]); | 210 | map_destroy(msp_flash[i]); |
169 | iounmap((void *)msp_maps[i].virt); | 211 | iounmap((void *)msp_maps[i].virt); |