diff options
-rw-r--r-- | fs/pstore/ram.c | 99 |
1 files changed, 62 insertions, 37 deletions
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 9b274b98bf3b..6b7676738493 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c | |||
@@ -202,13 +202,65 @@ static struct ramoops_context oops_cxt = { | |||
202 | }, | 202 | }, |
203 | }; | 203 | }; |
204 | 204 | ||
205 | static void ramoops_free_przs(struct ramoops_context *cxt) | ||
206 | { | ||
207 | int i; | ||
208 | |||
209 | if (!cxt->przs) | ||
210 | return; | ||
211 | |||
212 | for (i = 0; cxt->przs[i]; i++) | ||
213 | persistent_ram_free(cxt->przs[i]); | ||
214 | kfree(cxt->przs); | ||
215 | } | ||
216 | |||
217 | static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt, | ||
218 | phys_addr_t *paddr, size_t dump_mem_sz) | ||
219 | { | ||
220 | int err = -ENOMEM; | ||
221 | int i; | ||
222 | |||
223 | if (!cxt->record_size) | ||
224 | return 0; | ||
225 | |||
226 | cxt->max_dump_cnt = dump_mem_sz / cxt->record_size; | ||
227 | if (!cxt->max_dump_cnt) | ||
228 | return -ENOMEM; | ||
229 | |||
230 | cxt->przs = kzalloc(sizeof(*cxt->przs) * cxt->max_dump_cnt, | ||
231 | GFP_KERNEL); | ||
232 | if (!cxt->przs) { | ||
233 | dev_err(dev, "failed to initialize a prz array for dumps\n"); | ||
234 | return -ENOMEM; | ||
235 | } | ||
236 | |||
237 | for (i = 0; i < cxt->max_dump_cnt; i++) { | ||
238 | size_t sz = cxt->record_size; | ||
239 | |||
240 | cxt->przs[i] = persistent_ram_new(*paddr, sz, cxt->ecc); | ||
241 | if (IS_ERR(cxt->przs[i])) { | ||
242 | err = PTR_ERR(cxt->przs[i]); | ||
243 | dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", | ||
244 | sz, (unsigned long long)*paddr, err); | ||
245 | goto fail_prz; | ||
246 | } | ||
247 | *paddr += sz; | ||
248 | } | ||
249 | |||
250 | return 0; | ||
251 | fail_prz: | ||
252 | ramoops_free_przs(cxt); | ||
253 | return err; | ||
254 | } | ||
255 | |||
205 | static int __init ramoops_probe(struct platform_device *pdev) | 256 | static int __init ramoops_probe(struct platform_device *pdev) |
206 | { | 257 | { |
207 | struct device *dev = &pdev->dev; | 258 | struct device *dev = &pdev->dev; |
208 | struct ramoops_platform_data *pdata = pdev->dev.platform_data; | 259 | struct ramoops_platform_data *pdata = pdev->dev.platform_data; |
209 | struct ramoops_context *cxt = &oops_cxt; | 260 | struct ramoops_context *cxt = &oops_cxt; |
261 | size_t dump_mem_sz; | ||
262 | phys_addr_t paddr; | ||
210 | int err = -EINVAL; | 263 | int err = -EINVAL; |
211 | int i; | ||
212 | 264 | ||
213 | /* Only a single ramoops area allowed at a time, so fail extra | 265 | /* Only a single ramoops area allowed at a time, so fail extra |
214 | * probes. | 266 | * probes. |
@@ -225,21 +277,6 @@ static int __init ramoops_probe(struct platform_device *pdev) | |||
225 | pdata->mem_size = rounddown_pow_of_two(pdata->mem_size); | 277 | pdata->mem_size = rounddown_pow_of_two(pdata->mem_size); |
226 | pdata->record_size = rounddown_pow_of_two(pdata->record_size); | 278 | pdata->record_size = rounddown_pow_of_two(pdata->record_size); |
227 | 279 | ||
228 | /* Check for the minimum memory size */ | ||
229 | if (pdata->mem_size < MIN_MEM_SIZE && | ||
230 | pdata->record_size < MIN_MEM_SIZE) { | ||
231 | pr_err("memory size too small, minimum is %lu\n", | ||
232 | MIN_MEM_SIZE); | ||
233 | goto fail_out; | ||
234 | } | ||
235 | |||
236 | if (pdata->mem_size < pdata->record_size) { | ||
237 | pr_err("The memory size must be larger than the " | ||
238 | "records size\n"); | ||
239 | goto fail_out; | ||
240 | } | ||
241 | |||
242 | cxt->max_dump_cnt = pdata->mem_size / pdata->record_size; | ||
243 | cxt->dump_read_cnt = 0; | 280 | cxt->dump_read_cnt = 0; |
244 | cxt->size = pdata->mem_size; | 281 | cxt->size = pdata->mem_size; |
245 | cxt->phys_addr = pdata->mem_address; | 282 | cxt->phys_addr = pdata->mem_address; |
@@ -247,24 +284,14 @@ static int __init ramoops_probe(struct platform_device *pdev) | |||
247 | cxt->dump_oops = pdata->dump_oops; | 284 | cxt->dump_oops = pdata->dump_oops; |
248 | cxt->ecc = pdata->ecc; | 285 | cxt->ecc = pdata->ecc; |
249 | 286 | ||
250 | cxt->przs = kzalloc(sizeof(*cxt->przs) * cxt->max_dump_cnt, GFP_KERNEL); | 287 | paddr = cxt->phys_addr; |
251 | if (!cxt->przs) { | ||
252 | err = -ENOMEM; | ||
253 | dev_err(dev, "failed to initialize a prz array\n"); | ||
254 | goto fail_out; | ||
255 | } | ||
256 | |||
257 | for (i = 0; i < cxt->max_dump_cnt; i++) { | ||
258 | size_t sz = cxt->record_size; | ||
259 | phys_addr_t start = cxt->phys_addr + sz * i; | ||
260 | 288 | ||
261 | cxt->przs[i] = persistent_ram_new(start, sz, cxt->ecc); | 289 | dump_mem_sz = cxt->size; |
262 | if (IS_ERR(cxt->przs[i])) { | 290 | err = ramoops_init_przs(dev, cxt, &paddr, dump_mem_sz); |
263 | err = PTR_ERR(cxt->przs[i]); | 291 | if (err) { |
264 | dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", | 292 | pr_err("memory size too small, minimum is %lu\n", |
265 | sz, (unsigned long long)start, err); | 293 | cxt->record_size); |
266 | goto fail_przs; | 294 | goto fail_count; |
267 | } | ||
268 | } | 295 | } |
269 | 296 | ||
270 | cxt->pstore.data = cxt; | 297 | cxt->pstore.data = cxt; |
@@ -303,10 +330,8 @@ fail_buf: | |||
303 | fail_clear: | 330 | fail_clear: |
304 | cxt->pstore.bufsize = 0; | 331 | cxt->pstore.bufsize = 0; |
305 | cxt->max_dump_cnt = 0; | 332 | cxt->max_dump_cnt = 0; |
306 | fail_przs: | 333 | fail_count: |
307 | for (i = 0; cxt->przs[i]; i++) | 334 | ramoops_free_przs(cxt); |
308 | persistent_ram_free(cxt->przs[i]); | ||
309 | kfree(cxt->przs); | ||
310 | fail_out: | 335 | fail_out: |
311 | return err; | 336 | return err; |
312 | } | 337 | } |