Commit 596fd46268634082314b3af1ded4612e1b7f3f03
Committed by
David Woodhouse
1 parent
021796b892
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
mtd: nandsim: don't open code a do_div helper
We don't need to open code the divide function, just use div_u64 that already exists and do the same job. While this is a straightforward clean up, there is more to that, the real motivation for this. While building on a cross compiling environment in armel, using gcc 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5), I was getting the following build error: ERROR: "__aeabi_uldivmod" [drivers/mtd/nand/nandsim.ko] undefined! After investigating with objdump and hand built assembly version generated with the compiler, I narrowed __aeabi_uldivmod as being generated from the divide function. When nandsim.c is built with -fno-inline-functions-called-once, that happens when CONFIG_DEBUG_SECTION_MISMATCH is enabled, the do_div optimization in arch/arm/include/asm/div64.h doesn't work as expected with the open coded divide function: even if the do_div we are using doesn't have a constant divisor, the compiler still includes the else parts of the optimized do_div macro, and translates the divisions there to use __aeabi_uldivmod, instead of only calling __do_div_asm -> __do_div64 and optimizing/removing everything else out. So to reproduce, gcc 4.6 plus CONFIG_DEBUG_SECTION_MISMATCH=y and CONFIG_MTD_NAND_NANDSIM=m should do it, building on armel. After this change, the compiler does the intended thing even with -fno-inline-functions-called-once, and optimizes out as expected the constant handling in the optimized do_div on arm. As this also avoids a build issue, I'm marking for Stable, as I think is applicable for this case. Signed-off-by: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com> Cc: stable@vger.kernel.org Acked-by: Nicolas Pitre <nico@linaro.org> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Showing 1 changed file with 3 additions and 9 deletions Side-by-side Diff
drivers/mtd/nand/nandsim.c
... | ... | @@ -28,7 +28,7 @@ |
28 | 28 | #include <linux/module.h> |
29 | 29 | #include <linux/moduleparam.h> |
30 | 30 | #include <linux/vmalloc.h> |
31 | -#include <asm/div64.h> | |
31 | +#include <linux/math64.h> | |
32 | 32 | #include <linux/slab.h> |
33 | 33 | #include <linux/errno.h> |
34 | 34 | #include <linux/string.h> |
... | ... | @@ -546,12 +546,6 @@ |
546 | 546 | return kstrdup(buf, GFP_KERNEL); |
547 | 547 | } |
548 | 548 | |
549 | -static uint64_t divide(uint64_t n, uint32_t d) | |
550 | -{ | |
551 | - do_div(n, d); | |
552 | - return n; | |
553 | -} | |
554 | - | |
555 | 549 | /* |
556 | 550 | * Initialize the nandsim structure. |
557 | 551 | * |
... | ... | @@ -580,7 +574,7 @@ |
580 | 574 | ns->geom.oobsz = mtd->oobsize; |
581 | 575 | ns->geom.secsz = mtd->erasesize; |
582 | 576 | ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz; |
583 | - ns->geom.pgnum = divide(ns->geom.totsz, ns->geom.pgsz); | |
577 | + ns->geom.pgnum = div_u64(ns->geom.totsz, ns->geom.pgsz); | |
584 | 578 | ns->geom.totszoob = ns->geom.totsz + (uint64_t)ns->geom.pgnum * ns->geom.oobsz; |
585 | 579 | ns->geom.secshift = ffs(ns->geom.secsz) - 1; |
586 | 580 | ns->geom.pgshift = chip->page_shift; |
... | ... | @@ -921,7 +915,7 @@ |
921 | 915 | |
922 | 916 | if (!rptwear) |
923 | 917 | return 0; |
924 | - wear_eb_count = divide(mtd->size, mtd->erasesize); | |
918 | + wear_eb_count = div_u64(mtd->size, mtd->erasesize); | |
925 | 919 | mem = wear_eb_count * sizeof(unsigned long); |
926 | 920 | if (mem / sizeof(unsigned long) != wear_eb_count) { |
927 | 921 | NS_ERR("Too many erase blocks for wear reporting\n"); |