Skip to content

Commit 2275be7

Browse files
committed
Merge tag 'arm-ffa-updates-5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/drivers
Arm FF-A updates for v5.16 Just couple of minor updates: - Adding support for MEMORY_LEND API - Handling compatibility with different firmware versions(especially dealing with newer/higher versions than the one supported by the driver) * tag 'arm-ffa-updates-5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux: firmware: arm_ffa: Remove unused 'compat_version' variable firmware: arm_ffa: Add support for MEM_LEND firmware: arm_ffa: Handle compatibility with different firmware versions firmware: arm_ffa: Fix __ffa_devices_unregister firmware: arm_ffa: Add missing remove callback to ffa_bus_type Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnd Bergmann <[email protected]>
2 parents e2a3495 + 01537a0 commit 2275be7

File tree

3 files changed

+59
-6
lines changed

3 files changed

+59
-6
lines changed

drivers/firmware/arm_ffa/bus.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ static int ffa_device_probe(struct device *dev)
4949
return ffa_drv->probe(ffa_dev);
5050
}
5151

52+
static void ffa_device_remove(struct device *dev)
53+
{
54+
struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver);
55+
56+
ffa_drv->remove(to_ffa_dev(dev));
57+
}
58+
5259
static int ffa_device_uevent(struct device *dev, struct kobj_uevent_env *env)
5360
{
5461
struct ffa_device *ffa_dev = to_ffa_dev(dev);
@@ -86,6 +93,7 @@ struct bus_type ffa_bus_type = {
8693
.name = "arm_ffa",
8794
.match = ffa_device_match,
8895
.probe = ffa_device_probe,
96+
.remove = ffa_device_remove,
8997
.uevent = ffa_device_uevent,
9098
.dev_groups = ffa_device_attributes_groups,
9199
};
@@ -127,7 +135,7 @@ static void ffa_release_device(struct device *dev)
127135

128136
static int __ffa_devices_unregister(struct device *dev, void *data)
129137
{
130-
ffa_release_device(dev);
138+
device_unregister(dev);
131139

132140
return 0;
133141
}

drivers/firmware/arm_ffa/driver.c

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,27 @@ 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+
u16 major = MAJOR_VERSION(version), minor = MINOR_VERSION(version);
181+
u16 drv_major = MAJOR_VERSION(FFA_DRIVER_VERSION);
182+
u16 drv_minor = MINOR_VERSION(FFA_DRIVER_VERSION);
183+
184+
if ((major < drv_major) || (major == drv_major && minor <= drv_minor))
185+
return version;
186+
187+
pr_info("Firmware version higher than driver version, downgrading\n");
188+
return FFA_DRIVER_VERSION;
189+
}
190+
170191
static int ffa_version_check(u32 *version)
171192
{
172193
ffa_value_t ver;
@@ -180,15 +201,20 @@ static int ffa_version_check(u32 *version)
180201
return -EOPNOTSUPP;
181202
}
182203

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));
204+
if (ver.a0 < FFA_MIN_VERSION) {
205+
pr_err("Incompatible v%d.%d! Earliest supported v%d.%d\n",
206+
MAJOR_VERSION(ver.a0), MINOR_VERSION(ver.a0),
207+
MAJOR_VERSION(FFA_MIN_VERSION),
208+
MINOR_VERSION(FFA_MIN_VERSION));
186209
return -EINVAL;
187210
}
188211

189-
*version = ver.a0;
190-
pr_info("Version %d.%d found\n", MAJOR_VERSION(ver.a0),
212+
pr_info("Driver version %d.%d\n", MAJOR_VERSION(FFA_DRIVER_VERSION),
213+
MINOR_VERSION(FFA_DRIVER_VERSION));
214+
pr_info("Firmware version %d.%d found\n", MAJOR_VERSION(ver.a0),
191215
MINOR_VERSION(ver.a0));
216+
*version = ffa_compatible_version_find(ver.a0);
217+
192218
return 0;
193219
}
194220

@@ -586,13 +612,30 @@ ffa_memory_share(struct ffa_device *dev, struct ffa_mem_ops_args *args)
586612
return ffa_memory_ops(FFA_FN_NATIVE(MEM_SHARE), args);
587613
}
588614

615+
static int
616+
ffa_memory_lend(struct ffa_device *dev, struct ffa_mem_ops_args *args)
617+
{
618+
/* Note that upon a successful MEM_LEND request the caller
619+
* must ensure that the memory region specified is not accessed
620+
* until a successful MEM_RECALIM call has been made.
621+
* On systems with a hypervisor present this will been enforced,
622+
* however on systems without a hypervisor the responsibility
623+
* falls to the calling kernel driver to prevent access.
624+
*/
625+
if (dev->mode_32bit)
626+
return ffa_memory_ops(FFA_MEM_LEND, args);
627+
628+
return ffa_memory_ops(FFA_FN_NATIVE(MEM_LEND), args);
629+
}
630+
589631
static const struct ffa_dev_ops ffa_ops = {
590632
.api_version_get = ffa_api_version_get,
591633
.partition_info_get = ffa_partition_info_get,
592634
.mode_32bit_set = ffa_mode_32bit_set,
593635
.sync_send_receive = ffa_sync_send_receive,
594636
.memory_reclaim = ffa_memory_reclaim,
595637
.memory_share = ffa_memory_share,
638+
.memory_lend = ffa_memory_lend,
596639
};
597640

598641
const struct ffa_dev_ops *ffa_dev_ops_get(struct ffa_device *dev)

include/linux/arm_ffa.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,8 @@ struct ffa_dev_ops {
262262
int (*memory_reclaim)(u64 g_handle, u32 flags);
263263
int (*memory_share)(struct ffa_device *dev,
264264
struct ffa_mem_ops_args *args);
265+
int (*memory_lend)(struct ffa_device *dev,
266+
struct ffa_mem_ops_args *args);
265267
};
266268

267269
#endif /* _LINUX_ARM_FFA_H */

0 commit comments

Comments
 (0)