xref: /dpdk/drivers/net/ionic/ionic_dev.c (revision 90fa040a20e79e1ca96bcbb1bfae3af371a095f1)
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
ionic_dev_cmd_status(struct ionic_dev * idev)16 ionic_dev_cmd_status(struct ionic_dev *idev)
17 {
18 	return ioread8(&idev->dev_cmd->comp.comp.status);
19 }
20 
21 bool
ionic_dev_cmd_done(struct ionic_dev * idev)22 ionic_dev_cmd_done(struct ionic_dev *idev)
23 {
24 	return ioread32(&idev->dev_cmd->done) & IONIC_DEV_CMD_DONE;
25 }
26 
27 void
ionic_dev_cmd_comp(struct ionic_dev * idev,void * mem)28 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 	for (i = 0; i < comp_size; i++)
35 		comp->words[i] = ioread32(&idev->dev_cmd->comp.words[i]);
36 }
37 
38 void
ionic_dev_cmd_go(struct ionic_dev * idev,union ionic_dev_cmd * cmd)39 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 	IONIC_PRINT(DEBUG, "Sending %s (%d) via dev_cmd",
45 		    ionic_opcode_to_str(cmd->cmd.opcode), cmd->cmd.opcode);
46 
47 	for (i = 0; i < cmd_size; i++)
48 		iowrite32(cmd->words[i], &idev->dev_cmd->cmd.words[i]);
49 
50 	iowrite32(0, &idev->dev_cmd->done);
51 	iowrite32(1, &idev->dev_cmd->doorbell);
52 }
53 
54 /* Device commands */
55 
56 void
ionic_dev_cmd_identify(struct ionic_dev * idev,uint8_t ver)57 ionic_dev_cmd_identify(struct ionic_dev *idev, uint8_t ver)
58 {
59 	union ionic_dev_cmd cmd = {
60 		.identify.opcode = IONIC_CMD_IDENTIFY,
61 		.identify.ver = ver,
62 	};
63 
64 	ionic_dev_cmd_go(idev, &cmd);
65 }
66 
67 void
ionic_dev_cmd_init(struct ionic_dev * idev)68 ionic_dev_cmd_init(struct ionic_dev *idev)
69 {
70 	union ionic_dev_cmd cmd = {
71 		.init.opcode = IONIC_CMD_INIT,
72 		.init.type = 0,
73 	};
74 
75 	ionic_dev_cmd_go(idev, &cmd);
76 }
77 
78 void
ionic_dev_cmd_reset(struct ionic_dev * idev)79 ionic_dev_cmd_reset(struct ionic_dev *idev)
80 {
81 	union ionic_dev_cmd cmd = {
82 		.reset.opcode = IONIC_CMD_RESET,
83 	};
84 
85 	ionic_dev_cmd_go(idev, &cmd);
86 }
87 
88 /* Port commands */
89 
90 void
ionic_dev_cmd_port_identify(struct ionic_dev * idev)91 ionic_dev_cmd_port_identify(struct ionic_dev *idev)
92 {
93 	union ionic_dev_cmd cmd = {
94 		.port_init.opcode = IONIC_CMD_PORT_IDENTIFY,
95 		.port_init.index = 0,
96 	};
97 
98 	ionic_dev_cmd_go(idev, &cmd);
99 }
100 
101 void
ionic_dev_cmd_port_init(struct ionic_dev * idev)102 ionic_dev_cmd_port_init(struct ionic_dev *idev)
103 {
104 	union ionic_dev_cmd cmd = {
105 		.port_init.opcode = IONIC_CMD_PORT_INIT,
106 		.port_init.index = 0,
107 		.port_init.info_pa = rte_cpu_to_le_64(idev->port_info_pa),
108 	};
109 
110 	ionic_dev_cmd_go(idev, &cmd);
111 }
112 
113 void
ionic_dev_cmd_port_reset(struct ionic_dev * idev)114 ionic_dev_cmd_port_reset(struct ionic_dev *idev)
115 {
116 	union ionic_dev_cmd cmd = {
117 		.port_reset.opcode = IONIC_CMD_PORT_RESET,
118 		.port_reset.index = 0,
119 	};
120 
121 	ionic_dev_cmd_go(idev, &cmd);
122 }
123 
124 void
ionic_dev_cmd_port_state(struct ionic_dev * idev,uint8_t state)125 ionic_dev_cmd_port_state(struct ionic_dev *idev, uint8_t state)
126 {
127 	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 	ionic_dev_cmd_go(idev, &cmd);
135 }
136 
137 void
ionic_dev_cmd_port_speed(struct ionic_dev * idev,uint32_t speed)138 ionic_dev_cmd_port_speed(struct ionic_dev *idev, uint32_t speed)
139 {
140 	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 	ionic_dev_cmd_go(idev, &cmd);
148 }
149 
150 void
ionic_dev_cmd_port_mtu(struct ionic_dev * idev,uint32_t mtu)151 ionic_dev_cmd_port_mtu(struct ionic_dev *idev, uint32_t mtu)
152 {
153 	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 	ionic_dev_cmd_go(idev, &cmd);
161 }
162 
163 void
ionic_dev_cmd_port_autoneg(struct ionic_dev * idev,uint8_t an_enable)164 ionic_dev_cmd_port_autoneg(struct ionic_dev *idev, uint8_t an_enable)
165 {
166 	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 	ionic_dev_cmd_go(idev, &cmd);
174 }
175 
176 void
ionic_dev_cmd_port_fec(struct ionic_dev * idev,uint8_t fec_type)177 ionic_dev_cmd_port_fec(struct ionic_dev *idev, uint8_t fec_type)
178 {
179 	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 	ionic_dev_cmd_go(idev, &cmd);
187 }
188 
189 void
ionic_dev_cmd_port_pause(struct ionic_dev * idev,uint8_t pause_type)190 ionic_dev_cmd_port_pause(struct ionic_dev *idev, uint8_t pause_type)
191 {
192 	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 	ionic_dev_cmd_go(idev, &cmd);
200 }
201 
202 void
ionic_dev_cmd_port_loopback(struct ionic_dev * idev,uint8_t loopback_mode)203 ionic_dev_cmd_port_loopback(struct ionic_dev *idev, uint8_t loopback_mode)
204 {
205 	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 	ionic_dev_cmd_go(idev, &cmd);
213 }
214 
215 /* LIF commands */
216 
217 void
ionic_dev_cmd_queue_identify(struct ionic_dev * idev,uint16_t lif_type,uint8_t qtype,uint8_t qver)218 ionic_dev_cmd_queue_identify(struct ionic_dev *idev,
219 		uint16_t lif_type, uint8_t qtype, uint8_t qver)
220 {
221 	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 	ionic_dev_cmd_go(idev, &cmd);
229 }
230 
231 void
ionic_dev_cmd_lif_identify(struct ionic_dev * idev,uint8_t type,uint8_t ver)232 ionic_dev_cmd_lif_identify(struct ionic_dev *idev, uint8_t type, uint8_t ver)
233 {
234 	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 	ionic_dev_cmd_go(idev, &cmd);
241 }
242 
243 void
ionic_dev_cmd_lif_init(struct ionic_dev * idev,rte_iova_t info_pa)244 ionic_dev_cmd_lif_init(struct ionic_dev *idev, rte_iova_t info_pa)
245 {
246 	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 	ionic_dev_cmd_go(idev, &cmd);
252 }
253 
254 void
ionic_dev_cmd_lif_reset(struct ionic_dev * idev)255 ionic_dev_cmd_lif_reset(struct ionic_dev *idev)
256 {
257 	union ionic_dev_cmd cmd = {
258 		.lif_init.opcode = IONIC_CMD_LIF_RESET,
259 	};
260 
261 	ionic_dev_cmd_go(idev, &cmd);
262 }
263 
264 struct ionic_doorbell *
ionic_db_map(struct ionic_lif * lif,struct ionic_queue * q)265 ionic_db_map(struct ionic_lif *lif, struct ionic_queue *q)
266 {
267 	return lif->kern_dbpage + q->hw_type;
268 }
269 
270 void
ionic_intr_init(struct ionic_dev * idev,struct ionic_intr_info * intr,unsigned long index)271 ionic_intr_init(struct ionic_dev *idev, struct ionic_intr_info *intr,
272 		unsigned long index)
273 {
274 	ionic_intr_clean(idev->intr_ctrl, index);
275 	intr->index = index;
276 }
277 
278 void
ionic_dev_cmd_adminq_init(struct ionic_dev * idev,struct ionic_qcq * qcq)279 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 	union ionic_dev_cmd cmd = {
285 		.q_init.opcode = IONIC_CMD_Q_INIT,
286 		.q_init.type = q->type,
287 		.q_init.ver = qcq->lif->qtype_info[q->type].version,
288 		.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 		.q_init.ring_size = rte_log2_u32(q->num_descs),
292 		.q_init.ring_base = rte_cpu_to_le_64(q->base_pa),
293 		.q_init.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
294 	};
295 
296 	IONIC_PRINT(DEBUG, "adminq.q_init.ver %u", cmd.q_init.ver);
297 
298 	ionic_dev_cmd_go(idev, &cmd);
299 }
300 
301 int
ionic_cq_init(struct ionic_cq * cq,uint16_t num_descs)302 ionic_cq_init(struct ionic_cq *cq, uint16_t num_descs)
303 {
304 	if (!rte_is_power_of_2(num_descs) ||
305 	    num_descs < IONIC_MIN_RING_DESC ||
306 	    num_descs > IONIC_MAX_RING_DESC) {
307 		IONIC_PRINT(ERR, "%u descriptors (min: %u max: %u)",
308 			num_descs, IONIC_MIN_RING_DESC, IONIC_MAX_RING_DESC);
309 		return -EINVAL;
310 	}
311 
312 	cq->num_descs = num_descs;
313 	cq->size_mask = num_descs - 1;
314 	cq->tail_idx = 0;
315 	cq->done_color = 1;
316 
317 	return 0;
318 }
319 
320 void
ionic_cq_reset(struct ionic_cq * cq)321 ionic_cq_reset(struct ionic_cq *cq)
322 {
323 	cq->tail_idx = 0;
324 	cq->done_color = 1;
325 
326 	memset(cq->base, 0, sizeof(struct ionic_nop_comp) * cq->num_descs);
327 }
328 
329 void
ionic_cq_map(struct ionic_cq * cq,void * base,rte_iova_t base_pa)330 ionic_cq_map(struct ionic_cq *cq, void *base, rte_iova_t base_pa)
331 {
332 	cq->base = base;
333 	cq->base_pa = base_pa;
334 }
335 
336 uint32_t
ionic_cq_service(struct ionic_cq * cq,uint32_t work_to_do,ionic_cq_cb cb,void * cb_arg)337 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 	if (work_to_do == 0)
343 		return 0;
344 
345 	while (cb(cq, cq->tail_idx, cb_arg)) {
346 		cq->tail_idx = Q_NEXT_TO_SRVC(cq, 1);
347 		if (cq->tail_idx == 0)
348 			cq->done_color = !cq->done_color;
349 
350 		if (++work_done == work_to_do)
351 			break;
352 	}
353 
354 	return work_done;
355 }
356 
357 int
ionic_q_init(struct ionic_queue * q,uint32_t index,uint16_t num_descs)358 ionic_q_init(struct ionic_queue *q, uint32_t index, uint16_t num_descs)
359 {
360 	uint32_t ring_size;
361 
362 	if (!rte_is_power_of_2(num_descs))
363 		return -EINVAL;
364 
365 	ring_size = rte_log2_u32(num_descs);
366 	if (ring_size < 2 || ring_size > 16)
367 		return -EINVAL;
368 
369 	q->index = index;
370 	q->num_descs = num_descs;
371 	q->size_mask = num_descs - 1;
372 	ionic_q_reset(q);
373 
374 	return 0;
375 }
376 
377 void
ionic_q_map(struct ionic_queue * q,void * base,rte_iova_t base_pa,void * cmb_base,rte_iova_t cmb_base_pa)378 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 	q->base = base;
382 	q->base_pa = base_pa;
383 	q->cmb_base = cmb_base;
384 	q->cmb_base_pa = cmb_base_pa;
385 }
386 
387 void
ionic_q_sg_map(struct ionic_queue * q,void * base,rte_iova_t base_pa)388 ionic_q_sg_map(struct ionic_queue *q, void *base, rte_iova_t base_pa)
389 {
390 	q->sg_base = base;
391 	q->sg_base_pa = base_pa;
392 }
393 
394 void
ionic_q_reset(struct ionic_queue * q)395 ionic_q_reset(struct ionic_queue *q)
396 {
397 	q->head_idx = 0;
398 	q->cmb_head_idx = 0;
399 	q->tail_idx = 0;
400 }
401