2019-02-20 05:58:56

by Masahiro Yamada

[permalink] [raw]
Subject: [PATCH v2] powerpc/prom_init: add __init markers to all functions

It is fragile to rely on the compiler's optimization to avoid the
section mismatch. Some functions may not be necessarily inlined
when the compiler's inlining heuristic changes.

Add __init markers consistently.

As for prom_getprop() and prom_getproplen(), they are marked as
'inline', so inlining is guaranteed because PowerPC never enables
CONFIG_OPTIMIZE_INLINING. However, it would be better to leave the
inlining decision to the compiler. I replaced 'inline' with __init.
I added __maybe_unused to prom_getproplen() because it is currently
relying on the side-effect of 'inline'; GCC does not report
-Wunused-function warnings for functions with 'inline' marker.

Signed-off-by: Masahiro Yamada <[email protected]>
---

Changes in v2:
- Add __maybe_unsed to prom_getproplen()
- Add __init to enter_prom() as well

arch/powerpc/kernel/prom_init.c | 29 +++++++++++++++--------------
1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index f33ff41..1bad0ac 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -138,9 +138,9 @@ extern void __start(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r9);

#ifdef CONFIG_PPC64
-extern int enter_prom(struct prom_args *args, unsigned long entry);
+extern int __init enter_prom(struct prom_args *args, unsigned long entry);
#else
-static inline int enter_prom(struct prom_args *args, unsigned long entry)
+static int __init enter_prom(struct prom_args *args, unsigned long entry)
{
return ((int (*)(struct prom_args *))entry)(args);
}
@@ -501,19 +501,20 @@ static int __init prom_next_node(phandle *nodep)
}
}

