| From foo@baz Sun Jun 17 12:07:34 CEST 2018 |
| From: Geert Uytterhoeven <geert@linux-m68k.org> |
| Date: Mon, 14 May 2018 12:49:37 +0200 |
| Subject: mtd: rawnand: Fix return type of __DIVIDE() when called with 32-bit |
| |
| From: Geert Uytterhoeven <geert@linux-m68k.org> |
| |
| [ Upstream commit 9f825e74d761c13b0cfaa5f65344d64ff970e252 ] |
| |
| The __DIVIDE() macro checks whether it is called with a 32-bit or 64-bit |
| dividend, to select the appropriate divide-and-round-up routine. |
| As the check uses the ternary operator, the result will always be |
| promoted to a type that can hold both results, i.e. unsigned long long. |
| |
| When using this result in a division on a 32-bit system, this may lead |
| to link errors like: |
| |
| ERROR: "__udivdi3" [drivers/mtd/nand/raw/nand.ko] undefined! |
| |
| Fix this by casting the result of the division to the type of the |
| dividend. |
| |
| Fixes: 8878b126df769831 ("mtd: nand: add ->exec_op() implementation") |
| Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> |
| Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| include/linux/mtd/rawnand.h | 16 +++++++++++----- |
| 1 file changed, 11 insertions(+), 5 deletions(-) |
| |
| --- a/include/linux/mtd/rawnand.h |
| +++ b/include/linux/mtd/rawnand.h |
| @@ -824,12 +824,18 @@ struct nand_op_instr { |
| * tBERS (during an erase) which all of them are u64 values that cannot be |
| * divided by usual kernel macros and must be handled with the special |
| * DIV_ROUND_UP_ULL() macro. |
| + * |
| + * Cast to type of dividend is needed here to guarantee that the result won't |
| + * be an unsigned long long when the dividend is an unsigned long (or smaller), |
| + * which is what the compiler does when it sees ternary operator with 2 |
| + * different return types (picks the largest type to make sure there's no |
| + * loss). |
| */ |
| -#define __DIVIDE(dividend, divisor) ({ \ |
| - sizeof(dividend) == sizeof(u32) ? \ |
| - DIV_ROUND_UP(dividend, divisor) : \ |
| - DIV_ROUND_UP_ULL(dividend, divisor); \ |
| - }) |
| +#define __DIVIDE(dividend, divisor) ({ \ |
| + (__typeof__(dividend))(sizeof(dividend) <= sizeof(unsigned long) ? \ |
| + DIV_ROUND_UP(dividend, divisor) : \ |
| + DIV_ROUND_UP_ULL(dividend, divisor)); \ |
| + }) |
| #define PSEC_TO_NSEC(x) __DIVIDE(x, 1000) |
| #define PSEC_TO_MSEC(x) __DIVIDE(x, 1000000000) |
| |