Skip to content

Commit 8f67099

Browse files
committed
firmware: arm_ffa: Add support for {un,}registration of framework notifications
JIRA: https://issues.redhat.com/browse/RHEL-102691 commit c10debf Author: Sudeep Holla <sudeep.holla@arm.com> Date: Mon, 17 Feb 2025 15:38:57 +0000 Framework notifications are doorbells that are rung by the partition managers to signal common events to an endpoint. These doorbells cannot be rung by an endpoint directly. A partition manager can signal a Framework notification in response to an FF-A ABI invocation by an endpoint. Two additional notify_ops interface is being added for any FF-A device/ driver to register and unregister for such a framework notifications. Tested-by: Viresh Kumar <viresh.kumar@linaro.org> Message-Id: <20250217-ffa_updates-v3-16-bd1d9de615e7@arm.com> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com> Signed-off-by: Marcin Juszkiewicz <mjuszkiewicz@redhat.com>
1 parent 2150ad7 commit 8f67099

File tree

2 files changed

+97
-21
lines changed

2 files changed

+97
-21
lines changed

drivers/firmware/arm_ffa/driver.c

Lines changed: 92 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,7 @@ static int ffa_memory_lend(struct ffa_mem_ops_args *args)
11171117
struct notifier_cb_info {
11181118
struct hlist_node hnode;
11191119
struct ffa_device *dev;
1120+
ffa_fwk_notifier_cb fwk_cb;
11201121
ffa_notifier_cb cb;
11211122
void *cb_data;
11221123
};
@@ -1180,28 +1181,61 @@ static enum notify_type ffa_notify_type_get(u16 vm_id)
11801181
return NON_SECURE_VM;
11811182
}
11821183

1183-
/* Should be called while the notify_lock is taken */
1184+
/* notifier_hnode_get* should be called with notify_lock held */
11841185
static struct notifier_cb_info *
1185-
notifier_hash_node_get(u16 notify_id, enum notify_type type)
1186+
notifier_hnode_get_by_vmid(u16 notify_id, int vmid)
11861187
{
11871188
struct notifier_cb_info *node;
11881189

11891190
hash_for_each_possible(drv_info->notifier_hash, node, hnode, notify_id)
1190-
if (type == ffa_notify_type_get(node->dev->vm_id))
1191+
if (node->fwk_cb && vmid == node->dev->vm_id)
1192+
return node;
1193+
1194+
return NULL;
1195+
}
1196+
1197+
static struct notifier_cb_info *
1198+
notifier_hnode_get_by_vmid_uuid(u16 notify_id, int vmid, const uuid_t *uuid)
1199+
{
1200+
struct notifier_cb_info *node;
1201+
1202+
if (uuid_is_null(uuid))
1203+
return notifier_hnode_get_by_vmid(notify_id, vmid);
1204+
1205+
hash_for_each_possible(drv_info->notifier_hash, node, hnode, notify_id)
1206+
if (node->fwk_cb && vmid == node->dev->vm_id &&
1207+
uuid_equal(&node->dev->uuid, uuid))
1208+
return node;
1209+
1210+
return NULL;
1211+
}
1212+
1213+
static struct notifier_cb_info *
1214+
notifier_hnode_get_by_type(u16 notify_id, enum notify_type type)
1215+
{
1216+
struct notifier_cb_info *node;
1217+
1218+
hash_for_each_possible(drv_info->notifier_hash, node, hnode, notify_id)
1219+
if (node->cb && type == ffa_notify_type_get(node->dev->vm_id))
11911220
return node;
11921221

11931222
return NULL;
11941223
}
11951224

