Skip to content

Commit 3522be4

Browse files
committed
firmware: arm_ffa: Implement the NOTIFICATION_INFO_GET interface
The receiver’s scheduler uses the FFA_NOTIFICATION_INFO_GET interface to retrieve the list of endpoints that have pending notifications and must be run. A notification could be signaled by a sender in the secure world to a VM. The Hypervisor needs to determine which VM and vCPU (in case a per-vCPU notification is signaled) has a pending notification in this scenario. It must obtain this information through an invocation of the FFA_NOTIFICATION_INFO_GET. Add the implementation of the NOTIFICATION_INFO_GET interface and prepare to use this to handle the schedule receiver interrupt. Implementation of handling notifications will be added later. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Sudeep Holla <[email protected]>
1 parent faa1962 commit 3522be4

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

drivers/firmware/arm_ffa/driver.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,13 @@ static int ffa_notification_bitmap_destroy(void)
602602
(FIELD_PREP(RECEIVER_VCPU_MASK, (vcpu_r)) | \
603603
FIELD_PREP(RECEIVER_ID_MASK, (r)))
604604

605+
#define NOTIFICATION_INFO_GET_MORE_PEND_MASK BIT(0)
606+
#define NOTIFICATION_INFO_GET_ID_COUNT GENMASK(11, 7)
607+
#define ID_LIST_MASK_64 GENMASK(51, 12)
608+
#define ID_LIST_MASK_32 GENMASK(31, 12)
609+
#define MAX_IDS_64 20
610+
#define MAX_IDS_32 10
611+
605612
static int ffa_notification_bind_common(u16 dst_id, u64 bitmap,
606613
u32 flags, bool is_bind)
607614
{
@@ -673,6 +680,72 @@ static int ffa_notification_get(u32 flags, struct ffa_notify_bitmaps *notify)
673680
return 0;
674681
}
675682

683+
static void __do_sched_recv_cb(u16 partition_id, u16 vcpu, bool is_per_vcpu)
684+
{
685+
pr_err("Callback for partition 0x%x failed.\n", partition_id);
686+
}
687+
688+
static void ffa_notification_info_get(void)
689+
{
690+
int idx, list, max_ids, lists_cnt, ids_processed, ids_count[MAX_IDS_64];
691+
bool is_64b_resp;
692+
ffa_value_t ret;
693+
u64 id_list;
694+
695+
do {
696+
invoke_ffa_fn((ffa_value_t){
697+
.a0 = FFA_FN_NATIVE(NOTIFICATION_INFO_GET),
698+
}, &ret);
699+
700+
if (ret.a0 != FFA_FN_NATIVE(SUCCESS) && ret.a0 != FFA_SUCCESS) {
701+
if (ret.a2 != FFA_RET_NO_DATA)
702+
pr_err("Notification Info fetch failed: 0x%lx (0x%lx)",
703+
ret.a0, ret.a2);
704+
return;
705+
}
706+
707+
is_64b_resp = (ret.a0 == FFA_FN64_SUCCESS);
708+
709+
ids_processed = 0;
710+
lists_cnt = FIELD_GET(NOTIFICATION_INFO_GET_ID_COUNT, ret.a2);
711+
if (is_64b_resp) {
712+
max_ids = MAX_IDS_64;
713+
id_list = FIELD_GET(ID_LIST_MASK_64, ret.a2);
714+
} else {
715+
max_ids = MAX_IDS_32;
716+
id_list = FIELD_GET(ID_LIST_MASK_32, ret.a2);
717+
}
718+
719+
for (idx = 0; idx < lists_cnt; idx++, id_list >>= 2)
720+
ids_count[idx] = (id_list & 0x3) + 1;
721+
722+
/* Process IDs */
723+
for (list = 0; list < lists_cnt; list++) {
724+
u16 vcpu_id, part_id, *packed_id_list = (u16 *)&ret.a3;
725+
726+
if (ids_processed >= max_ids - 1)
727+
break;
728+
729+
part_id = packed_id_list[++ids_processed];
730+
731+
if (!ids_count[list]) { /* Global Notification */
732+
__do_sched_recv_cb(part_id, 0, false);
733+
continue;
734+
}
735+
736+
/* Per vCPU Notification */
737+
for (idx = 0; idx < ids_count[list]; idx++) {
738+
if (ids_processed >= max_ids - 1)
739+
break;
740+
741+
vcpu_id = packed_id_list[++ids_processed];
742+
743+
__do_sched_recv_cb(part_id, vcpu_id, true);
744+
}
745+
}
746+
} while (ret.a2 & NOTIFICATION_INFO_GET_MORE_PEND_MASK);
747+
}
748+
676749
static int ffa_run(struct ffa_device *dev, u16 vcpu)
677750
{
678751
ffa_value_t ret;

0 commit comments

Comments
 (0)