diff options
Diffstat (limited to 'platform')
-rw-r--r-- | platform/linux-keystone2/odp_schedule.c | 79 |
1 files changed, 76 insertions, 3 deletions
diff --git a/platform/linux-keystone2/odp_schedule.c b/platform/linux-keystone2/odp_schedule.c index 069def1e..2cc01c73 100644 --- a/platform/linux-keystone2/odp_schedule.c +++ b/platform/linux-keystone2/odp_schedule.c @@ -135,9 +135,82 @@ odp_event_t odp_schedule(odp_queue_t *out_queue, uint64_t wait) int odp_schedule_multi(odp_queue_t *out_queue, uint64_t wait, odp_event_t out_ev[], int num) { - ODP_AS_STR(num > 0, "Zero buffers requested\n"); - out_ev[0] = odp_schedule(out_queue, wait); - return (out_ev[0] == ODP_EVENT_INVALID) ? 0 : 1; + int first = 1; + int rx_num = 0; + odp_time_t time, start_time, diff, wtime; + em_event_t em_event; + em_queue_t em_queue = EM_QUEUE_UNDEF; + odp_event_t event = ODP_EVENT_INVALID; + + odp_pr_dbg("scheduling ....\n"); + odp_schedule_release_atomic(); + + num--; + while (1) { + em_event = ti_em_schedule_once(&em_queue); + if (rx_num < num) + ti_em_preschedule(); + + if (odp_likely(em_event != EM_EVENT_UNDEF)) { + + odp_queue_t src_queue = _odp_queue_from_em_queue(em_queue); + + event = (odp_event_t)ti_em_to_packet(em_event); + out_ev[rx_num] = event; + + /** + * Convert buffer pointers to virtual addresses as the + * rest of code assumes them to be virtual. + * + * @todo: Double convertion phy->virt->phy->virt is + * done, because EM returns virtual address and McSDK + * doesn't have API to convert only buffers. That can + * be fixed. + * Better to postpone conversion until buffer is needed. + */ + Osal_qmssConvertDescPhyToVirt(0, Osal_qmssVirtToPhy( + _odp_ev_to_cppi_desc(event))); + if (out_queue) + *out_queue = src_queue; + + /* Packets from PKTIN queues have to be updated */ + if (odp_queue_type(src_queue) == ODP_QUEUE_TYPE_PKTIN) + pktin_update_event(event, + _odp_queue_to_qentry(src_queue)); + + odp_pr_dbg("Got event from EM: %x, em_queue: %x, odp_queue: %x, buf: %p, thr: %d\n", + em_event, + em_queue, + _odp_queue_from_em_queue(em_queue), + event, + odp_thread_id()); + + if (rx_num++ < num) + continue; + break; + } + + if (wait == ODP_SCHED_WAIT) + continue; + + if (wait == ODP_SCHED_NO_WAIT) + break; + + if (first) { + wtime = odp_time_local_from_ns(wait); + start_time = odp_time_local(); + first = 0; + continue; + } + + time = odp_time_local(); + diff = odp_time_diff(time, start_time); + + if (odp_time_cmp(wtime, diff) < 0) + break; + } + + return rx_num; } |