11961225
static int
1197-
update_notifier_cb(struct ffa_device *dev, int notify_id, ffa_notifier_cb cb,
1198-
void *cb_data, bool is_registration)
1226+
update_notifier_cb(struct ffa_device *dev, int notify_id, void *cb,
1227+
void *cb_data, bool is_registration, bool is_framework)
11991228
{
12001229
struct notifier_cb_info *cb_info = NULL;
12011230
enum notify_type type = ffa_notify_type_get(dev->vm_id);
12021231
bool cb_found;
12031232

1204-
cb_info = notifier_hash_node_get(notify_id, type);
1233+
if (is_framework)
1234+
cb_info = notifier_hnode_get_by_vmid_uuid(notify_id, dev->vm_id,
1235+
&dev->uuid);
1236+
else
1237+
cb_info = notifier_hnode_get_by_type(notify_id, type);
1238+
12051239
cb_found = !!cb_info;
12061240

12071241
if (!(is_registration ^ cb_found))
@@ -1213,8 +1247,11 @@ update_notifier_cb(struct ffa_device *dev, int notify_id, ffa_notifier_cb cb,
12131247
return -ENOMEM;
12141248

12151249
cb_info->dev = dev;
1216-
cb_info->cb = cb;
12171250
cb_info->cb_data = cb_data;
1251+
if (is_framework)
1252+
cb_info->fwk_cb = cb;
1253+
else
1254+
cb_info->cb = cb;
12181255

12191256
hash_add(drv_info->notifier_hash, &cb_info->hnode, notify_id);
12201257
} else {
@@ -1224,7 +1261,8 @@ update_notifier_cb(struct ffa_device *dev, int notify_id, ffa_notifier_cb cb,
12241261
return 0;
12251262
}
12261263

1227-
static int ffa_notify_relinquish(struct ffa_device *dev, int notify_id)
1264+
static int __ffa_notify_relinquish(struct ffa_device *dev, int notify_id,
1265+
bool is_framework)
12281266
{
12291267
int rc;
12301268

@@ -1236,22 +1274,35 @@ static int ffa_notify_relinquish(struct ffa_device *dev, int notify_id)
12361274

12371275
mutex_lock(&drv_info->notify_lock);
12381276

1239-
rc = update_notifier_cb(dev, notify_id, NULL, NULL, false);
1277+
rc = update_notifier_cb(dev, notify_id, NULL, NULL, false,
1278+
is_framework);
12401279
if (rc) {
12411280
pr_err("Could not unregister notification callback\n");
12421281
mutex_unlock(&drv_info->notify_lock);
12431282
return rc;
12441283
}
12451284

1246-
rc = ffa_notification_unbind(dev->vm_id, BIT(notify_id));
1285+
if (!is_framework)
1286+
rc = ffa_notification_unbind(dev->vm_id, BIT(notify_id));
12471287

12481288
mutex_unlock(&drv_info->notify_lock);
12491289

12501290
return rc;
12511291
}
12521292

1253-
static int ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu,
1254-
ffa_notifier_cb cb, void *cb_data, int notify_id)
1293+
static int ffa_notify_relinquish(struct ffa_device *dev, int notify_id)
1294+
{
1295+
return __ffa_notify_relinquish(dev, notify_id, false);
1296+
}
1297+
1298+
static int ffa_fwk_notify_relinquish(struct ffa_device *dev, int notify_id)
1299+
{
1300+
return __ffa_notify_relinquish(dev, notify_id, true);
1301+
}
1302+
1303+
static int __ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu,
1304+
void *cb, void *cb_data,
1305+
int notify_id, bool is_framework)
12551306
{
12561307
int rc;
12571308
u32 flags = 0;
@@ -1264,26 +1315,44 @@ static int ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu,
12641315

12651316
mutex_lock(&drv_info->notify_lock);
12661317

1267-
if (is_per_vcpu)
1268-
flags = PER_VCPU_NOTIFICATION_FLAG;
1318+
if (!is_framework) {
1319+
if (is_per_vcpu)
1320+
flags = PER_VCPU_NOTIFICATION_FLAG;
12691321

1270-
rc = ffa_notification_bind(dev->vm_id, BIT(notify_id), flags);
1271-
if (rc) {
1272-
mutex_unlock(&drv_info->notify_lock);
1273-
return rc;
1322+
rc = ffa_notification_bind(dev->vm_id, BIT(notify_id), flags);
1323+
if (rc) {
1324+
mutex_unlock(&drv_info->notify_lock);
1325+
return rc;
1326+
}
12741327
}
12751328

1276-
rc = update_notifier_cb(dev, notify_id, cb, cb_data, true);
1329+
rc = update_notifier_cb(dev, notify_id, cb, cb_data, true,
1330+
is_framework);
12771331
if (rc) {
12781332
pr_err("Failed to register callback for %d - %d\n",
12791333
notify_id, rc);
1280-
ffa_notification_unbind(dev->vm_id, BIT(notify_id));
1334+
if (!is_framework)
1335+
ffa_notification_unbind(dev->vm_id, BIT(notify_id));
12811336
}
12821337
mutex_unlock(&drv_info->notify_lock);
12831338

12841339
return rc;
12851340
}
12861341

1342+
static int ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu,
1343+
ffa_notifier_cb cb, void *cb_data, int notify_id)
1344+
{
1345+
return __ffa_notify_request(dev, is_per_vcpu, cb, cb_data, notify_id,
1346+
false);
1347+
}
1348+
1349+
static int
1350+
ffa_fwk_notify_request(struct ffa_device *dev, ffa_fwk_notifier_cb cb,
1351+
void *cb_data, int notify_id)
1352+
{
1353+
return __ffa_notify_request(dev, false, cb, cb_data, notify_id, true);
1354+
}
1355+
12871356
static int ffa_notify_send(struct ffa_device *dev, int notify_id,
12881357
bool is_per_vcpu, u16 vcpu)
12891358
{
@@ -1313,7 +1382,7 @@ static void handle_notif_callbacks(u64 bitmap, enum notify_type type)
13131382
continue;
13141383

13151384
mutex_lock(&drv_info->notify_lock);
1316-
cb_info = notifier_hash_node_get(notify_id, type);
1385+
cb_info = notifier_hnode_get_by_type(notify_id, type);
13171386
mutex_unlock(&drv_info->notify_lock);
13181387

13191388
if (cb_info && cb_info->cb)
@@ -1386,6 +1455,8 @@ static const struct ffa_notifier_ops ffa_drv_notifier_ops = {
13861455
.sched_recv_cb_unregister = ffa_sched_recv_cb_unregister,
13871456
.notify_request = ffa_notify_request,
13881457
.notify_relinquish = ffa_notify_relinquish,
1458+
.fwk_notify_request = ffa_fwk_notify_request,
1459+
.fwk_notify_relinquish = ffa_fwk_notify_relinquish,
13891460
.notify_send = ffa_notify_send,
13901461
};
13911462

include/linux/arm_ffa.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ struct ffa_cpu_ops {
460460

461461
typedef void (*ffa_sched_recv_cb)(u16 vcpu, bool is_per_vcpu, void *cb_data);
462462
typedef void (*ffa_notifier_cb)(int notify_id, void *cb_data);
463+
typedef void (*ffa_fwk_notifier_cb)(int notify_id, void *cb_data, void *buf);
463464

464465
struct ffa_notifier_ops {
465466
int (*sched_recv_cb_register)(struct ffa_device *dev,
@@ -468,6 +469,10 @@ struct ffa_notifier_ops {
468469
int (*notify_request)(struct ffa_device *dev, bool per_vcpu,
469470
ffa_notifier_cb cb, void *cb_data, int notify_id);
470471
int (*notify_relinquish)(struct ffa_device *dev, int notify_id);
472+
int (*fwk_notify_request)(struct ffa_device *dev,
473+
ffa_fwk_notifier_cb cb, void *cb_data,
474+
int notify_id);
475+
int (*fwk_notify_relinquish)(struct ffa_device *dev, int notify_id);
471476
int (*notify_send)(struct ffa_device *dev, int notify_id, bool per_vcpu,
472477
u16 vcpu);
473478
};

0 commit comments

Comments
 (0)