Re: [PATCH v2 2/6] iio: adc: ad4130: Fix comparison of channel setups

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Feb 18, 2025 at 8:31 PM Uwe Kleine-König
<u.kleine-koenig@xxxxxxxxxxxx> wrote:
>
> Checking the binary representation of two structs (of the same type)
> for equality doesn't have the same semantic as comparing all members for
> equality. The former might find a difference where the latter doesn't in
> the presence of padding or when ambiguous types like float or bool are
> involved. (Floats typically have different representations for single
> values, like -0.0 vs +0.0, or 0.5 * 2² vs 0.25 * 2³. The type bool has
> at least 8 bits and the raw values 1 and 2 (probably) both evaluate to
> true, but memcmp finds a difference.)
>
> When searching for a channel that already has the configuration we need,
> the comparison by member is the one that is needed.
>
> Convert the comparison accordingly to compare the members one after
> another. Also add a BUILD_BUG guard to (somewhat) ensure that when
> struct ad4130_setup_info is expanded, the comparison is adapted, too.

...

> +/*
> + * If you make adaptions in this struct, you most likely also have to adapt

adaptations?


> + * ad4130_setup_info_eq(), too.
> + */

...

> +static bool ad4130_setup_info_eq(struct ad4130_setup_info *a,
> +                                struct ad4130_setup_info *b)
> +{
> +       /*
> +        * This is just to make sure that the comparison is adapted after
> +        * struct ad4130_setup_info was changed.
> +        */
> +       static_assert(sizeof(*a) ==
> +                     sizeof(struct {
> +                                    unsigned int iout0_val;
> +                                    unsigned int iout1_val;
> +                                    unsigned int burnout;
> +                                    unsigned int pga;
> +                                    unsigned int fs;
> +                                    u32 ref_sel;
> +                                    enum ad4130_filter_mode filter_mode;
> +                                    bool ref_bufp;
> +                                    bool ref_bufm;
> +                            }));

This can be moved out of the function, but in any case it should not
affect code generation I believe.

> +       if (a->iout0_val != b->iout0_val ||
> +           a->iout1_val != b->iout1_val ||
> +           a->burnout != b->burnout ||
> +           a->pga != b->pga ||
> +           a->fs != b->fs ||
> +           a->ref_sel != b->ref_sel ||
> +           a->filter_mode != b->filter_mode ||
> +           a->ref_bufp != b->ref_bufp ||
> +           a->ref_bufm != b->ref_bufm)
> +               return false;
> +
> +       return true;
> +}

...

>                 struct ad4130_slot_info *slot_info = &st->slots_info[i];
>
>                 /* Immediately accept a matching setup info. */
> -               if (!memcmp(target_setup_info, &slot_info->setup,
> -                           sizeof(*target_setup_info))) {
> +               if (ad4130_setup_info_eq(target_setup_info, &slot_info->setup)) {

I don't remember if we discussed the idea of using crc32 to compare
the data structures, like it's done for PLD data in USB Type-C cases.
https://elixir.bootlin.com/linux/v6.14-rc3/C/ident/pld_crc

>                         *slot = i;
>                         return 0;
>                 }


-- 
With Best Regards,
Andy Shevchenko





[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux