edc574673f3741752f358402fc1d01638ada4989
[dpdk.git] / drivers / event / octeontx2 / otx2_worker.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2019 Marvell International Ltd.
3  */
4
5 #include "otx2_worker.h"
6
7 static __rte_noinline uint8_t
8 otx2_ssogws_new_event(struct otx2_ssogws *ws, const struct rte_event *ev)
9 {
10         const uint32_t tag = (uint32_t)ev->event;
11         const uint8_t new_tt = ev->sched_type;
12         const uint64_t event_ptr = ev->u64;
13         const uint16_t grp = ev->queue_id;
14
15         if (ws->xaq_lmt <= *ws->fc_mem)
16                 return 0;
17
18         otx2_ssogws_add_work(ws, event_ptr, tag, new_tt, grp);
19
20         return 1;
21 }
22
23 static __rte_always_inline void
24 otx2_ssogws_fwd_swtag(struct otx2_ssogws *ws, const struct rte_event *ev)
25 {
26         const uint32_t tag = (uint32_t)ev->event;
27         const uint8_t new_tt = ev->sched_type;
28         const uint8_t cur_tt = ws->cur_tt;
29
30         /* 96XX model
31          * cur_tt/new_tt     SSO_SYNC_ORDERED SSO_SYNC_ATOMIC SSO_SYNC_UNTAGGED
32          *
33          * SSO_SYNC_ORDERED        norm           norm             untag
34          * SSO_SYNC_ATOMIC         norm           norm             untag
35          * SSO_SYNC_UNTAGGED       norm           norm             NOOP
36          */
37
38         if (new_tt == SSO_SYNC_UNTAGGED) {
39                 if (cur_tt != SSO_SYNC_UNTAGGED)
40                         otx2_ssogws_swtag_untag(ws);
41         } else {
42                 otx2_ssogws_swtag_norm(ws, tag, new_tt);
43         }
44
45         ws->swtag_req = 1;
46 }
47
48 static __rte_always_inline void
49 otx2_ssogws_fwd_group(struct otx2_ssogws *ws, const struct rte_event *ev,
50                       const uint16_t grp)
51 {
52         const uint32_t tag = (uint32_t)ev->event;
53         const uint8_t new_tt = ev->sched_type;
54
55         otx2_write64(ev->u64, OTX2_SSOW_GET_BASE_ADDR(ws->getwrk_op) +
56                      SSOW_LF_GWS_OP_UPD_WQP_GRP1);
57         rte_smp_wmb();
58         otx2_ssogws_swtag_desched(ws, tag, new_tt, grp);
59 }
60
61 static __rte_always_inline void
62 otx2_ssogws_forward_event(struct otx2_ssogws *ws, const struct rte_event *ev)
63 {
64         const uint8_t grp = ev->queue_id;
65
66         /* Group hasn't changed, Use SWTAG to forward the event */
67         if (ws->cur_grp == grp)
68                 otx2_ssogws_fwd_swtag(ws, ev);
69         else
70         /*
71          * Group has been changed for group based work pipelining,
72          * Use deschedule/add_work operation to transfer the event to
73          * new group/core
74          */
75                 otx2_ssogws_fwd_group(ws, ev, grp);
76 }
77
78 static __rte_always_inline void
79 otx2_ssogws_release_event(struct otx2_ssogws *ws)
80 {
81         otx2_ssogws_swtag_flush(ws);
82 }
83
84 uint16_t __hot
85 otx2_ssogws_deq(void *port, struct rte_event *ev, uint64_t timeout_ticks)
86 {
87         struct otx2_ssogws *ws = port;
88
89         RTE_SET_USED(timeout_ticks);
90
91         if (ws->swtag_req) {
92                 ws->swtag_req = 0;
93                 otx2_ssogws_swtag_wait(ws);
94                 return 1;
95         }
96
97         return otx2_ssogws_get_work(ws, ev);
98 }
99
100 uint16_t __hot
101 otx2_ssogws_deq_burst(void *port, struct rte_event ev[], uint16_t nb_events,
102                       uint64_t timeout_ticks)
103 {
104         RTE_SET_USED(nb_events);
105
106         return otx2_ssogws_deq(port, ev, timeout_ticks);
107 }
108
109 uint16_t __hot
110 otx2_ssogws_deq_timeout(void *port, struct rte_event *ev,
111                         uint64_t timeout_ticks)
112 {
113         struct otx2_ssogws *ws = port;
114         uint16_t ret = 1;
115         uint64_t iter;
116
117         if (ws->swtag_req) {
118                 ws->swtag_req = 0;
119                 otx2_ssogws_swtag_wait(ws);
120                 return ret;
121         }
122
123         ret = otx2_ssogws_get_work(ws, ev);
124         for (iter = 1; iter < timeout_ticks && (ret == 0); iter++)
125                 ret = otx2_ssogws_get_work(ws, ev);
126
127         return ret;
128 }
129
130 uint16_t __hot
131 otx2_ssogws_deq_timeout_burst(void *port, struct rte_event ev[],
132                               uint16_t nb_events, uint64_t timeout_ticks)
133 {
134         RTE_SET_USED(nb_events);
135
136         return otx2_ssogws_deq_timeout(port, ev, timeout_ticks);
137 }
138
139 uint16_t __hot
140 otx2_ssogws_enq(void *port, const struct rte_event *ev)
141 {
142         struct otx2_ssogws *ws = port;
143
144         switch (ev->op) {
145         case RTE_EVENT_OP_NEW:
146                 rte_smp_mb();
147                 return otx2_ssogws_new_event(ws, ev);
148         case RTE_EVENT_OP_FORWARD:
149                 otx2_ssogws_forward_event(ws, ev);
150                 break;
151         case RTE_EVENT_OP_RELEASE:
152                 otx2_ssogws_release_event(ws);
153                 break;
154         default:
155                 return 0;
156         }
157
158         return 1;
159 }
160
161 uint16_t __hot
162 otx2_ssogws_enq_burst(void *port, const struct rte_event ev[],
163                       uint16_t nb_events)
164 {
165         RTE_SET_USED(nb_events);
166         return otx2_ssogws_enq(port, ev);
167 }
168
169 uint16_t __hot
170 otx2_ssogws_enq_new_burst(void *port, const struct rte_event ev[],
171                           uint16_t nb_events)
172 {
173         struct otx2_ssogws *ws = port;
174         uint16_t i, rc = 1;
175
176         rte_smp_mb();
177         if (ws->xaq_lmt <= *ws->fc_mem)
178                 return 0;
179
180         for (i = 0; i < nb_events && rc; i++)
181                 rc = otx2_ssogws_new_event(ws,  &ev[i]);
182
183         return nb_events;
184 }
185
186 uint16_t __hot
187 otx2_ssogws_enq_fwd_burst(void *port, const struct rte_event ev[],
188                           uint16_t nb_events)
189 {
190         struct otx2_ssogws *ws = port;
191
192         RTE_SET_USED(nb_events);
193         otx2_ssogws_forward_event(ws,  ev);
194
195         return 1;
196 }