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