linux-sparse.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [linux-next:master] BUILD REGRESSION 736ee37e2e8eed7fe48d0a37ee5a709514d478b3
       [not found] ` <0530d502-1291-23f3-64ac-97bd38a26bd4@roeck-us.net>
@ 2022-05-20 12:40   ` Geert Uytterhoeven
  2022-05-20 12:46     ` Geert Uytterhoeven
                       ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Geert Uytterhoeven @ 2022-05-20 12:40 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: kernel test robot, Andrew Morton, linux-staging,
	open list:TI ETHERNET SWITCH DRIVER (CPSW),
	linux-nvme, linux-hwmon, Linux Fbdev development list, KVM list,
	DRI Development, amd-gfx list, Linux Memory Management List,
	Luc Van Oostenryck, linux-sparse, linux-m68k

Hi Günter

On Thu, May 19, 2022 at 8:48 AM Guenter Roeck <linux@roeck-us.net> wrote:
> On 5/18/22 17:55, kernel test robot wrote:
> > tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
> > branch HEAD: 736ee37e2e8eed7fe48d0a37ee5a709514d478b3  Add linux-next specific files for 20220518
> >
> > Error/Warning reports:
> >
> > https://lore.kernel.org/linux-mm/202204291924.vTGZmerI-lkp@intel.com
> > https://lore.kernel.org/linux-mm/202205041248.WgCwPcEV-lkp@intel.com
> > https://lore.kernel.org/linux-mm/202205122113.uLKzd3SZ-lkp@intel.com
> > https://lore.kernel.org/linux-mm/202205172344.3GFeaum1-lkp@intel.com
> > https://lore.kernel.org/linux-mm/202205190527.o9wVEvHI-lkp@intel.com
> >
> > Error/Warning: (recently discovered and may have been fixed)
> >
> [ .. ]
> > drivers/hwmon/nct6775-platform.c:199:9: sparse:    unsigned char
> > drivers/hwmon/nct6775-platform.c:199:9: sparse:    void
>
> This is getting tiresome. Every driver using outb() on m68k will
> experience that "problem". As far as I can see, it is caused by
>
> #define out_8(addr,b) (void)((*(__force volatile u8 *) (unsigned long)(addr)) = (b))
>
> in arch/m68k/include/asm/raw_io.h. I have no idea what the
> "(void)" is for,

The "(void)" makes sure there is no return value.
Which matters if the result of a function returning void is propagated
to another function returning void.

> but removing it "fixes" the problem.

This introduces new problems (m68k all{mod,yes}config):

    In file included from arch/m68k/include/asm/io_mm.h:25,
                     from arch/m68k/include/asm/io.h:8,
                     from include/linux/io.h:13,
                     from include/linux/of_address.h:7,
                     from drivers/gpu/drm/msm/adreno/adreno_gpu.c:13:
    drivers/gpu/drm/msm/adreno/a6xx_gmu.h: In function ‘gmu_write_rscc’:
    arch/m68k/include/asm/raw_io.h:34:80: error: ‘return’ with a
value, in function returning void [-Werror=return-type]
       34 | #define out_le32(addr,l) ((*(__force volatile __le32 *)
(unsigned long)(addr)) = cpu_to_le32(l))
          |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
    arch/m68k/include/asm/io_mm.h:397:26: note: in expansion of macro ‘out_le32’
      397 | #define writel(val,addr) out_le32((addr),(val))
          |                          ^~~~~~~~
    drivers/gpu/drm/msm/msm_drv.h:468:32: note: in expansion of macro ‘writel’
      468 | #define msm_writel(data, addr) writel((data), (addr))
          |                                ^~~~~~
    /drivers/gpu/drm/msm/adreno/a6xx_gmu.h:141:9: note: in expansion
of macro ‘msm_writel’
      141 |  return msm_writel(value, gmu->rscc + (offset << 2));
          |         ^~~~~~~~~~
    In file included from drivers/gpu/drm/msm/adreno/a6xx_gpu.h:11,
                     from drivers/gpu/drm/msm/adreno/adreno_gpu.c:20:
    drivers/gpu/drm/msm/adreno/a6xx_gmu.h:139:20: note: declared here
      139 | static inline void gmu_write_rscc(struct a6xx_gmu *gmu,
u32 offset, u32 value)
          |                    ^~~~~~~~~~~~~~

These can be fixed using e.g. (there are more in the Adreno driver):

     static inline void gmu_write(struct a6xx_gmu *gmu, u32 offset, u32 value)
     {
    -       return msm_writel(value, gmu->mmio + (offset << 2));
    +       msm_writel(value, gmu->mmio + (offset << 2));
     }

> Either case, this is not a problem with the nct6775 driver,
> nor is it a new problem.

Indeed.

For the sparse people:

The full error is:

        drivers/net/appletalk/cops.c:382:17: error: incompatible types
in conditional expression (different base types):
        drivers/net/appletalk/cops.c:382:17:    unsigned char
        drivers/net/appletalk/cops.c:382:17:    void

Basically, sparse doesn't like "a ? b : c", if the return types of
b and c don't match, even if the resulting value is not used.

E.g. outb() on m68k:

    #define outb(val, port) (((port) < 1024 && ISA_TYPE ==
ISA_TYPE_ENEC) ? isa_rom_outb((val), (port)) : isa_outb((val),
(port)))

where isa_rom_outb() leads to rom_out_8() returning u8, while
isa_outb() leads to the out_8() that includes the cast to void.

So the best solution seems to be to add more "(void)" casts, to e.g.
rom_out_8() and friends?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [linux-next:master] BUILD REGRESSION 736ee37e2e8eed7fe48d0a37ee5a709514d478b3
  2022-05-20 12:40   ` [linux-next:master] BUILD REGRESSION 736ee37e2e8eed7fe48d0a37ee5a709514d478b3 Geert Uytterhoeven
