[PATCH] firmware: arm_ffa: Handle compatibility with different firmware versions

Jens Wiklander jens.wiklander at linaro.org
Wed Oct 13 06:10:50 PDT 2021


On Wed, Oct 13, 2021 at 11:11 AM Sudeep Holla <sudeep.holla at arm.com> wrote:
>
> The driver currently just support v1.0 of Arm FFA specification. It also
> expects the firmware implementation to match the same and bail out if it
> doesn't match. This is causing issue when running with higher version of
> firmware implementation(e.g. v1.1 which will released soon).
>
> In order to support compatibility with different firmware versions, let
> us add additional checks and find the compatible version the driver can
> work with.
>
> Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
> ---
>  drivers/firmware/arm_ffa/driver.c | 37 ++++++++++++++++++++++++++-----
>  1 file changed, 32 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
> index c9fb56afbcb4..6e0c883ab708 100644
> --- a/drivers/firmware/arm_ffa/driver.c
> +++ b/drivers/firmware/arm_ffa/driver.c
> @@ -167,6 +167,28 @@ struct ffa_drv_info {
>
>  static struct ffa_drv_info *drv_info;
>
> +/*
> + * The driver must be able to support all the versions from the earliest
> + * supported FFA_MIN_VERSION to the latest supported FFA_DRIVER_VERSION.
> + * The specification states that if firmware supports a FFA implementation
> + * that is incompatible with and at a greater version number than specified
> + * by the caller(FFA_DRIVER_VERSION passed as parameter to FFA_VERSION),
> + * it must return the NOT_SUPPORTED error code.

>From what I understand from the specification (v1.1 beta0) it may also
return its version in this case.

> + */
> +static u32 ffa_compatible_version_find(u32 version)
> +{
> +       u32 compat_version;
> +       u16 major = MAJOR_VERSION(version), minor = MINOR_VERSION(version);
> +       u16 drv_major = MAJOR_VERSION(FFA_DRIVER_VERSION);
> +       u16 drv_minor = MINOR_VERSION(FFA_DRIVER_VERSION);
> +
> +       if ((major < drv_major) || (major == drv_major && minor <= drv_minor))
> +               return version;

A mismatch in the major version number makes the versions
incompatible. There's no recovery from this, an error code must be
returned instead.

Cheers,
Jens

> +
> +       pr_info("Firmware version higher than driver version, downgrading\n");
> +       return FFA_DRIVER_VERSION;
> +}
> +
>  static int ffa_version_check(u32 *version)
>  {
>         ffa_value_t ver;
> @@ -180,15 +202,20 @@ static int ffa_version_check(u32 *version)
>                 return -EOPNOTSUPP;
>         }
>
> -       if (ver.a0 < FFA_MIN_VERSION || ver.a0 > FFA_DRIVER_VERSION) {
> -               pr_err("Incompatible version %d.%d found\n",
> -                      MAJOR_VERSION(ver.a0), MINOR_VERSION(ver.a0));
> +       if (ver.a0 < FFA_MIN_VERSION) {
> +               pr_err("Incompatible v%d.%d! Earliest supported v%d.%d\n",
> +                      MAJOR_VERSION(ver.a0), MINOR_VERSION(ver.a0),
> +                      MAJOR_VERSION(FFA_MIN_VERSION),
> +                      MINOR_VERSION(FFA_MIN_VERSION));
>                 return -EINVAL;
>         }
>
> -       *version = ver.a0;
> -       pr_info("Version %d.%d found\n", MAJOR_VERSION(ver.a0),
> +       pr_info("Driver version %d.%d\n", MAJOR_VERSION(FFA_DRIVER_VERSION),
> +               MINOR_VERSION(FFA_DRIVER_VERSION));
> +       pr_info("Firmware version %d.%d found\n", MAJOR_VERSION(ver.a0),
>                 MINOR_VERSION(ver.a0));
> +       *version = ffa_compatible_version_find(ver.a0);
> +
>         return 0;
>  }
>
> --
> 2.25.1
>



More information about the linux-arm-kernel mailing list