mtd: maps: physmap: Remove the MAX_RESOURCES limitation

Remove the MAX_RESOURCES limitation by dynamically allocating the
->mtds[] and ->maps[] at probe time based on the number of iomem
resources attached to the platform device.

Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Reviewed-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
Boris Brezillon 2018-10-19 09:48:59 +02:00
parent ea5bc54b12
commit 51b436a242
1 changed files with 27 additions and 17 deletions

View File

@ -22,12 +22,11 @@
#include <linux/mtd/concat.h> #include <linux/mtd/concat.h>
#include <linux/io.h> #include <linux/io.h>
#define MAX_RESOURCES 4
struct physmap_flash_info { struct physmap_flash_info {
struct mtd_info *mtds[MAX_RESOURCES]; unsigned int nmaps;
struct mtd_info **mtds;
struct mtd_info *cmtd; struct mtd_info *cmtd;
struct map_info maps[MAX_RESOURCES]; struct map_info *maps;
spinlock_t vpp_lock; spinlock_t vpp_lock;
int vpp_refcnt; int vpp_refcnt;
}; };
@ -50,7 +49,7 @@ static int physmap_flash_remove(struct platform_device *dev)
mtd_concat_destroy(info->cmtd); mtd_concat_destroy(info->cmtd);
} }
for (i = 0; i < MAX_RESOURCES; i++) { for (i = 0; i < info->nmaps; i++) {
if (info->mtds[i] != NULL) if (info->mtds[i] != NULL)
map_destroy(info->mtds[i]); map_destroy(info->mtds[i]);
} }
@ -101,7 +100,6 @@ static int physmap_flash_probe(struct platform_device *dev)
const char * const *part_types; const char * const *part_types;
int err = 0; int err = 0;
int i; int i;
int devices_found = 0;
physmap_data = dev_get_platdata(&dev->dev); physmap_data = dev_get_platdata(&dev->dev);
if (physmap_data == NULL) if (physmap_data == NULL)
@ -114,6 +112,24 @@ static int physmap_flash_probe(struct platform_device *dev)
goto err_out; goto err_out;
} }
while (platform_get_resource(dev, IORESOURCE_MEM, info->nmaps))
info->nmaps++;
if (!info->nmaps)
return -ENODEV;
info->maps = devm_kzalloc(&dev->dev,
sizeof(*info->maps) * info->nmaps,
GFP_KERNEL);
if (!info->maps)
return -ENOMEM;
info->mtds = devm_kzalloc(&dev->dev,
sizeof(*info->mtds) * info->nmaps,
GFP_KERNEL);
if (!info->mtds)
return -ENOMEM;
if (physmap_data->init) { if (physmap_data->init) {
err = physmap_data->init(dev); err = physmap_data->init(dev);
if (err) if (err)
@ -122,13 +138,10 @@ static int physmap_flash_probe(struct platform_device *dev)
platform_set_drvdata(dev, info); platform_set_drvdata(dev, info);
for (i = 0; i < MAX_RESOURCES; i++) { for (i = 0; i < info->nmaps; i++) {
struct resource *res; struct resource *res;
res = platform_get_resource(dev, IORESOURCE_MEM, i); res = platform_get_resource(dev, IORESOURCE_MEM, i);
if (!res)
break;
info->maps[i].virt = devm_ioremap_resource(&dev->dev, res); info->maps[i].virt = devm_ioremap_resource(&dev->dev, res);
if (IS_ERR(info->maps[i].virt)) { if (IS_ERR(info->maps[i].virt)) {
err = PTR_ERR(info->maps[i].virt); err = PTR_ERR(info->maps[i].virt);
@ -159,21 +172,18 @@ static int physmap_flash_probe(struct platform_device *dev)
dev_err(&dev->dev, "map_probe failed\n"); dev_err(&dev->dev, "map_probe failed\n");
err = -ENXIO; err = -ENXIO;
goto err_out; goto err_out;
} else {
devices_found++;
} }
info->mtds[i]->dev.parent = &dev->dev; info->mtds[i]->dev.parent = &dev->dev;
} }
if (!devices_found) { if (info->nmaps == 1) {
err = -ENODEV;
} else if (devices_found == 1) {
info->cmtd = info->mtds[0]; info->cmtd = info->mtds[0];
} else { } else {
/* /*
* We detected multiple devices. Concatenate them together. * We detected multiple devices. Concatenate them together.
*/ */
info->cmtd = mtd_concat_create(info->mtds, devices_found, dev_name(&dev->dev)); info->cmtd = mtd_concat_create(info->mtds, info->nmaps,
dev_name(&dev->dev));
if (info->cmtd == NULL) if (info->cmtd == NULL)
err = -ENXIO; err = -ENXIO;
} }
@ -199,7 +209,7 @@ static void physmap_flash_shutdown(struct platform_device *dev)
struct physmap_flash_info *info = platform_get_drvdata(dev); struct physmap_flash_info *info = platform_get_drvdata(dev);
int i; int i;
for (i = 0; i < MAX_RESOURCES && info->mtds[i]; i++) for (i = 0; i < info->nmaps && info->mtds[i]; i++)
if (mtd_suspend(info->mtds[i]) == 0) if (mtd_suspend(info->mtds[i]) == 0)
mtd_resume(info->mtds[i]); mtd_resume(info->mtds[i]);
} }