Unverified Commit 2275be72 authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'arm-ffa-updates-5.16' of...

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/20211026141535.1920602-1-sudeep.holla@arm.com


Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents e2a3495b 01537a07
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -49,6 +49,13 @@ static int ffa_device_probe(struct device *dev)
	return ffa_drv->probe(ffa_dev);
}

static void ffa_device_remove(struct device *dev)
{
	struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver);

	ffa_drv->remove(to_ffa_dev(dev));
}

static int ffa_device_uevent(struct device *dev, struct kobj_uevent_env *env)
{
	struct ffa_device *ffa_dev = to_ffa_dev(dev);
@@ -86,6 +93,7 @@ struct bus_type ffa_bus_type = {
	.name		= "arm_ffa",
	.match		= ffa_device_match,
	.probe		= ffa_device_probe,
	.remove		= ffa_device_remove,
	.uevent		= ffa_device_uevent,
	.dev_groups	= ffa_device_attributes_groups,
};
@@ -127,7 +135,7 @@ static void ffa_release_device(struct device *dev)

static int __ffa_devices_unregister(struct device *dev, void *data)
{
	ffa_release_device(dev);
	device_unregister(dev);

	return 0;
}
+48 −5
Original line number Diff line number Diff line
@@ -167,6 +167,27 @@ 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.
 */
static u32 ffa_compatible_version_find(u32 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;

	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 +201,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;
}

@@ -586,6 +612,22 @@ ffa_memory_share(struct ffa_device *dev, struct ffa_mem_ops_args *args)
	return ffa_memory_ops(FFA_FN_NATIVE(MEM_SHARE), args);
}

static int
ffa_memory_lend(struct ffa_device *dev, struct ffa_mem_ops_args *args)
{
	/* Note that upon a successful MEM_LEND request the caller
	 * must ensure that the memory region specified is not accessed
	 * until a successful MEM_RECALIM call has been made.
	 * On systems with a hypervisor present this will been enforced,
	 * however on systems without a hypervisor the responsibility
	 * falls to the calling kernel driver to prevent access.
	 */
	if (dev->mode_32bit)
		return ffa_memory_ops(FFA_MEM_LEND, args);

	return ffa_memory_ops(FFA_FN_NATIVE(MEM_LEND), args);
}

static const struct ffa_dev_ops ffa_ops = {
	.api_version_get = ffa_api_version_get,
	.partition_info_get = ffa_partition_info_get,
@@ -593,6 +635,7 @@ static const struct ffa_dev_ops ffa_ops = {
	.sync_send_receive = ffa_sync_send_receive,
	.memory_reclaim = ffa_memory_reclaim,
	.memory_share = ffa_memory_share,
	.memory_lend = ffa_memory_lend,
};

const struct ffa_dev_ops *ffa_dev_ops_get(struct ffa_device *dev)
+2 −0
Original line number Diff line number Diff line
@@ -262,6 +262,8 @@ struct ffa_dev_ops {
	int (*memory_reclaim)(u64 g_handle, u32 flags);
	int (*memory_share)(struct ffa_device *dev,
			    struct ffa_mem_ops_args *args);
	int (*memory_lend)(struct ffa_device *dev,
			   struct ffa_mem_ops_args *args);
};

#endif /* _LINUX_ARM_FFA_H */