aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/maps/pmcmsp-flash.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/maps/pmcmsp-flash.c')
-rw-r--r--drivers/mtd/maps/pmcmsp-flash.c76
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
51static int __init init_msp_flash(void) 51static 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
188cleanup_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);
197free_msp_parts:
198 kfree(msp_parts);
199free_msp_flash:
200 kfree(msp_flash);
201 return ret;
160} 202}
161 203
162static void __exit cleanup_msp_flash(void) 204static 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);