@ 2022-05-20 12:46     ` Geert Uytterhoeven
  2022-05-22 11:57       ` Luc Van Oostenryck
  2022-05-22 11:44     ` Luc Van Oostenryck
  2022-05-22 11:54     ` Christoph Hellwig
  2 siblings, 1 reply; 5+ messages in thread
From: Geert Uytterhoeven @ 2022-05-20 12:46 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: kernel test robot, Andrew Morton, linux-staging,
	open list:TI ETHERNET SWITCH DRIVER (CPSW),
	linux-nvme, linux-hwmon, Linux Fbdev development list, KVM list,
	DRI Development, amd-gfx list, Linux Memory Management List,
	Luc Van Oostenryck, linux-sparse, linux-m68k

On Fri, May 20, 2022 at 2:40 PM Geert Uytterhoeven <geert@linux-m68k.org> wrote:
> On Thu, May 19, 2022 at 8:48 AM Guenter Roeck <linux@roeck-us.net> wrote:
> > On 5/18/22 17:55, kernel test robot wrote:
> > > tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
> > > branch HEAD: 736ee37e2e8eed7fe48d0a37ee5a709514d478b3  Add linux-next specific files for 20220518
> > >
> > > Error/Warning reports:
> > >
> > > https://lore.kernel.org/linux-mm/202204291924.vTGZmerI-lkp@intel.com
> > > https://lore.kernel.org/linux-mm/202205041248.WgCwPcEV-lkp@intel.com
> > > https://lore.kernel.org/linux-mm/202205122113.uLKzd3SZ-lkp@intel.com
> > > https://lore.kernel.org/linux-mm/202205172344.3GFeaum1-lkp@intel.com
> > > https://lore.kernel.org/linux-mm/202205190527.o9wVEvHI-lkp@intel.com
> > >
> > > Error/Warning: (recently discovered and may have been fixed)
> > >
> > [ .. ]
> > > drivers/hwmon/nct6775-platform.c:199:9: sparse:    unsigned char
> > > drivers/hwmon/nct6775-platform.c:199:9: sparse:    void
> >
> > This is getting tiresome. Every driver using outb() on m68k will
> > experience that "problem". As far as I can see, it is caused by
> >
> > #define out_8(addr,b) (void)((*(__force volatile u8 *) (unsigned long)(addr)) = (b))
> >
> > in arch/m68k/include/asm/raw_io.h. I have no idea what the
> > "(void)" is for,
>
> The "(void)" makes sure there is no return value.
> Which matters if the result of a function returning void is propagated
> to another function returning void.

