Re: [PATCH v2 2/3] counter: 104-quad-8: Refactor to buffer states for CMR, IOR, and IDR

From: William Breathitt Gray
Date: Fri Mar 24 2023 - 11:35:36 EST


On Fri, Mar 24, 2023 at 03:48:19PM +0200, Andy Shevchenko wrote:
> On Fri, Mar 24, 2023 at 09:26:14AM -0400, William Breathitt Gray wrote:
> > On Fri, Mar 24, 2023 at 01:50:07PM +0200, Andy Shevchenko wrote:
> > > On Fri, Mar 24, 2023 at 01:48:43PM +0200, Andy Shevchenko wrote:
> > > > On Thu, Mar 23, 2023 at 05:25:28PM -0400, William Breathitt Gray wrote:
>
> ...
>
> > > > > +static void quad8_control_register_update(struct quad8 *const priv, u8 *const buf,
> > > > > + const size_t channel, const u8 val, const u8 field)
> > > > > +{
> > > > > + u8p_replace_bits(&buf[channel], val, field);
> > > > > + iowrite8(buf[channel], &priv->reg->channel[channel].control);
> > > > > +}
> > > >
> > > > How did you compile this?
> > > > Due to nature of *_replace_bits() this may only be a macro.
> > > >
> > > > That's what LKP is telling about I think.
> > >
> > > Ah, no, that's because the last parameter is not constant in the last patch in
> > > the series.
>
> > I'm having trouble cross-compiling for riscv, but I'm unable to recreate
> > the build error when I compile for x86_64. However, I'd like to
> > understand this error so I can fix it properly.
> >
> > Is the problem here due to the "const u8 field" parameter? Instead of a
> > constant variable, does this need to be a constant literal value for
> > u8p_replace_bits()? I don't think that parameter changed in the last
> > patch of the series, so why is the build error occurring for the last
> > patch and not this penultimate patch here?
>
> Good question. Perhaps my understanding is incorrect.
>
> > Would qualifying the
> > quad8_control_register_update() function with "__always_inline" resolve
> > this issue?
>
> Hmm... Don't know. You can always download a toolchain specifically build for
> building kernels: https://mirrors.edge.kernel.org/pub/tools/crosstool/.
>
> --
> With Best Regards,
> Andy Shevchenko
>
>

I tried to build using crosstools, so I followed the reproduce sequence
from the kernel test robot message: download make.cross, fetch branch
and checkout commit, and then I executed the following (I'm on an arm64
system):

URL=https://cdn.kernel.org/pub/tools/crosstool/files/bin/arm64 COMPILER_INSTALL_PATH=$HOME/Projects/Linux/testwilliam/0day COMPILER=gcc-12.1.0 ../make.cross W=1 O=build_dir ARCH=riscv olddefconfig
URL=https://cdn.kernel.org/pub/tools/crosstool/files/bin/arm64 COMPILER_INSTALL_PATH=$HOME/Projects/Linux/testwilliam/0day COMPILER=gcc-12.1.0 ../make.cross W=1 O=build_dir ARCH=riscv SHELL=/bin/bash drivers/

I encountered the following errors regarding GCC plugins:

cc1: error: cannot load plugin ./scripts/gcc-plugins/randomize_layout_plugin.so: ./scripts/gcc-plugins/randomize_layout_plugin.so: undefined symbol: _ZN8opt_pass14set_pass_paramEjb
cc1: error: cannot load plugin ./scripts/gcc-plugins/latent_entropy_plugin.so: ./scripts/gcc-plugins/latent_entropy_plugin.so: undefined symbol: _ZN8opt_pass14set_pass_paramEjb
cc1: error: cannot load plugin ./scripts/gcc-plugins/randomize_layout_plugin.so: ./scripts/gcc-plugins/randomize_layout_plugin.so: undefined symbol: _ZN8opt_pass14set_pass_paramEjb
make[2]: *** [../scripts/Makefile.build:252: scripts/mod/empty.o] Error 1
cc1: error: cannot load plugin ./scripts/gcc-plugins/latent_entropy_plugin.so: ./scripts/gcc-plugins/latent_entropy_plugin.so: undefined symbol: _ZN8opt_pass14set_pass_paramEjb

I'm not quite sure how to resolve that plugin issue, but regardless I
continued investigating the original build error reported by the kernel
test robot.

There are eight calls to quad8_control_register_update() in 104-quad-8:

quad8_control_register_update(priv, priv->idr, id, DISABLE_INDEX_MODE, INDEX_MODE);
quad8_control_register_update(priv, priv->cmr, id, mode_cfg, QUADRATURE_MODE);
quad8_control_register_update(priv, priv->ior, event_node->channel, flg_pins, FLG_PINS);
quad8_control_register_update(priv, priv->idr, channel_id, index_polarity, INDEX_POLARITY);
quad8_control_register_update(priv, priv->idr, channel_id, synchronous_mode, INDEX_MODE);
quad8_control_register_update(priv, priv->cmr, count->id, count_mode, COUNT_MODE);
quad8_control_register_update(priv, priv->ior, count->id, enable, AB_GATE);
quad8_control_register_update(priv, priv->ior, count->id, !preset_enable, LOAD_PIN);

The field arguments for these calls are all preprocessor defines:

#define INDEX_MODE BIT(0)
#define QUADRATURE_MODE GENMASK(4, 3)
#define FLG_PINS GENMASK(4, 3)
#define INDEX_POLARITY BIT(1)
#define COUNT_MODE GENMASK(2, 1)
#define AB_GATE BIT(0)
#define LOAD_PIN BIT(1)

Removing the duplicates, we get the following four field masks:

BIT(0)
BIT(1)
GENMASK(2, 1)
GENMASK(4, 3)

I don't think there's a problem with these masks (unless there's
something broken in the BIT() or GENMASK() implementations for riscv) so
I'm suspecting something is wrong in bitfields.h. Here's the relevant
function:

extern void __compiletime_error("bad bitfield mask")
__bad_mask(void);
static __always_inline u64 field_multiplier(u64 field)
{
if ((field | (field - 1)) & ((field | (field - 1)) + 1))
__bad_mask();
return field & -field;
}

If I compute the conditional check by hand, it evaluates to false for
all four possible field masks. Is it possible the compiler is ignoring
the if statement evaluation and attempting the __bad_mask() compilation
regardless of the field passed in?

William Breathitt Gray

Attachment: signature.asc
Description: PGP signature