Skip to content

Commit 8e3f9da

Browse files
committed
firmware: arm_ffa: Handle compatibility with different firmware versions
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. Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Jens Wiklander <[email protected]> Signed-off-by: Sudeep Holla <[email protected]>
1 parent eb7b52e commit 8e3f9da

File tree

1 file changed

+32
-5
lines changed

1 file changed

+32
-5
lines changed

drivers/firmware/arm_ffa/driver.c

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,28 @@ struct ffa_drv_info {
167167

168168
static struct ffa_drv_info *drv_info;
169169

170+
/*
171+
* The driver must be able to support all the versions from the earliest
172+
* supported FFA_MIN_VERSION to the latest supported FFA_DRIVER_VERSION.
173+
* The specification states that if firmware supports a FFA implementation
174+
* that is incompatible with and at a greater version number than specified
175+
* by the caller(FFA_DRIVER_VERSION passed as parameter to FFA_VERSION),
176+
* it must return the NOT_SUPPORTED error code.
177+
*/
178+
static u32 ffa_compatible_version_find(u32 version)
179+
{
180+
u32 compat_version;
181+
u16 major = MAJOR_VERSION(version), minor = MINOR_VERSION(version);
182+
u16 drv_major = MAJOR_VERSION(FFA_DRIVER_VERSION);
183+
u16 drv_minor = MINOR_VERSION(FFA_DRIVER_VERSION);
184+
185+
if ((major < drv_major) || (major == drv_major && minor <= drv_minor))
186+
return version;
187+
188+
pr_info("Firmware version higher than driver version, downgrading\n");
189+
return FFA_DRIVER_VERSION;
190+
}
191+
170192
static int ffa_version_check(u32 *version)
171193
{
172194
ffa_value_t ver;
@@ -180,15 +202,20 @@ static int ffa_version_check(u32 *version)
180202
return -EOPNOTSUPP;
181203
}
182204

183-
if (ver.a0 < FFA_MIN_VERSION || ver.a0 > FFA_DRIVER_VERSION) {
184-
pr_err("Incompatible version %d.%d found\n",
185-
MAJOR_VERSION(ver.a0), MINOR_VERSION(ver.a0));
205+
if (ver.a0 < FFA_MIN_VERSION) {
206+
pr_err("Incompatible v%d.%d! Earliest supported v%d.%d\n",
207+
MAJOR_VERSION(ver.a0), MINOR_VERSION(ver.a0),
208+
MAJOR_VERSION(FFA_MIN_VERSION),
209+
MINOR_VERSION(FFA_MIN_VERSION));
186210
return -EINVAL;
187211
}
188212

189-
*version = ver.a0;
190-
pr_info("Version %d.%d found\n", MAJOR_VERSION(ver.a0),
213+
pr_info("Driver version %d.%d\n", MAJOR_VERSION(FFA_DRIVER_VERSION),
214+
MINOR_VERSION(FFA_DRIVER_VERSION));
215+
pr_info("Firmware version %d.%d found\n", MAJOR_VERSION(ver.a0),
191216
MINOR_VERSION(ver.a0));
217+
*version = ffa_compatible_version_find(ver.a0);
218+
192219
return 0;
193220
}
194221

0 commit comments

Comments
 (0)