Which, FTR, sparse also doesn't like:

    error: return expression in void function

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [linux-next:master] BUILD REGRESSION 736ee37e2e8eed7fe48d0a37ee5a709514d478b3
  2022-05-20 12:40   ` [linux-next:master] BUILD REGRESSION 736ee37e2e8eed7fe48d0a37ee5a709514d478b3 Geert Uytterhoeven
  2022-05-20 12:46     ` Geert Uytterhoeven
@ 2022-05-22 11:44     ` Luc Van Oostenryck
  2022-05-22 11:54     ` Christoph Hellwig
  2 siblings, 0 replies; 5+ messages in thread
From: Luc Van Oostenryck @ 2022-05-22 11:44 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Guenter Roeck, kernel test robot, Andrew Morton, linux-staging,
	open list:TI ETHERNET SWITCH DRIVER (CPSW),
	linux-nvme, linux-hwmon, Linux Fbdev development list, KVM list,
	DRI Development, amd-gfx list, Linux Memory Management List,
	linux-sparse, linux-m68k

On Fri, May 20, 2022 at 02:40:20PM +0200, Geert Uytterhoeven wrote:
> Hi Günter
> 
> On Thu, May 19, 2022 at 8:48 AM Guenter Roeck <linux@roeck-us.net> wrote:
> > This is getting tiresome. Every driver using outb() on m68k will
> > experience that "problem". As far as I can see, it is caused by
> >
> > #define out_8(addr,b) (void)((*(__force volatile u8 *) (unsigned long)(addr)) = (b))

Not directly related to the root cause but the cast on the LHS is over-complex.
*) If the types are correct, 'addr' should always be a 'u8 __iomem *'. Casting
   it to an unsigned long will throw away all type checking: pointers of
   any size, of any address space, any kind of integer, any scalar value will
   be silently be accepted.
*) Then, when casting an integer to a pointer '__force' is unneeded because
   it's meaningless (because the integer has no type info about the pointee).

The most correct way to write the above would be:
	static inline void out_8(u8 __iomem *addr, ... b)
	{
		*((__force volatile u8 *)addr) = b;
	}
this way, you can typecheck 'addr' (but maybe it's the idea/the argument is
not always type clean?).
Otherwise, if the cast to unsigned long is kept, '__force' can be removed.
 
> 
> Indeed.
> 
> For the sparse people:
> 
> The full error is:
> 
>         drivers/net/appletalk/cops.c:382:17: error: incompatible types
> in conditional expression (different base types):
>         drivers/net/appletalk/cops.c:382:17:    unsigned char
>         drivers/net/appletalk/cops.c:382:17:    void
> 
> Basically, sparse doesn't like "a ? b : c", if the return types of
> b and c don't match, even if the resulting value is not used.

Well, you know that the motivation for sparse was to be stricter than GCC.
In this case it's simply what is required by the standard:
	    
    n1570 (C11) 6.5.15
	One of the following shall hold for the second and third operands:
	— both operands have arithmetic type;
	— both operands have the same structure or union type;
	— both operands have void type;
	— both operands are pointers to qualified or unqualified versions
          of compatible types;
	— one operand is a pointer and the other is a null pointer constant; or
	— one operand is a pointer to an object type and the other is a
          pointer to a qualified or unqualified version of void.

Also, yes, the type checking is independent from the fact of being used
or not (because the type of an expression must be know before any kind
of processing can be done on its value).

> E.g. outb() on m68k:
> 
>     #define outb(val, port) (((port) < 1024 && ISA_TYPE ==
> ISA_TYPE_ENEC) ? isa_rom_outb((val), (port)) : isa_outb((val),
> (port)))
> 
> where isa_rom_outb() leads to rom_out_8() returning u8, while
> isa_outb() leads to the out_8() that includes the cast to void.
> 
> So the best solution seems to be to add more "(void)" casts, to e.g.
> rom_out_8() and friends?

