xref: /dpdk/drivers/net/netvsc/hn_nvs.c (revision 68a03efeed657e6e05f281479b33b51102797e15)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2018 Microsoft Corp.
3  * Copyright (c) 2010-2012 Citrix Inc.
4  * Copyright (c) 2012 NetApp Inc.
5  * All rights reserved.
6  */
7 
8 /*
9  * Network Virtualization Service.
10  */
11 
12 
13 #include <stdint.h>
14 #include <string.h>
15 #include <stdio.h>
16 #include <errno.h>
17 #include <unistd.h>
18 
19 #include <rte_ethdev.h>
20 #include <rte_string_fns.h>
21 #include <rte_memzone.h>
22 #include <rte_malloc.h>
23 #include <rte_atomic.h>
24 #include <rte_branch_prediction.h>
25 #include <rte_ether.h>
26 #include <rte_common.h>
27 #include <rte_errno.h>
28 #include <rte_cycles.h>
29 #include <rte_memory.h>
30 #include <rte_eal.h>
31 #include <rte_dev.h>
32 #include <rte_bus_vmbus.h>
33 
34 #include "hn_logs.h"
35 #include "hn_var.h"
36 #include "hn_nvs.h"
37 
38 static const uint32_t hn_nvs_version[] = {
39 	NVS_VERSION_61,
40 	NVS_VERSION_6,
41 	NVS_VERSION_5,
42 	NVS_VERSION_4,
43 	NVS_VERSION_2,
44 	NVS_VERSION_1
45 };
46 
47 static int hn_nvs_req_send(struct hn_data *hv,
48 			   void *req, uint32_t reqlen)
49 {
50 	return rte_vmbus_chan_send(hn_primary_chan(hv),
51 				   VMBUS_CHANPKT_TYPE_INBAND,
52 				   req, reqlen, 0,
53 				   VMBUS_CHANPKT_FLAG_NONE, NULL);
54 }
55 
56 static int
57 __hn_nvs_execute(struct hn_data *hv,
58 	       void *req, uint32_t reqlen,
59 	       void *resp, uint32_t resplen,
60 	       uint32_t type)
61 {
62 	struct vmbus_channel *chan = hn_primary_chan(hv);
63 	char buffer[NVS_RESPSIZE_MAX];
64 	const struct hn_nvs_hdr *hdr;
65 	uint64_t xactid;
66 	uint32_t len;
67 	int ret;
68 
69 	/* Send request to ring buffer */
70 	ret = rte_vmbus_chan_send(chan, VMBUS_CHANPKT_TYPE_INBAND,
71 				  req, reqlen, 0,
72 				  VMBUS_CHANPKT_FLAG_RC, NULL);
73 
74 	if (ret) {
75 		PMD_DRV_LOG(ERR, "send request failed: %d", ret);
76 		return ret;
77 	}
78 
79  retry:
80 	len = sizeof(buffer);
81 	ret = rte_vmbus_chan_recv(chan, buffer, &len, &xactid);
82 	if (ret == -EAGAIN) {
83 		rte_delay_us(HN_CHAN_INTERVAL_US);
84 		goto retry;
85 	}
86 
87 	if (ret < 0) {
88 		PMD_DRV_LOG(ERR, "recv response failed: %d", ret);
89 		return ret;
90 	}
91 
92 	if (len < sizeof(*hdr)) {
93 		PMD_DRV_LOG(ERR, "response missing NVS header");
94 		return -EINVAL;
95 	}
96 
97 	hdr = (struct hn_nvs_hdr *)buffer;
98 
99 	/* Silently drop received packets while waiting for response */
100 	switch (hdr->type) {
101 	case NVS_TYPE_RNDIS:
102 		hn_nvs_ack_rxbuf(chan, xactid);
103 		/* fallthrough */
104 
105 	case NVS_TYPE_TXTBL_NOTE:
106 		PMD_DRV_LOG(DEBUG, "discard packet type 0x%x", hdr->type);
107 		goto retry;
108 	}
109 
110 	if (hdr->type != type) {
111 		PMD_DRV_LOG(ERR, "unexpected NVS resp %#x, expect %#x",
112 			    hdr->type, type);
113 		return -EINVAL;
114 	}
115 
116 	if (len < resplen) {
117 		PMD_DRV_LOG(ERR,
118 			    "invalid NVS resp len %u (expect %u)",
119 			    len, resplen);
120 		return -EINVAL;
121 	}
122 
123 	memcpy(resp, buffer, resplen);
124 
125 	/* All pass! */
126 	return 0;
127 }
128 
129 
130 /*
131  * Execute one control command and get the response.
132  * Only one command can be active on a channel at once
133  * Unlike BSD, DPDK does not have an interrupt context
134  * so the polling is required to wait for response.
135  */
136 static int
137 hn_nvs_execute(struct hn_data *hv,
138 	       void *req, uint32_t reqlen,
139 	       void *resp, uint32_t resplen,
140 	       uint32_t type)
141 {
142 	struct hn_rx_queue *rxq = hv->primary;
143 	int ret;
144 
145 	rte_spinlock_lock(&rxq->ring_lock);
146 	ret = __hn_nvs_execute(hv, req, reqlen, resp, resplen, type);
147 	rte_spinlock_unlock(&rxq->ring_lock);
148 
149 	return ret;
150 }
151 
152 static int
153 hn_nvs_doinit(struct hn_data *hv, uint32_t nvs_ver)
154 {
155 	struct hn_nvs_init init;
156 	struct hn_nvs_init_resp resp;
157 	uint32_t status;
158 	int error;
159 
160 	memset(&init, 0, sizeof(init));
161 	init.type = NVS_TYPE_INIT;
162 	init.ver_min = nvs_ver;
163 	init.ver_max = nvs_ver;
164 
165 	error = hn_nvs_execute(hv, &init, sizeof(init),
166 			       &resp, sizeof(resp),
167 			       NVS_TYPE_INIT_RESP);
168 	if (error)
169 		return error;
170 
171 	status = resp.status;
172 	if (status != NVS_STATUS_OK) {
173 		/* Not fatal, try other versions */
174 		PMD_INIT_LOG(DEBUG, "nvs init failed for ver 0x%x",
175 			     nvs_ver);
176 		return -EINVAL;
177 	}
178 
179 	return 0;
180 }
181 
182 static int
183 hn_nvs_conn_rxbuf(struct hn_data *hv)
184 {
185 	struct hn_nvs_rxbuf_conn conn;
186 	struct hn_nvs_rxbuf_connresp resp;
187 	uint32_t status;
188 	int error;
189 
190 	/* Kernel has already setup RXBUF on primary channel. */
191 
192 	/*
193 	 * Connect RXBUF to NVS.
194 	 */
195 	conn.type = NVS_TYPE_RXBUF_CONN;
196 	conn.gpadl = hv->rxbuf_res->phys_addr;
197 	conn.sig = NVS_RXBUF_SIG;
198 	PMD_DRV_LOG(DEBUG, "connect rxbuff va=%p gpad=%#" PRIx64,
199 		    hv->rxbuf_res->addr,
200 		    hv->rxbuf_res->phys_addr);
201 
202 	error = hn_nvs_execute(hv, &conn, sizeof(conn),
203 			       &resp, sizeof(resp),
204 			       NVS_TYPE_RXBUF_CONNRESP);
205 	if (error) {
206 		PMD_DRV_LOG(ERR,
207 			    "exec nvs rxbuf conn failed: %d",
208 			    error);
209 		return error;
210 	}
211 
212 	status = resp.status;
213 	if (status != NVS_STATUS_OK) {
214 		PMD_DRV_LOG(ERR,
215 			    "nvs rxbuf conn failed: %x", status);
216 		return -EIO;
217 	}
218 	if (resp.nsect != 1) {
219 		PMD_DRV_LOG(ERR,
220 			    "nvs rxbuf response num sections %u != 1",
221 			    resp.nsect);
222 		return -EIO;
223 	}
224 
225 	PMD_DRV_LOG(INFO,
226 		    "receive buffer size %u count %u",
227 		    resp.nvs_sect[0].slotsz,
228 		    resp.nvs_sect[0].slotcnt);
229 	hv->rxbuf_section_cnt = resp.nvs_sect[0].slotcnt;
230 
231 	/*
232 	 * Pimary queue's rxbuf_info is not allocated at creation time.
233 	 * Now we can allocate it after we figure out the slotcnt.
234 	 */
235 	hv->primary->rxbuf_info = rte_calloc("HN_RXBUF_INFO",
236 			hv->rxbuf_section_cnt,
237 			sizeof(*hv->primary->rxbuf_info),
238 			RTE_CACHE_LINE_SIZE);
239 	if (!hv->primary->rxbuf_info) {
240 		PMD_DRV_LOG(ERR,
241 			    "could not allocate rxbuf info");
242 		return -ENOMEM;
243 	}
244 
245 	return 0;
246 }
247 
248 static void
249 hn_nvs_disconn_rxbuf(struct hn_data *hv)
250 {
251 	struct hn_nvs_rxbuf_disconn disconn;
252 	int error;
253 
254 	/*
255 	 * Disconnect RXBUF from NVS.
256 	 */
257 	memset(&disconn, 0, sizeof(disconn));
258 	disconn.type = NVS_TYPE_RXBUF_DISCONN;
259 	disconn.sig = NVS_RXBUF_SIG;
260 
261 	/* NOTE: No response. */
262 	error = hn_nvs_req_send(hv, &disconn, sizeof(disconn));
263 	if (error) {
264 		PMD_DRV_LOG(ERR,
265 			    "send nvs rxbuf disconn failed: %d",
266 			    error);
267 	}
268 
269 	/*
270 	 * Linger long enough for NVS to disconnect RXBUF.
271 	 */
272 	rte_delay_ms(200);
273 }
274 
275 static void
276 hn_nvs_disconn_chim(struct hn_data *hv)
277 {
278 	int error;
279 
280 	if (hv->chim_cnt != 0) {
281 		struct hn_nvs_chim_disconn disconn;
282 
283 		/* Disconnect chimney sending buffer from NVS. */
284 		memset(&disconn, 0, sizeof(disconn));
285 		disconn.type = NVS_TYPE_CHIM_DISCONN;
286 		disconn.sig = NVS_CHIM_SIG;
287 
288 		/* NOTE: No response. */
289 		error = hn_nvs_req_send(hv, &disconn, sizeof(disconn));
290 
291 		if (error) {
292 			PMD_DRV_LOG(ERR,
293 				    "send nvs chim disconn failed: %d", error);
294 		}
295 
296 		hv->chim_cnt = 0;
297 		/*
298 		 * Linger long enough for NVS to disconnect chimney
299 		 * sending buffer.
300 		 */
301 		rte_delay_ms(200);
302 	}
303 }
304 
305 static int
306 hn_nvs_conn_chim(struct hn_data *hv)
307 {
308 	struct hn_nvs_chim_conn chim;
309 	struct hn_nvs_chim_connresp resp;
310 	uint32_t sectsz;
311 	unsigned long len = hv->chim_res->len;
312 	int error;
313 
314 	/* Connect chimney sending buffer to NVS */
315 	memset(&chim, 0, sizeof(chim));
316 	chim.type = NVS_TYPE_CHIM_CONN;
317 	chim.gpadl = hv->chim_res->phys_addr;
318 	chim.sig = NVS_CHIM_SIG;
319 	PMD_DRV_LOG(DEBUG, "connect send buf va=%p gpad=%#" PRIx64,
320 		    hv->chim_res->addr,
321 		    hv->chim_res->phys_addr);
322 
323 	error = hn_nvs_execute(hv, &chim, sizeof(chim),
324 			       &resp, sizeof(resp),
325 			       NVS_TYPE_CHIM_CONNRESP);
326 	if (error) {
327 		PMD_DRV_LOG(ERR, "exec nvs chim conn failed");
328 		return error;
329 	}
330 
331 	if (resp.status != NVS_STATUS_OK) {
332 		PMD_DRV_LOG(ERR, "nvs chim conn failed: %x",
333 			    resp.status);
334 		return -EIO;
335 	}
336 
337 	sectsz = resp.sectsz;
338 	if (sectsz == 0 || sectsz & (sizeof(uint32_t) - 1)) {
339 		/* Can't use chimney sending buffer; done! */
340 		PMD_DRV_LOG(NOTICE,
341 			    "invalid chimney sending buffer section size: %u",
342 			    sectsz);
343 		error = -EINVAL;
344 		goto cleanup;
345 	}
346 
347 	hv->chim_szmax = sectsz;
348 	hv->chim_cnt = len / sectsz;
349 
350 	PMD_DRV_LOG(INFO, "send buffer %lu section size:%u, count:%u",
351 		    len, hv->chim_szmax, hv->chim_cnt);
352 
353 	/* Done! */
354 	return 0;
355 
356 cleanup:
357 	hn_nvs_disconn_chim(hv);
358 	return error;
359 }
360 
361 /*
362  * Configure MTU and enable VLAN.
363  */
364 static int
365 hn_nvs_conf_ndis(struct hn_data *hv, unsigned int mtu)
366 {
367 	struct hn_nvs_ndis_conf conf;
368 	int error;
369 
370 	memset(&conf, 0, sizeof(conf));
371 	conf.type = NVS_TYPE_NDIS_CONF;
372 	conf.mtu = mtu + RTE_ETHER_HDR_LEN;
373 	conf.caps = NVS_NDIS_CONF_VLAN;
374 
375 	/* enable SRIOV */
376 	if (hv->nvs_ver >= NVS_VERSION_5)
377 		conf.caps |= NVS_NDIS_CONF_SRIOV;
378 
379 	/* NOTE: No response. */
380 	error = hn_nvs_req_send(hv, &conf, sizeof(conf));
381 	if (error) {
382 		PMD_DRV_LOG(ERR,
383 			    "send nvs ndis conf failed: %d", error);
384 		return error;
385 	}
386 
387 	return 0;
388 }
389 
390 static int
391 hn_nvs_init_ndis(struct hn_data *hv)
392 {
393 	struct hn_nvs_ndis_init ndis;
394 	int error;
395 
396 	memset(&ndis, 0, sizeof(ndis));
397 	ndis.type = NVS_TYPE_NDIS_INIT;
398 	ndis.ndis_major = NDIS_VERSION_MAJOR(hv->ndis_ver);
399 	ndis.ndis_minor = NDIS_VERSION_MINOR(hv->ndis_ver);
400 
401 	/* NOTE: No response. */
402 	error = hn_nvs_req_send(hv, &ndis, sizeof(ndis));
403 	if (error)
404 		PMD_DRV_LOG(ERR,
405 			    "send nvs ndis init failed: %d", error);
406 
407 	return error;
408 }
409 
410 static int
411 hn_nvs_init(struct hn_data *hv)
412 {
413 	unsigned int i;
414 	int error;
415 
416 	/*
417 	 * Find the supported NVS version and set NDIS version accordingly.
418 	 */
419 	for (i = 0; i < RTE_DIM(hn_nvs_version); ++i) {
420 		error = hn_nvs_doinit(hv, hn_nvs_version[i]);
421 		if (error) {
422 			PMD_INIT_LOG(DEBUG, "version %#x error %d",
423 				     hn_nvs_version[i], error);
424 			continue;
425 		}
426 
427 		hv->nvs_ver = hn_nvs_version[i];
428 
429 		/* Set NDIS version according to NVS version. */
430 		hv->ndis_ver = NDIS_VERSION_6_30;
431 		if (hv->nvs_ver <= NVS_VERSION_4)
432 			hv->ndis_ver = NDIS_VERSION_6_1;
433 
434 		PMD_INIT_LOG(DEBUG,
435 			     "NVS version %#x, NDIS version %u.%u",
436 			     hv->nvs_ver, NDIS_VERSION_MAJOR(hv->ndis_ver),
437 			     NDIS_VERSION_MINOR(hv->ndis_ver));
438 		return 0;
439 	}
440 
441 	PMD_DRV_LOG(ERR,
442 		    "no NVS compatible version available");
443 	return -ENXIO;
444 }
445 
446 int
447 hn_nvs_attach(struct hn_data *hv, unsigned int mtu)
448 {
449 	int error;
450 
451 	/*
452 	 * Initialize NVS.
453 	 */
454 	error = hn_nvs_init(hv);
455 	if (error)
456 		return error;
457 
458 	/** Configure NDIS before initializing it. */
459 	if (hv->nvs_ver >= NVS_VERSION_2) {
460 		error = hn_nvs_conf_ndis(hv, mtu);
461 		if (error)
462 			return error;
463 	}
464 
465 	/*
466 	 * Initialize NDIS.
467 	 */
468 	error = hn_nvs_init_ndis(hv);
469 	if (error)
470 		return error;
471 
472 	/*
473 	 * Connect RXBUF.
474 	 */
475 	error = hn_nvs_conn_rxbuf(hv);
476 	if (error)
477 		return error;
478 
479 	/*
480 	 * Connect chimney sending buffer.
481 	 */
482 	error = hn_nvs_conn_chim(hv);
483 	if (error) {
484 		hn_nvs_disconn_rxbuf(hv);
485 		return error;
486 	}
487 
488 	return 0;
489 }
490 
491 void
492 hn_nvs_detach(struct hn_data *hv __rte_unused)
493 {
494 	PMD_INIT_FUNC_TRACE();
495 
496 	/* NOTE: there are no requests to stop the NVS. */
497 	hn_nvs_disconn_rxbuf(hv);
498 	hn_nvs_disconn_chim(hv);
499 }
500 
501 /*
502  * Ack the consumed RXBUF associated w/ this channel packet,
503  * so that this RXBUF can be recycled by the hypervisor.
504  */
505 void
506 hn_nvs_ack_rxbuf(struct vmbus_channel *chan, uint64_t tid)
507 {
508 	unsigned int retries = 0;
509 	struct hn_nvs_rndis_ack ack = {
510 		.type = NVS_TYPE_RNDIS_ACK,
511 		.status = NVS_STATUS_OK,
512 	};
513 	int error;
514 
515 	PMD_RX_LOG(DEBUG, "ack RX id %" PRIu64, tid);
516 
517  again:
518 	error = rte_vmbus_chan_send(chan, VMBUS_CHANPKT_TYPE_COMP,
519 				    &ack, sizeof(ack), tid,
520 				    VMBUS_CHANPKT_FLAG_NONE, NULL);
521 
522 	if (error == 0)
523 		return;
524 
525 	if (error == -EAGAIN) {
526 		/*
527 		 * NOTE:
528 		 * This should _not_ happen in real world, since the
529 		 * consumption of the TX bufring from the TX path is
530 		 * controlled.
531 		 */
532 		PMD_RX_LOG(NOTICE, "RXBUF ack retry");
533 		if (++retries < 10) {
534 			rte_delay_ms(1);
535 			goto again;
536 		}
537 	}
538 	/* RXBUF leaks! */
539 	PMD_DRV_LOG(ERR, "RXBUF ack failed");
540 }
541 
542 int
543 hn_nvs_alloc_subchans(struct hn_data *hv, uint32_t *nsubch)
544 {
545 	struct hn_nvs_subch_req req;
546 	struct hn_nvs_subch_resp resp;
547 	int error;
548 
549 	memset(&req, 0, sizeof(req));
550 	req.type = NVS_TYPE_SUBCH_REQ;
551 	req.op = NVS_SUBCH_OP_ALLOC;
552 	req.nsubch = *nsubch;
553 
554 	error = hn_nvs_execute(hv, &req, sizeof(req),
555 			       &resp, sizeof(resp),
556 			       NVS_TYPE_SUBCH_RESP);
557 	if (error)
558 		return error;
559 
560 	if (resp.status != NVS_STATUS_OK) {
561 		PMD_INIT_LOG(ERR,
562 			     "nvs subch alloc failed: %#x",
563 			     resp.status);
564 		return -EIO;
565 	}
566 
567 	if (resp.nsubch > *nsubch) {
568 		PMD_INIT_LOG(NOTICE,
569 			     "%u subchans are allocated, requested %u",
570 			     resp.nsubch, *nsubch);
571 	}
572 	*nsubch = resp.nsubch;
573 
574 	return 0;
575 }
576 
577 int
578 hn_nvs_set_datapath(struct hn_data *hv, uint32_t path)
579 {
580 	struct hn_nvs_datapath dp;
581 	int error;
582 
583 	PMD_DRV_LOG(DEBUG, "set datapath %s",
584 		    path ? "VF" : "Synthetic");
585 
586 	memset(&dp, 0, sizeof(dp));
587 	dp.type = NVS_TYPE_SET_DATAPATH;
588 	dp.active_path = path;
589 
590 	error = hn_nvs_req_send(hv, &dp, sizeof(dp));
591 	if (error) {
592 		PMD_DRV_LOG(ERR,
593 			    "send set datapath failed: %d",
594 			    error);
595 	}
596 
597 	return error;
598 }
599