Message ID | 20200306021220.22097-9-digetx@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Introduce NVIDIA Tegra Partition Tablex | expand |
Hi Dmitry, I love your patch! Perhaps something to improve: [auto build test WARNING on tegra/for-next] [also build test WARNING on block/for-next linus/master v5.6-rc4 next-20200305] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982] url: https://github.com/0day-ci/linux/commits/Dmitry-Osipenko/Introduce-NVIDIA-Tegra-Partition-Tablex/20200306-124106 base: https://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git for-next reproduce: # apt-get install sparse # sparse version: v0.6.1-174-g094d5a94-dirty make ARCH=x86_64 allmodconfig make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' If you fix the issue, kindly add following tag Reported-by: kbuild test robot <lkp@intel.com> sparse warnings: (new ones prefixed by >>) >> block/partitions/tegra.c:491:53: sparse: sparse: Using plain integer as NULL pointer vim +491 block/partitions/tegra.c 488 489 int tegra_partition(struct parsed_partitions *state) 490 { > 491 struct tegra_partition_table_parser ptp = { 0 }; --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Hi Dmitry, I love your patch! Yet something to improve: [auto build test ERROR on tegra/for-next] [also build test ERROR on block/for-next linus/master v5.6-rc5 next-20200306] [cannot apply to ulf.hansson-mmc/next] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982] url: https://github.com/0day-ci/linux/commits/Dmitry-Osipenko/Introduce-NVIDIA-Tegra-Partition-Tablex/20200306-124106 base: https://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git for-next config: arm64-randconfig-a001-20200308 (attached as .config) compiler: aarch64-linux-gcc (GCC) 7.5.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree GCC_VERSION=7.5.0 make.cross ARCH=arm64 If you fix the issue, kindly add following tag Reported-by: kbuild test robot <lkp@intel.com> All errors (new ones prefixed by >>): block/partitions/tegra.o: In function `tegra_partition_table_emmc_boot_offset': block/partitions/tegra.c:379: undefined reference to `mmc_bdev_to_card' block/partitions/tegra.c:379:(.text+0x674): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `mmc_bdev_to_card' block/partitions/tegra.c:389: undefined reference to `mmc_card_is_blockaddr' block/partitions/tegra.c:389:(.text+0x6a4): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `mmc_card_is_blockaddr' >> block/partitions/tegra.c:424: undefined reference to `mmc_bdev_to_part_type' block/partitions/tegra.c:424:(.text+0x748): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `mmc_bdev_to_part_type' >> block/partitions/tegra.c:417: undefined reference to `mmc_bdev_to_area_type' block/partitions/tegra.c:417:(.text+0xbec): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `mmc_bdev_to_area_type' vim +424 block/partitions/tegra.c 375 376 static int 377 tegra_partition_table_emmc_boot_offset(struct tegra_partition_table_parser *ptp) 378 { 379 struct mmc_card *card = mmc_bdev_to_card(ptp->state->bdev); 380 const struct of_device_id *matched; 381 int part_type, area_type; 382 const u32 *sdhci_bases; 383 u32 sdhci_base; 384 unsigned int i; 385 int err; 386 387 /* filter out unexpected/untested boot sources */ 388 if (!card || card->ext_csd.rev < 3 || 389 !mmc_card_is_blockaddr(card) || 390 mmc_card_is_removable(card->host)) 391 return -1; 392 393 /* skip everything unrelated to Tegra eMMC */ 394 matched = of_match_node(tegra_sdhci_match, card->host->parent->of_node); 395 if (!matched) 396 return -1; 397 398 sdhci_bases = matched->data; 399 400 /* figure out SDHCI instance ID by the base address */ 401 err = of_property_read_u32_index(card->host->parent->of_node, 402 "reg", 0, &sdhci_base); 403 if (err) 404 return -1; 405 406 for (i = 0; i < TEGRA_PT_SDHCI_DEVICE_INSTANCES; i++) { 407 if (sdhci_base == sdhci_bases[i]) 408 break; 409 } 410 411 if (i == TEGRA_PT_SDHCI_DEVICE_INSTANCES) 412 return -1; 413 414 ptp->dev_id = TEGRA_PT_SDHCI_DEVICE_ID; 415 ptp->dev_instance = i; 416 > 417 area_type = mmc_bdev_to_area_type(ptp->state->bdev); 418 419 if (WARN_ON(area_type < 0)) 420 return -1; 421 422 switch (area_type) { 423 case MMC_BLK_DATA_AREA_BOOT: > 424 part_type = mmc_bdev_to_part_type(ptp->state->bdev); 425 426 if (WARN_ON(part_type < 0)) 427 return -1; 428 429 ptp->boot_id = part_type - EXT_CSD_PART_CONFIG_ACC_BOOT0; 430 ptp->snapshot_mode = true; 431 break; 432 433 case MMC_BLK_DATA_AREA_MAIN: 434 break; 435 436 default: 437 TEGRA_PT_ERR(ptp, "unexpected area_type: %u\n", area_type); 438 return -1; 439 } 440 441 ptp->card = card; 442 443 /* 444 * eMMC storage has two special boot partitions in addition to the 445 * main one. NVIDIA's bootloader linearizes eMMC boot0->boot1->main 446 * accesses, this means that the partition table addresses are shifted 447 * by the size of boot partitions. In accordance with the eMMC 448 * specification, the boot partition size is calculated as follows: 449 * 450 * boot partition size = 128K byte x BOOT_SIZE_MULT 451 * 452 * This function returns number of sectors occupied by the both boot 453 * partitions. 454 */ 455 return card->ext_csd.raw_boot_mult * SZ_128K / 456 SECTOR_SIZE * MMC_NUM_BOOT_PARTITION; 457 } 458 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/block/partitions/tegra.c b/block/partitions/tegra.c index 6f150a7e3275..153928eef60b 100644 --- a/block/partitions/tegra.c +++ b/block/partitions/tegra.c @@ -25,6 +25,7 @@ #include <linux/mmc/blkdev.h> #include <linux/mmc/card.h> #include <linux/mmc/host.h> +#include <linux/mmc/mmc.h> #include <soc/tegra/common.h> #include <soc/tegra/partition.h> @@ -50,7 +51,10 @@ struct tegra_partition_table_parser { struct tegra_partition_table *pt; struct parsed_partitions *state; + struct mmc_card *card; bool pt_entry_checked; + unsigned int boot_id; + bool snapshot_mode; sector_t sector; int boot_offset; u32 dev_instance; @@ -67,6 +71,7 @@ struct tegra_partition_type { char *name; }; +static struct tegra_partition_table *scratch_pt; static sector_t tegra_pt_sector_address; static sector_t tegra_pt_sectors_num; @@ -224,6 +229,10 @@ static bool tegra_partition_valid(struct tegra_partition_table_parser *ptp, return false; } + /* size will be validated when ptp->snapshot_mode=false */ + if (ptp->snapshot_mode && size) + return true; + sect_end = get_capacity(ptp->state->bdev->bd_disk); /* eMMC boot partitions are below ptp->boot_offset */ @@ -369,6 +378,7 @@ tegra_partition_table_emmc_boot_offset(struct tegra_partition_table_parser *ptp) { struct mmc_card *card = mmc_bdev_to_card(ptp->state->bdev); const struct of_device_id *matched; + int part_type, area_type; const u32 *sdhci_bases; u32 sdhci_base; unsigned int i; @@ -404,6 +414,32 @@ tegra_partition_table_emmc_boot_offset(struct tegra_partition_table_parser *ptp) ptp->dev_id = TEGRA_PT_SDHCI_DEVICE_ID; ptp->dev_instance = i; + area_type = mmc_bdev_to_area_type(ptp->state->bdev); + + if (WARN_ON(area_type < 0)) + return -1; + + switch (area_type) { + case MMC_BLK_DATA_AREA_BOOT: + part_type = mmc_bdev_to_part_type(ptp->state->bdev); + + if (WARN_ON(part_type < 0)) + return -1; + + ptp->boot_id = part_type - EXT_CSD_PART_CONFIG_ACC_BOOT0; + ptp->snapshot_mode = true; + break; + + case MMC_BLK_DATA_AREA_MAIN: + break; + + default: + TEGRA_PT_ERR(ptp, "unexpected area_type: %u\n", area_type); + return -1; + } + + ptp->card = card; + /* * eMMC storage has two special boot partitions in addition to the * main one. NVIDIA's bootloader linearizes eMMC boot0->boot1->main @@ -427,6 +463,9 @@ static int tegra_read_partition_table(struct tegra_partition_table_parser *ptp) Sector sect; void *part; + if (scratch_pt) + return 1; + for (i = 0; i < ARRAY_SIZE(ptu->pt_parts); i++) { /* * Partition table takes at maximum 4096 bytes, but @@ -449,29 +488,77 @@ static int tegra_read_partition_table(struct tegra_partition_table_parser *ptp) int tegra_partition(struct parsed_partitions *state) { - struct tegra_partition_table_parser ptp = { .state = state }; + struct tegra_partition_table_parser ptp = { 0 }; sector_t end_sector; int ret = 0; if (!soc_is_tegra()) return 0; + ptp.state = state; + ptp.boot_offset = tegra_partition_table_emmc_boot_offset(&ptp); if (ptp.boot_offset < 0) return 0; - if (tegra_pt_sector_address < ptp.boot_offset) { - TEGRA_PT_INFO(&ptp, - "scanning eMMC boot partitions unimplemented\n"); - return 0; - } + /* + * Some devices store partition table on boot MMC partition. + * In this case a "snapshot mode" will be used, which will + * only read->check->store partition table, the stored table + * will be used for the main MMC partition later on. + */ + if (ptp.snapshot_mode) { + sector_t boot_start, boot_end, boot_size; - ptp.pt = kmalloc(sizeof(*ptp.pt), GFP_KERNEL); - if (!ptp.pt) - return 0; + /* partition is already snapshoted, no need to proceed */ + if (scratch_pt) + return 0; + + boot_size = ptp.boot_offset / MMC_NUM_BOOT_PARTITION; + boot_start = ptp.boot_id * boot_size; + boot_end = boot_start + boot_size; + + /* + * Bail out if partition table isn't located here, at this MMC + * partition. + */ + if (tegra_pt_sector_address < boot_start || + tegra_pt_sector_address >= boot_end) + return 0; + + ptp.boot_offset = boot_start; + + /* + * Note that mmc_blk_probe() always registers boot partitions + * after the main and we rely on this feature, otherwise + * scratch_pt won't be released (although this is not a big + * deal). + */ + ptp.pt = kmalloc(sizeof(*ptp.pt), GFP_KERNEL); + if (!ptp.pt) + return 0; + + ptp.sector = tegra_pt_sector_address - ptp.boot_offset; + end_sector = ptp.sector + tegra_pt_sectors_num; - ptp.sector = tegra_pt_sector_address - ptp.boot_offset; - end_sector = ptp.sector + tegra_pt_sectors_num; + } else if (scratch_pt) { + TEGRA_PT_INFO(&ptp, "using stashed partition table\n"); + + ptp.pt = scratch_pt; + ptp.sector = 0; + end_sector = 1; + + } else { + if (tegra_pt_sector_address < ptp.boot_offset) + return 0; + + ptp.pt = kmalloc(sizeof(*ptp.pt), GFP_KERNEL); + if (!ptp.pt) + return 0; + + ptp.sector = tegra_pt_sector_address - ptp.boot_offset; + end_sector = ptp.sector + tegra_pt_sectors_num; + } /* * Partition table is duplicated till the end_sector. @@ -501,9 +588,20 @@ int tegra_partition(struct parsed_partitions *state) ptp.sector += TEGRA_PT_SECTOR_SZ; } - if (ret == 1) + if (ret == 1) { + if (ptp.snapshot_mode) { + ptp.card->quirks |= MMC_QUIRK_RESCAN_MAIN_BLKDEV; + scratch_pt = ptp.pt; + + TEGRA_PT_INFO(&ptp, "stashed partition table\n"); + + return 0; + } + strlcat(state->pp_buf, "\n", PAGE_SIZE); + } + scratch_pt = NULL; kfree(ptp.pt); return ret;
Some NVIDIA Tegra devices store partition table on eMMC boot partition. In order to support this case, the tegra-partition parser will read out partition table from a boot partition and stash it for the main eMMC partition. Signed-off-by: Dmitry Osipenko <digetx@gmail.com> --- block/partitions/tegra.c | 122 +++++++++++++++++++++++++++++++++++---- 1 file changed, 110 insertions(+), 12 deletions(-)