diff options
author | Miquel Raynal <miquel.raynal@bootlin.com> | 2018-07-25 09:31:51 -0400 |
---|---|---|
committer | Miquel Raynal <miquel.raynal@bootlin.com> | 2018-07-31 03:46:14 -0400 |
commit | 2023f1fa216f30b1877d65be2057fbaf0bbd49b3 (patch) | |
tree | 5d53702f9da4b77d8cfdd36e0bfb2b88aed18ea8 | |
parent | 98732da1a08ebb666983d469981a8b994e77d556 (diff) |
mtd: rawnand: allocate model parameter dynamically
Thanks to the migration of all drivers to use nand_scan() and the
related nand_controller_ops, we can now allocate data during the
detection phase. Let's do it first for the NAND model parameter which
is allocated in nand_detect().
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
-rw-r--r-- | drivers/mtd/nand/raw/nand_base.c | 52 | ||||
-rw-r--r-- | include/linux/mtd/rawnand.h | 2 |
2 files changed, 42 insertions, 12 deletions
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 34ea44f90fd8..00e80781124a 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c | |||
@@ -5225,8 +5225,11 @@ static int nand_flash_detect_onfi(struct nand_chip *chip) | |||
5225 | 5225 | ||
5226 | sanitize_string(p->manufacturer, sizeof(p->manufacturer)); | 5226 | sanitize_string(p->manufacturer, sizeof(p->manufacturer)); |
5227 | sanitize_string(p->model, sizeof(p->model)); | 5227 | sanitize_string(p->model, sizeof(p->model)); |
5228 | strncpy(chip->parameters.model, p->model, | 5228 | chip->parameters.model = kstrdup(p->model, GFP_KERNEL); |
5229 | sizeof(chip->parameters.model) - 1); | 5229 | if (!chip->parameters.model) { |
5230 | ret = -ENOMEM; | ||
5231 | goto free_onfi_param_page; | ||
5232 | } | ||
5230 | 5233 | ||
5231 | mtd->writesize = le32_to_cpu(p->byte_per_page); | 5234 | mtd->writesize = le32_to_cpu(p->byte_per_page); |
5232 | 5235 | ||
@@ -5356,8 +5359,11 @@ static int nand_flash_detect_jedec(struct nand_chip *chip) | |||
5356 | 5359 | ||
5357 | sanitize_string(p->manufacturer, sizeof(p->manufacturer)); | 5360 | sanitize_string(p->manufacturer, sizeof(p->manufacturer)); |
5358 | sanitize_string(p->model, sizeof(p->model)); | 5361 | sanitize_string(p->model, sizeof(p->model)); |
5359 | strncpy(chip->parameters.model, p->model, | 5362 | chip->parameters.model = kstrdup(p->model, GFP_KERNEL); |
5360 | sizeof(chip->parameters.model) - 1); | 5363 | if (!chip->parameters.model) { |
5364 | ret = -ENOMEM; | ||
5365 | goto free_jedec_param_page; | ||
5366 | } | ||
5361 | 5367 | ||
5362 | mtd->writesize = le32_to_cpu(p->byte_per_page); | 5368 | mtd->writesize = le32_to_cpu(p->byte_per_page); |
5363 | 5369 | ||
@@ -5546,8 +5552,9 @@ static bool find_full_id_nand(struct nand_chip *chip, | |||
5546 | chip->onfi_timing_mode_default = | 5552 | chip->onfi_timing_mode_default = |
5547 | type->onfi_timing_mode_default; | 5553 | type->onfi_timing_mode_default; |
5548 | 5554 | ||
5549 | strncpy(chip->parameters.model, type->name, | 5555 | chip->parameters.model = kstrdup(type->name, GFP_KERNEL); |
5550 | sizeof(chip->parameters.model) - 1); | 5556 | if (!chip->parameters.model) |
5557 | return false; | ||
5551 | 5558 | ||
5552 | return true; | 5559 | return true; |
5553 | } | 5560 | } |
@@ -5706,8 +5713,9 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) | |||
5706 | if (!type->name) | 5713 | if (!type->name) |
5707 | return -ENODEV; | 5714 | return -ENODEV; |
5708 | 5715 | ||
5709 | strncpy(chip->parameters.model, type->name, | 5716 | chip->parameters.model = kstrdup(type->name, GFP_KERNEL); |
5710 | sizeof(chip->parameters.model) - 1); | 5717 | if (!chip->parameters.model) |
5718 | return -ENOMEM; | ||
5711 | 5719 | ||
5712 | chip->chipsize = (uint64_t)type->chipsize << 20; | 5720 | chip->chipsize = (uint64_t)type->chipsize << 20; |
5713 | 5721 | ||
@@ -5737,7 +5745,9 @@ ident_done: | |||
5737 | mtd->name); | 5745 | mtd->name); |
5738 | pr_warn("bus width %d instead of %d bits\n", busw ? 16 : 8, | 5746 | pr_warn("bus width %d instead of %d bits\n", busw ? 16 : 8, |
5739 | (chip->options & NAND_BUSWIDTH_16) ? 16 : 8); | 5747 | (chip->options & NAND_BUSWIDTH_16) ? 16 : 8); |
5740 | return -EINVAL; | 5748 | ret = -EINVAL; |
5749 | |||
5750 | goto free_detect_allocation; | ||
5741 | } | 5751 | } |
5742 | 5752 | ||
5743 | nand_decode_bbm_options(chip); | 5753 | nand_decode_bbm_options(chip); |
@@ -5774,6 +5784,11 @@ ident_done: | |||
5774 | (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC", | 5784 | (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC", |
5775 | mtd->erasesize >> 10, mtd->writesize, mtd->oobsize); | 5785 | mtd->erasesize >> 10, mtd->writesize, mtd->oobsize); |
5776 | return 0; | 5786 | return 0; |
5787 | |||
5788 | free_detect_allocation: | ||
5789 | kfree(chip->parameters.model); | ||
5790 | |||
5791 | return ret; | ||
5777 | } | 5792 | } |
5778 | 5793 | ||
5779 | static const char * const nand_ecc_modes[] = { | 5794 | static const char * const nand_ecc_modes[] = { |
@@ -6013,6 +6028,11 @@ static int nand_scan_ident(struct mtd_info *mtd, int maxchips, | |||
6013 | return 0; | 6028 | return 0; |
6014 | } | 6029 | } |
6015 | 6030 | ||
6031 | static void nand_scan_ident_cleanup(struct nand_chip *chip) | ||
6032 | { | ||
6033 | kfree(chip->parameters.model); | ||
6034 | } | ||
6035 | |||
6016 | static int nand_set_ecc_soft_ops(struct mtd_info *mtd) | 6036 | static int nand_set_ecc_soft_ops(struct mtd_info *mtd) |
6017 | { | 6037 | { |
6018 | struct nand_chip *chip = mtd_to_nand(mtd); | 6038 | struct nand_chip *chip = mtd_to_nand(mtd); |
@@ -6760,11 +6780,18 @@ int nand_scan_with_ids(struct mtd_info *mtd, int maxchips, | |||
6760 | 6780 | ||
6761 | ret = nand_attach(chip); | 6781 | ret = nand_attach(chip); |
6762 | if (ret) | 6782 | if (ret) |
6763 | return ret; | 6783 | goto cleanup_ident; |
6764 | 6784 | ||
6765 | ret = nand_scan_tail(mtd); | 6785 | ret = nand_scan_tail(mtd); |
6766 | if (ret) | 6786 | if (ret) |
6767 | nand_detach(chip); | 6787 | goto detach_chip; |
6788 | |||
6789 | return 0; | ||
6790 | |||
6791 | detach_chip: | ||
6792 | nand_detach(chip); | ||
6793 | cleanup_ident: | ||
6794 | nand_scan_ident_cleanup(chip); | ||
6768 | 6795 | ||
6769 | return ret; | 6796 | return ret; |
6770 | } | 6797 | } |
@@ -6796,6 +6823,9 @@ void nand_cleanup(struct nand_chip *chip) | |||
6796 | 6823 | ||
6797 | /* Free controller specific allocations after chip identification */ | 6824 | /* Free controller specific allocations after chip identification */ |
6798 | nand_detach(chip); | 6825 | nand_detach(chip); |
6826 | |||
6827 | /* Free identification phase allocations */ | ||
6828 | nand_scan_ident_cleanup(chip); | ||
6799 | } | 6829 | } |
6800 | 6830 | ||
6801 | EXPORT_SYMBOL_GPL(nand_cleanup); | 6831 | EXPORT_SYMBOL_GPL(nand_cleanup); |
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 71571ed23a20..099fa166569a 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h | |||
@@ -476,7 +476,7 @@ struct onfi_params { | |||
476 | */ | 476 | */ |
477 | struct nand_parameters { | 477 | struct nand_parameters { |
478 | /* Generic parameters */ | 478 | /* Generic parameters */ |
479 | char model[100]; | 479 | const char *model; |
480 | bool supports_set_get_features; | 480 | bool supports_set_get_features; |
481 | DECLARE_BITMAP(set_feature_list, ONFI_FEATURE_NUMBER); | 481 | DECLARE_BITMAP(set_feature_list, ONFI_FEATURE_NUMBER); |
482 | DECLARE_BITMAP(get_feature_list, ONFI_FEATURE_NUMBER); | 482 | DECLARE_BITMAP(get_feature_list, ONFI_FEATURE_NUMBER); |