Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2018-2022 Advanced Micro Devices, Inc.
3 : : */
4 : :
5 : : #include <stdbool.h>
6 : :
7 : : #include <rte_malloc.h>
8 : :
9 : : #include "ionic_dev.h"
10 : : #include "ionic_lif.h"
11 : : #include "ionic.h"
12 : :
13 : : /* Devcmd Interface */
14 : :
15 : : uint8_t
16 : 0 : ionic_dev_cmd_status(struct ionic_dev *idev)
17 : : {
18 : 0 : return ioread8(&idev->dev_cmd->comp.comp.status);
19 : : }
20 : :
21 : : bool
22 : 0 : ionic_dev_cmd_done(struct ionic_dev *idev)
23 : : {
24 : 0 : return ioread32(&idev->dev_cmd->done) & IONIC_DEV_CMD_DONE;
25 : : }
26 : :
27 : : void
28 : 0 : ionic_dev_cmd_comp(struct ionic_dev *idev, void *mem)
29 : : {
30 : : union ionic_dev_cmd_comp *comp = mem;
31 : : uint32_t comp_size = RTE_DIM(comp->words);
32 : : uint32_t i;
33 : :
34 [ # # ]: 0 : for (i = 0; i < comp_size; i++)
35 : 0 : comp->words[i] = ioread32(&idev->dev_cmd->comp.words[i]);
36 : 0 : }
37 : :
38 : : void
39 : 0 : ionic_dev_cmd_go(struct ionic_dev *idev, union ionic_dev_cmd *cmd)
40 : : {
41 : : uint32_t cmd_size = RTE_DIM(cmd->words);
42 : : uint32_t i;
43 : :
44 : 0 : IONIC_PRINT(DEBUG, "Sending %s (%d) via dev_cmd",
45 : : ionic_opcode_to_str(cmd->cmd.opcode), cmd->cmd.opcode);
46 : :
47 [ # # ]: 0 : for (i = 0; i < cmd_size; i++)
48 : 0 : iowrite32(cmd->words[i], &idev->dev_cmd->cmd.words[i]);
49 : :
50 : 0 : iowrite32(0, &idev->dev_cmd->done);
51 : 0 : iowrite32(1, &idev->dev_cmd->doorbell);
52 : 0 : }
53 : :
54 : : /* Device commands */
55 : :
56 : : void
57 : 0 : ionic_dev_cmd_identify(struct ionic_dev *idev, uint8_t ver)
58 : : {
59 : 0 : union ionic_dev_cmd cmd = {
60 : : .identify.opcode = IONIC_CMD_IDENTIFY,
61 : : .identify.ver = ver,
62 : : };
63 : :
64 : 0 : ionic_dev_cmd_go(idev, &cmd);
65 : 0 : }
66 : :
67 : : void
68 : 0 : ionic_dev_cmd_init(struct ionic_dev *idev)
69 : : {
70 : 0 : union ionic_dev_cmd cmd = {
71 : : .init.opcode = IONIC_CMD_INIT,
72 : : .init.type = 0,
73 : : };
74 : :
75 : 0 : ionic_dev_cmd_go(idev, &cmd);
76 : 0 : }
77 : :
78 : : void
79 : 0 : ionic_dev_cmd_reset(struct ionic_dev *idev)
80 : : {
81 : 0 : union ionic_dev_cmd cmd = {
82 : : .reset.opcode = IONIC_CMD_RESET,
83 : : };
84 : :
85 : 0 : ionic_dev_cmd_go(idev, &cmd);
86 : 0 : }
87 : :
88 : : /* Port commands */
89 : :
90 : : void
91 : 0 : ionic_dev_cmd_port_identify(struct ionic_dev *idev)
92 : : {
93 : 0 : union ionic_dev_cmd cmd = {
94 : : .port_init.opcode = IONIC_CMD_PORT_IDENTIFY,
95 : : .port_init.index = 0,
96 : : };
97 : :
98 : 0 : ionic_dev_cmd_go(idev, &cmd);
99 : 0 : }
100 : :
101 : : void
102 : 0 : ionic_dev_cmd_port_init(struct ionic_dev *idev)
103 : : {
104 : 0 : union ionic_dev_cmd cmd = {
105 : : .port_init.opcode = IONIC_CMD_PORT_INIT,
106 : : .port_init.index = 0,
107 : 0 : .port_init.info_pa = rte_cpu_to_le_64(idev->port_info_pa),
108 : : };
109 : :
110 : 0 : ionic_dev_cmd_go(idev, &cmd);
111 : 0 : }
112 : :
113 : : void
114 : 0 : ionic_dev_cmd_port_reset(struct ionic_dev *idev)
115 : : {
116 : 0 : union ionic_dev_cmd cmd = {
117 : : .port_reset.opcode = IONIC_CMD_PORT_RESET,
118 : : .port_reset.index = 0,
119 : : };
120 : :
121 : 0 : ionic_dev_cmd_go(idev, &cmd);
122 : 0 : }
123 : :
124 : : void
125 : 0 : ionic_dev_cmd_port_state(struct ionic_dev *idev, uint8_t state)
126 : : {
127 : 0 : union ionic_dev_cmd cmd = {
128 : : .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
129 : : .port_setattr.index = 0,
130 : : .port_setattr.attr = IONIC_PORT_ATTR_STATE,
131 : : .port_setattr.state = state,
132 : : };
133 : :
134 : 0 : ionic_dev_cmd_go(idev, &cmd);
135 : 0 : }
136 : :
137 : : void
138 : 0 : ionic_dev_cmd_port_speed(struct ionic_dev *idev, uint32_t speed)
139 : : {
140 : 0 : union ionic_dev_cmd cmd = {
141 : : .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
142 : : .port_setattr.index = 0,
143 : : .port_setattr.attr = IONIC_PORT_ATTR_SPEED,
144 : : .port_setattr.speed = rte_cpu_to_le_32(speed),
145 : : };
146 : :
147 : 0 : ionic_dev_cmd_go(idev, &cmd);
148 : 0 : }
149 : :
150 : : void
151 : 0 : ionic_dev_cmd_port_mtu(struct ionic_dev *idev, uint32_t mtu)
152 : : {
153 : 0 : union ionic_dev_cmd cmd = {
154 : : .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
155 : : .port_setattr.index = 0,
156 : : .port_setattr.attr = IONIC_PORT_ATTR_MTU,
157 : : .port_setattr.mtu = rte_cpu_to_le_32(mtu),
158 : : };
159 : :
160 : 0 : ionic_dev_cmd_go(idev, &cmd);
161 : 0 : }
162 : :
163 : : void
164 : 0 : ionic_dev_cmd_port_autoneg(struct ionic_dev *idev, uint8_t an_enable)
165 : : {
166 : 0 : union ionic_dev_cmd cmd = {
167 : : .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
168 : : .port_setattr.index = 0,
169 : : .port_setattr.attr = IONIC_PORT_ATTR_AUTONEG,
170 : : .port_setattr.an_enable = an_enable,
171 : : };
172 : :
173 : 0 : ionic_dev_cmd_go(idev, &cmd);
174 : 0 : }
175 : :
176 : : void
177 : 0 : ionic_dev_cmd_port_fec(struct ionic_dev *idev, uint8_t fec_type)
178 : : {
179 : 0 : union ionic_dev_cmd cmd = {
180 : : .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
181 : : .port_setattr.index = 0,
182 : : .port_setattr.attr = IONIC_PORT_ATTR_FEC,
183 : : .port_setattr.fec_type = fec_type,
184 : : };
185 : :
186 : 0 : ionic_dev_cmd_go(idev, &cmd);
187 : 0 : }
188 : :
189 : : void
190 : 0 : ionic_dev_cmd_port_pause(struct ionic_dev *idev, uint8_t pause_type)
191 : : {
192 : 0 : union ionic_dev_cmd cmd = {
193 : : .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
194 : : .port_setattr.index = 0,
195 : : .port_setattr.attr = IONIC_PORT_ATTR_PAUSE,
196 : : .port_setattr.pause_type = pause_type,
197 : : };
198 : :
199 : 0 : ionic_dev_cmd_go(idev, &cmd);
200 : 0 : }
201 : :
202 : : void
203 : 0 : ionic_dev_cmd_port_loopback(struct ionic_dev *idev, uint8_t loopback_mode)
204 : : {
205 : 0 : union ionic_dev_cmd cmd = {
206 : : .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
207 : : .port_setattr.index = 0,
208 : : .port_setattr.attr = IONIC_PORT_ATTR_LOOPBACK,
209 : : .port_setattr.loopback_mode = loopback_mode,
210 : : };
211 : :
212 : 0 : ionic_dev_cmd_go(idev, &cmd);
213 : 0 : }
214 : :
215 : : /* LIF commands */
216 : :
217 : : void
218 : 0 : ionic_dev_cmd_queue_identify(struct ionic_dev *idev,
219 : : uint16_t lif_type, uint8_t qtype, uint8_t qver)
220 : : {
221 : 0 : union ionic_dev_cmd cmd = {
222 : : .q_identify.opcode = IONIC_CMD_Q_IDENTIFY,
223 : : .q_identify.lif_type = rte_cpu_to_le_16(lif_type),
224 : : .q_identify.type = qtype,
225 : : .q_identify.ver = qver,
226 : : };
227 : :
228 : 0 : ionic_dev_cmd_go(idev, &cmd);
229 : 0 : }
230 : :
231 : : void
232 : 0 : ionic_dev_cmd_lif_identify(struct ionic_dev *idev, uint8_t type, uint8_t ver)
233 : : {
234 : 0 : union ionic_dev_cmd cmd = {
235 : : .lif_identify.opcode = IONIC_CMD_LIF_IDENTIFY,
236 : : .lif_identify.type = type,
237 : : .lif_identify.ver = ver,
238 : : };
239 : :
240 : 0 : ionic_dev_cmd_go(idev, &cmd);
241 : 0 : }
242 : :
243 : : void
244 : 0 : ionic_dev_cmd_lif_init(struct ionic_dev *idev, rte_iova_t info_pa)
245 : : {
246 : 0 : union ionic_dev_cmd cmd = {
247 : : .lif_init.opcode = IONIC_CMD_LIF_INIT,
248 : : .lif_init.info_pa = rte_cpu_to_le_64(info_pa),
249 : : };
250 : :
251 : 0 : ionic_dev_cmd_go(idev, &cmd);
252 : 0 : }
253 : :
254 : : void
255 : 0 : ionic_dev_cmd_lif_reset(struct ionic_dev *idev)
256 : : {
257 : 0 : union ionic_dev_cmd cmd = {
258 : : .lif_init.opcode = IONIC_CMD_LIF_RESET,
259 : : };
260 : :
261 : 0 : ionic_dev_cmd_go(idev, &cmd);
262 : 0 : }
263 : :
264 : : struct ionic_doorbell *
265 : 0 : ionic_db_map(struct ionic_lif *lif, struct ionic_queue *q)
266 : : {
267 : 0 : return lif->kern_dbpage + q->hw_type;
268 : : }
269 : :
270 : : void
271 : 0 : ionic_intr_init(struct ionic_dev *idev, struct ionic_intr_info *intr,
272 : : unsigned long index)
273 : : {
274 : 0 : ionic_intr_clean(idev->intr_ctrl, index);
275 : 0 : intr->index = index;
276 : 0 : }
277 : :
278 : : void
279 : 0 : ionic_dev_cmd_adminq_init(struct ionic_dev *idev, struct ionic_qcq *qcq)
280 : : {
281 : : struct ionic_queue *q = &qcq->q;
282 : : struct ionic_cq *cq = &qcq->cq;
283 : :
284 : 0 : union ionic_dev_cmd cmd = {
285 : : .q_init.opcode = IONIC_CMD_Q_INIT,
286 : 0 : .q_init.type = q->type,
287 : 0 : .q_init.ver = qcq->lif->qtype_info[q->type].version,
288 : 0 : .q_init.index = rte_cpu_to_le_32(q->index),
289 : : .q_init.flags = rte_cpu_to_le_16(IONIC_QINIT_F_ENA),
290 : : .q_init.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
291 [ # # ]: 0 : .q_init.ring_size = rte_log2_u32(q->num_descs),
292 : 0 : .q_init.ring_base = rte_cpu_to_le_64(q->base_pa),
293 : 0 : .q_init.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
294 : : };
295 : :
296 : 0 : IONIC_PRINT(DEBUG, "adminq.q_init.ver %u", cmd.q_init.ver);
297 : :
298 : 0 : ionic_dev_cmd_go(idev, &cmd);
299 : 0 : }
300 : :
301 : : int
302 : 0 : ionic_cq_init(struct ionic_cq *cq, uint16_t num_descs)
303 : : {
304 [ # # ]: 0 : if (!rte_is_power_of_2(num_descs) ||
305 [ # # ]: 0 : num_descs < IONIC_MIN_RING_DESC ||
306 : : num_descs > IONIC_MAX_RING_DESC) {
307 : 0 : IONIC_PRINT(ERR, "%u descriptors (min: %u max: %u)",
308 : : num_descs, IONIC_MIN_RING_DESC, IONIC_MAX_RING_DESC);
309 : 0 : return -EINVAL;
310 : : }
311 : :
312 : 0 : cq->num_descs = num_descs;
313 : 0 : cq->size_mask = num_descs - 1;
314 : 0 : cq->tail_idx = 0;
315 : 0 : cq->done_color = 1;
316 : :
317 : 0 : return 0;
318 : : }
319 : :
320 : : void
321 : 0 : ionic_cq_reset(struct ionic_cq *cq)
322 : : {
323 : 0 : cq->tail_idx = 0;
324 : 0 : cq->done_color = 1;
325 : :
326 : 0 : memset(cq->base, 0, sizeof(struct ionic_nop_comp) * cq->num_descs);
327 : 0 : }
328 : :
329 : : void
330 : 0 : ionic_cq_map(struct ionic_cq *cq, void *base, rte_iova_t base_pa)
331 : : {
332 : 0 : cq->base = base;
333 : 0 : cq->base_pa = base_pa;
334 : 0 : }
335 : :
336 : : uint32_t
337 : 0 : ionic_cq_service(struct ionic_cq *cq, uint32_t work_to_do,
338 : : ionic_cq_cb cb, void *cb_arg)
339 : : {
340 : : uint32_t work_done = 0;
341 : :
342 [ # # ]: 0 : if (work_to_do == 0)
343 : : return 0;
344 : :
345 [ # # ]: 0 : while (cb(cq, cq->tail_idx, cb_arg)) {
346 : 0 : cq->tail_idx = Q_NEXT_TO_SRVC(cq, 1);
347 [ # # ]: 0 : if (cq->tail_idx == 0)
348 : 0 : cq->done_color = !cq->done_color;
349 : :
350 [ # # ]: 0 : if (++work_done == work_to_do)
351 : : break;
352 : : }
353 : :
354 : : return work_done;
355 : : }
356 : :
357 : : int
358 : 0 : ionic_q_init(struct ionic_queue *q, uint32_t index, uint16_t num_descs)
359 : : {
360 : : uint32_t ring_size;
361 : :
362 [ # # ]: 0 : if (!rte_is_power_of_2(num_descs))
363 : : return -EINVAL;
364 : :
365 : : ring_size = rte_log2_u32(num_descs);
366 [ # # ]: 0 : if (ring_size < 2 || ring_size > 16)
367 : : return -EINVAL;
368 : :
369 : 0 : q->index = index;
370 : 0 : q->num_descs = num_descs;
371 : 0 : q->size_mask = num_descs - 1;
372 : 0 : ionic_q_reset(q);
373 : :
374 : 0 : return 0;
375 : : }
376 : :
377 : : void
378 : 0 : ionic_q_map(struct ionic_queue *q, void *base, rte_iova_t base_pa,
379 : : void *cmb_base, rte_iova_t cmb_base_pa)
380 : : {
381 : 0 : q->base = base;
382 : 0 : q->base_pa = base_pa;
383 : 0 : q->cmb_base = cmb_base;
384 : 0 : q->cmb_base_pa = cmb_base_pa;
385 : 0 : }
386 : :
387 : : void
388 : 0 : ionic_q_sg_map(struct ionic_queue *q, void *base, rte_iova_t base_pa)
389 : : {
390 : 0 : q->sg_base = base;
391 : 0 : q->sg_base_pa = base_pa;
392 : 0 : }
393 : :
394 : : void
395 : 0 : ionic_q_reset(struct ionic_queue *q)
396 : : {
397 : 0 : q->head_idx = 0;
398 : 0 : q->cmb_head_idx = 0;
399 : 0 : q->tail_idx = 0;
400 : 0 : }
|