I kinda think so, yes (I suppose that rom_out_8() is never used as
returning a non-void value). But in truth, I think it's the excessive use
of relatively complex macros that is the real problem (an using a conditional
expression not for its value but for its side-effects). Can't outb() be
written as something like:
	static inline void outb(....) {
		if (port < 1024 && ISA_TYPE == ISA_TYPE_ENEC)
			isa_rom_outb(val, port);
		else
			isa_outb(val, port);
	}

With this you have better type checking, no trickery, no need for extra
casts, no problems with double evaluation, it's more readable (to me), ...
But yes, I suppose it's not really simple to convert all this. Sorry for
no being more helpful.

Best regards,
-- Luc

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [linux-next:master] BUILD REGRESSION 736ee37e2e8eed7fe48d0a37ee5a709514d478b3
  2022-05-20 12:40   ` [linux-next:master] BUILD REGRESSION 736ee37e2e8eed7fe48d0a37ee5a709514d478b3 Geert Uytterhoeven
  2022-05-20 12:46     ` Geert Uytterhoeven
  2022-05-22 11:44     ` Luc Van Oostenryck
@ 2022-05-22 11:54     ` Christoph Hellwig
  2 siblings, 0 replies; 5+ messages in thread
From: Christoph Hellwig @ 2022-05-22 11:54 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Guenter Roeck, kernel test robot, Andrew Morton, linux-staging,
	open list:TI ETHERNET SWITCH DRIVER (CPSW),
	linux-nvme, linux-hwmon, Linux Fbdev development list, KVM list,
	DRI Development, amd-gfx list, Linux Memory Management List,
	Luc Van Oostenryck, linux-sparse, linux-m68k

How about just turning the MMIO/PIO accessors on m68k into inline
functions as they are on most other architectures?

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [linux-next:master] BUILD REGRESSION 736ee37e2e8eed7fe48d0a37ee5a709514d478b3
  2022-05-20 12:46     ` Geert Uytterhoeven
@ 2022-05-22 11:57       ` Luc Van Oostenryck
  0 siblings, 0 replies; 5+ messages in thread
From: Luc Van Oostenryck @ 2022-05-22 11:57 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Guenter Roeck, kernel test robot, Andrew Morton, linux-staging,
	open list:TI ETHERNET SWITCH DRIVER (CPSW),
	linux-nvme, linux-hwmon, Linux Fbdev development list, KVM list,
	DRI Development, amd-gfx list, Linux Memory Management List,
	linux-sparse, linux-m68k

On Fri, May 20, 2022 at 02:46:20PM +0200, Geert Uytterhoeven wrote:
> > The "(void)" makes sure there is no return value.
> > Which matters if the result of a function returning void is propagated
> > to another function returning void.
> 
> Which, FTR, sparse also doesn't like:
> 
>     error: return expression in void function


You should get this message only if the expression is itself not void.
For example:
	$ cat test.c
	extern void fun(void);
	
	static void ko(int *ptr)
	{
		return *ptr;
	}
	
	static void ok1(int *ptr)
	{
		return (void) *ptr;
	}
	
	static void ok2(int *ptr)
	{
		return fun();
	}
	$ sparse test.c
	test.c:5:16: error: return expression in void function

IOW, sparse warn only for the ko() but not for ok1() or ok2().

If you have a case whee it s not the case, please send me the
pre-processed file and I'll be glad to investigate.

Best regards,
-- Luc

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-05-22 11:57 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <6285958d.+Z2aDZ4O1Y9eiazd%lkp@intel.com>
     [not found] ` <0530d502-1291-23f3-64ac-97bd38a26bd4@roeck-us.net>
2022-05-20 12:40   ` [linux-next:master] BUILD REGRESSION 736ee37e2e8eed7fe48d0a37ee5a709514d478b3 Geert Uytterhoeven
2022-05-20 12:46     ` Geert Uytterhoeven
2022-05-22 11:57       ` Luc Van Oostenryck
2022-05-22 11:44     ` Luc Van Oostenryck
2022-05-22 11:54     ` Christoph Hellwig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).