-static inline int prom_getprop(phandle node, const char *pname,
+static int __init prom_getprop(phandle node, const char *pname,
void *value, size_t valuelen)
{
return call_prom("getprop", 4, 1, node, ADDR(pname),
(u32)(unsigned long) value, (u32) valuelen);
}

-static inline int prom_getproplen(phandle node, const char *pname)
+static int __init __maybe_unused prom_getproplen(phandle node,
+ const char *pname)
{
return call_prom("getproplen", 2, 1, node, ADDR(pname));
}

-static void add_string(char **str, const char *q)
+static void __init add_string(char **str, const char *q)
{
char *p = *str;

@@ -523,7 +524,7 @@ static void add_string(char **str, const char *q)
*str = p;
}

-static char *tohex(unsigned int x)
+static char __init *tohex(unsigned int x)
{
static const char digits[] __initconst = "0123456789abcdef";
static char result[9] __prombss;
@@ -570,7 +571,7 @@ static int __init prom_setprop(phandle node, const char *nodename,
#define islower(c) ('a' <= (c) && (c) <= 'z')
#define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))

-static unsigned long prom_strtoul(const char *cp, const char **endp)
+static unsigned long __init prom_strtoul(const char *cp, const char **endp)
{
unsigned long result = 0, base = 10, value;

@@ -595,7 +596,7 @@ static unsigned long prom_strtoul(const char *cp, const char **endp)
return result;
}

-static unsigned long prom_memparse(const char *ptr, const char **retptr)
+static unsigned long __init prom_memparse(const char *ptr, const char **retptr)
{
unsigned long ret = prom_strtoul(ptr, retptr);
int shift = 0;
@@ -2924,7 +2925,7 @@ static void __init fixup_device_tree_pasemi(void)
prom_setprop(iob, name, "device_type", "isa", sizeof("isa"));
}
#else /* !CONFIG_PPC_PASEMI_NEMO */
-static inline void fixup_device_tree_pasemi(void) { }
+static void __init fixup_device_tree_pasemi(void) { }
#endif

static void __init fixup_device_tree(void)
@@ -2986,15 +2987,15 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4)

#ifdef CONFIG_PPC64
#ifdef CONFIG_RELOCATABLE
-static void reloc_toc(void)
+static void __init reloc_toc(void)
{
}

-static void unreloc_toc(void)
+static void __init unreloc_toc(void)
{
}
#else
-static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
+static void __init __reloc_toc(unsigned long offset, unsigned long nr_entries)
{
unsigned long i;
unsigned long *toc_entry;
@@ -3008,7 +3009,7 @@ static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
}
}

-static void reloc_toc(void)
+static void __init reloc_toc(void)
{
unsigned long offset = reloc_offset();
unsigned long nr_entries =
@@ -3019,7 +3020,7 @@ static void reloc_toc(void)
mb();
}

-static void unreloc_toc(void)
+static void __init unreloc_toc(void)
{
unsigned long offset = reloc_offset();
unsigned long nr_entries =
--
2.7.4



2019-02-20 06:55:12

by Christophe Leroy

[permalink] [raw]
Subject: Re: [PATCH v2] powerpc/prom_init: add __init markers to all functions



Le 20/02/2019 à 06:53, Masahiro Yamada a écrit :
> It is fragile to rely on the compiler's optimization to avoid the
> section mismatch. Some functions may not be necessarily inlined
> when the compiler's inlining heuristic changes.
>
> Add __init markers consistently.
>
> As for prom_getprop() and prom_getproplen(), they are marked as
> 'inline', so inlining is guaranteed because PowerPC never enables
> CONFIG_OPTIMIZE_INLINING. However, it would be better to leave the
> inlining decision to the compiler. I replaced 'inline' with __init.
> I added __maybe_unused to prom_getproplen() because it is currently
> relying on the side-effect of 'inline'; GCC does not report
> -Wunused-function warnings for functions with 'inline' marker.

__maybe_unused is really a bad trick that should be avoided, as it hides
unused functions.

Why is it a problem to keep prom_getproplen() as 'static inline' ? Most
small helpers are defined that way. Usually they are in an included
header file, but what's really the problem with having it here directly ?

Christophe

>
> Signed-off-by: Masahiro Yamada <[email protected]>
> ---
>
> Changes in v2:
> - Add __maybe_unsed to prom_getproplen()
> - Add __init to enter_prom() as well
>
> arch/powerpc/kernel/prom_init.c | 29 +++++++++++++++--------------
> 1 file changed, 15 insertions(+), 14 deletions(-)
>
> diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
> index f33ff41..1bad0ac 100644
> --- a/arch/powerpc/kernel/prom_init.c
> +++ b/arch/powerpc/kernel/prom_init.c
> @@ -138,9 +138,9 @@ extern void __start(unsigned long r3, unsigned long r4, unsigned long r5,
> unsigned long r9);
>
> #ifdef CONFIG_PPC64
> -extern int enter_prom(struct prom_args *args, unsigned long entry);
> +extern int __init enter_prom(struct prom_args *args, unsigned long entry);
> #else
> -static inline int enter_prom(struct prom_args *args, unsigned long entry)
> +static int __init enter_prom(struct prom_args *args, unsigned long entry)
> {
> return ((int (*)(struct prom_args *))entry)(args);
> }
> @@ -501,19 +501,20 @@ static int __init prom_next_node(phandle *nodep)
> }
> }
>
> -static inline int prom_getprop(phandle node, const char *pname,
> +static int __init prom_getprop(phandle node, const char *pname,
> void *value, size_t valuelen)
> {
> return call_prom("getprop", 4, 1, node, ADDR(pname),
> (u32)(unsigned long) value, (u32) valuelen);
> }
>
> -static inline int prom_getproplen(phandle node, const char *pname)
> +static int __init __maybe_unused prom_getproplen(phandle node,
> + const char *pname)
> {
> return call_prom("getproplen", 2, 1, node, ADDR(pname));
> }
>
> -static void add_string(char **str, const char *q)
> +static void __init add_string(char **str, const char *q)
> {
> char *p = *str;
>
> @@ -523,7 +524,7 @@ static void add_string(char **str, const char *q)
> *str = p;
> }
>
> -static char *tohex(unsigned int x)
> +static char __init *tohex(unsigned int x)
> {
> static const char digits[] __initconst = "0123456789abcdef";
> static char result[9] __prombss;
> @@ -570,7 +571,7 @@ static int __init prom_setprop(phandle node, const char *nodename,
> #define islower(c) ('a' <= (c) && (c) <= 'z')
> #define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
>
> -static unsigned long prom_strtoul(const char *cp, const char **endp)
> +static unsigned long __init prom_strtoul(const char *cp, const char **endp)
> {
> unsigned long result = 0, base = 10, value;
>
> @@ -595,7 +596,7 @@ static unsigned long prom_strtoul(const char *cp, const char **endp)
> return result;
> }
>
> -static unsigned long prom_memparse(const char *ptr, const char **retptr)
> +static unsigned long __init prom_memparse(const char *ptr, const char **retptr)
> {
> unsigned long ret = prom_strtoul(ptr, retptr);
> int shift = 0;
> @@ -2924,7 +2925,7 @@ static void __init fixup_device_tree_pasemi(void)
> prom_setprop(iob, name, "device_type", "isa", sizeof("isa"));
> }
> #else /* !CONFIG_PPC_PASEMI_NEMO */
> -static inline void fixup_device_tree_pasemi(void) { }
> +static void __init fixup_device_tree_pasemi(void) { }
> #endif
>
> static void __init fixup_device_tree(void)
> @@ -2986,15 +2987,15 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
>
> #ifdef CONFIG_PPC64
> #ifdef CONFIG_RELOCATABLE
> -static void reloc_toc(void)
> +static void __init reloc_toc(void)
> {
> }
>
> -static void unreloc_toc(void)
> +static void __init unreloc_toc(void)
> {
> }
> #else
> -static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
> +static void __init __reloc_toc(unsigned long offset, unsigned long nr_entries)
> {
> unsigned long i;
> unsigned long *toc_entry;
> @@ -3008,7 +3009,7 @@ static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
> }
> }
>
> -static void reloc_toc(void)
> +static void __init reloc_toc(void)
> {
> unsigned long offset = reloc_offset();
> unsigned long nr_entries =
> @@ -3019,7 +3020,7 @@ static void reloc_toc(void)
> mb();
> }
>
> -static void unreloc_toc(void)
> +static void __init unreloc_toc(void)
> {
> unsigned long offset = reloc_offset();
> unsigned long nr_entries =
>

2019-02-21 00:28:12

by Daniel Axtens

[permalink] [raw]
Subject: Re: [PATCH v2] powerpc/prom_init: add __init markers to all functions

Hi Masahiro,

> It is fragile to rely on the compiler's optimization to avoid the
> section mismatch. Some functions may not be necessarily inlined
> when the compiler's inlining heuristic changes.
>
> Add __init markers consistently.
>

Are you doing this with some sort of static analysis, or manually?

Regards,
Daniel

> As for prom_getprop() and prom_getproplen(), they are marked as
> 'inline', so inlining is guaranteed because PowerPC never enables
> CONFIG_OPTIMIZE_INLINING. However, it would be better to leave the
> inlining decision to the compiler. I replaced 'inline' with __init.
> I added __maybe_unused to prom_getproplen() because it is currently
> relying on the side-effect of 'inline'; GCC does not report
> -Wunused-function warnings for functions with 'inline' marker.
>
> Signed-off-by: Masahiro Yamada <[email protected]>
> ---
>
> Changes in v2:
> - Add __maybe_unsed to prom_getproplen()
> - Add __init to enter_prom() as well
>
> arch/powerpc/kernel/prom_init.c | 29 +++++++++++++++--------------
> 1 file changed, 15 insertions(+), 14 deletions(-)
>
> diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
> index f33ff41..1bad0ac 100644
> --- a/arch/powerpc/kernel/prom_init.c
> +++ b/arch/powerpc/kernel/prom_init.c
> @@ -138,9 +138,9 @@ extern void __start(unsigned long r3, unsigned long r4, unsigned long r5,
> unsigned long r9);
>
> #ifdef CONFIG_PPC64
> -extern int enter_prom(struct prom_args *args, unsigned long entry);
> +extern int __init enter_prom(struct prom_args *args, unsigned long entry);
> #else
> -static inline int enter_prom(struct prom_args *args, unsigned long entry)
> +static int __init enter_prom(struct prom_args *args, unsigned long entry)
> {
> return ((int (*)(struct prom_args *))entry)(args);
> }
> @@ -501,19 +501,20 @@ static int __init prom_next_node(phandle *nodep)
> }
> }
>
> -static inline int prom_getprop(phandle node, const char *pname,
> +static int __init prom_getprop(phandle node, const char *pname,
> void *value, size_t valuelen)
> {
> return call_prom("getprop", 4, 1, node, ADDR(pname),
> (u32)(unsigned long) value, (u32) valuelen);
> }
>
> -static inline int prom_getproplen(phandle node, const char *pname)
> +static int __init __maybe_unused prom_getproplen(phandle node,
> + const char *pname)
> {
> return call_prom("getproplen", 2, 1, node, ADDR(pname));
> }
>
> -static void add_string(char **str, const char *q)
> +static void __init add_string(char **str, const char *q)
> {
> char *p = *str;
>
> @@ -523,7 +524,7 @@ static void add_string(char **str, const char *q)
> *str = p;
> }
>
> -static char *tohex(unsigned int x)
> +static char __init *tohex(unsigned int x)
> {
> static const char digits[] __initconst = "0123456789abcdef";
> static char result[9] __prombss;
> @@ -570,7 +571,7 @@ static int __init prom_setprop(phandle node, const char *nodename,
> #define islower(c) ('a' <= (c) && (c) <= 'z')
> #define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
>
> -static unsigned long prom_strtoul(const char *cp, const char **endp)
> +static unsigned long __init prom_strtoul(const char *cp, const char **endp)
> {
> unsigned long result = 0, base = 10, value;
>
> @@ -595,7 +596,7 @@ static unsigned long prom_strtoul(const char *cp, const char **endp)
> return result;
> }
>
> -static unsigned long prom_memparse(const char *ptr, const char **retptr)
> +static unsigned long __init prom_memparse(const char *ptr, const char **retptr)
> {
> unsigned long ret = prom_strtoul(ptr, retptr);
> int shift = 0;
> @@ -2924,7 +2925,7 @@ static void __init fixup_device_tree_pasemi(void)
> prom_setprop(iob, name, "device_type", "isa", sizeof("isa"));
> }
> #else /* !CONFIG_PPC_PASEMI_NEMO */
> -static inline void fixup_device_tree_pasemi(void) { }
> +static void __init fixup_device_tree_pasemi(void) { }
> #endif
>
> static void __init fixup_device_tree(void)
> @@ -2986,15 +2987,15 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
>
> #ifdef CONFIG_PPC64
> #ifdef CONFIG_RELOCATABLE
> -static void reloc_toc(void)
> +static void __init reloc_toc(void)
> {
> }
>
> -static void unreloc_toc(void)
> +static void __init unreloc_toc(void)
> {
> }
> #else
> -static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
> +static void __init __reloc_toc(unsigned long offset, unsigned long nr_entries)
> {
> unsigned long i;
> unsigned long *toc_entry;
> @@ -3008,7 +3009,7 @@ static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
> }
> }
>
> -static void reloc_toc(void)
> +static void __init reloc_toc(void)
> {
> unsigned long offset = reloc_offset();
> unsigned long nr_entries =
> @@ -3019,7 +3020,7 @@ static void reloc_toc(void)
> mb();
> }
>
> -static void unreloc_toc(void)
> +static void __init unreloc_toc(void)
> {
> unsigned long offset = reloc_offset();
> unsigned long nr_entries =
> --
> 2.7.4