xref: /illumos-gate/usr/src/uts/common/io/vioif/vioif.c (revision 5f82aa32fbc5dc2c59bca6ff315f44a4c4c9ea86)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2013 Nexenta Inc.  All rights reserved.
14  * Copyright (c) 2014, 2016 by Delphix. All rights reserved.
15  */
16 
17 /* Based on the NetBSD virtio driver by Minoura Makoto. */
18 /*
19  * Copyright (c) 2010 Minoura Makoto.
20  * All rights reserved.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the above copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  *
31  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
32  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
33  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
35  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
40  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41  */
42 
43 #include <sys/types.h>
44 #include <sys/errno.h>
45 #include <sys/param.h>
46 #include <sys/stropts.h>
47 #include <sys/stream.h>
48 #include <sys/strsubr.h>
49 #include <sys/kmem.h>
50 #include <sys/conf.h>
51 #include <sys/devops.h>
52 #include <sys/ksynch.h>
53 #include <sys/stat.h>
54 #include <sys/modctl.h>
55 #include <sys/debug.h>
56 #include <sys/pci.h>
57 #include <sys/ethernet.h>
58 #include <sys/vlan.h>
59 
60 #include <sys/dlpi.h>
61 #include <sys/taskq.h>
62 #include <sys/cyclic.h>
63 
64 #include <sys/pattr.h>
65 #include <sys/strsun.h>
66 
67 #include <sys/random.h>
68 #include <sys/sysmacros.h>
69 #include <sys/stream.h>
70 
71 #include <sys/mac.h>
72 #include <sys/mac_provider.h>
73 #include <sys/mac_ether.h>
74 
75 #include "virtiovar.h"
76 #include "virtioreg.h"
77 
78 /* Configuration registers */
79 #define	VIRTIO_NET_CONFIG_MAC		0 /* 8bit x 6byte */
80 #define	VIRTIO_NET_CONFIG_STATUS	6 /* 16bit */
81 
82 /* Feature bits */
83 #define	VIRTIO_NET_F_CSUM	(1 << 0) /* Host handles pkts w/ partial csum */
84 #define	VIRTIO_NET_F_GUEST_CSUM	(1 << 1) /* Guest handles pkts w/ part csum */
85 #define	VIRTIO_NET_F_MAC	(1 << 5) /* Host has given MAC address. */
86 #define	VIRTIO_NET_F_GSO	(1 << 6) /* Host handles pkts w/ any GSO type */
87 #define	VIRTIO_NET_F_GUEST_TSO4	(1 << 7) /* Guest can handle TSOv4 in. */
88 #define	VIRTIO_NET_F_GUEST_TSO6	(1 << 8) /* Guest can handle TSOv6 in. */
89 #define	VIRTIO_NET_F_GUEST_ECN	(1 << 9) /* Guest can handle TSO[6] w/ ECN in */
90 #define	VIRTIO_NET_F_GUEST_UFO	(1 << 10) /* Guest can handle UFO in. */
91 #define	VIRTIO_NET_F_HOST_TSO4	(1 << 11) /* Host can handle TSOv4 in. */
92 #define	VIRTIO_NET_F_HOST_TSO6	(1 << 12) /* Host can handle TSOv6 in. */
93 #define	VIRTIO_NET_F_HOST_ECN	(1 << 13) /* Host can handle TSO[6] w/ ECN in */
94 #define	VIRTIO_NET_F_HOST_UFO	(1 << 14) /* Host can handle UFO in. */
95 #define	VIRTIO_NET_F_MRG_RXBUF	(1 << 15) /* Host can merge receive buffers. */
96 #define	VIRTIO_NET_F_STATUS	(1 << 16) /* Config.status available */
97 #define	VIRTIO_NET_F_CTRL_VQ	(1 << 17) /* Control channel available */
98 #define	VIRTIO_NET_F_CTRL_RX	(1 << 18) /* Control channel RX mode support */
99 #define	VIRTIO_NET_F_CTRL_VLAN	(1 << 19) /* Control channel VLAN filtering */
100 #define	VIRTIO_NET_F_CTRL_RX_EXTRA (1 << 20) /* Extra RX mode control support */
101 
102 #define	VIRTIO_NET_FEATURE_BITS \
103 	"\020" \
104 	"\1CSUM" \
105 	"\2GUEST_CSUM" \
106 	"\6MAC" \
107 	"\7GSO" \
108 	"\10GUEST_TSO4" \
109 	"\11GUEST_TSO6" \
110 	"\12GUEST_ECN" \
111 	"\13GUEST_UFO" \
112 	"\14HOST_TSO4" \
113 	"\15HOST_TSO6" \
114 	"\16HOST_ECN" \
115 	"\17HOST_UFO" \
116 	"\20MRG_RXBUF" \
117 	"\21STATUS" \
118 	"\22CTRL_VQ" \
119 	"\23CTRL_RX" \
120 	"\24CTRL_VLAN" \
121 	"\25CTRL_RX_EXTRA"
122 
123 /* Status */
124 #define	VIRTIO_NET_S_LINK_UP	1
125 
126 #pragma pack(1)
127 /* Packet header structure */
128 struct virtio_net_hdr {
129 	uint8_t		flags;
130 	uint8_t		gso_type;
131 	uint16_t	hdr_len;
132 	uint16_t	gso_size;
133 	uint16_t	csum_start;
134 	uint16_t	csum_offset;
135 };
136 #pragma pack()
137 
138 #define	VIRTIO_NET_HDR_F_NEEDS_CSUM	1 /* flags */
139 #define	VIRTIO_NET_HDR_GSO_NONE		0 /* gso_type */
140 #define	VIRTIO_NET_HDR_GSO_TCPV4	1 /* gso_type */
141 #define	VIRTIO_NET_HDR_GSO_UDP		3 /* gso_type */
142 #define	VIRTIO_NET_HDR_GSO_TCPV6	4 /* gso_type */
143 #define	VIRTIO_NET_HDR_GSO_ECN		0x80 /* gso_type, |'ed */
144 
145 
146 /* Control virtqueue */
147 #pragma pack(1)
148 struct virtio_net_ctrl_cmd {
149 	uint8_t	class;
150 	uint8_t	command;
151 };
152 #pragma pack()
153 
154 #define	VIRTIO_NET_CTRL_RX		0
155 #define	VIRTIO_NET_CTRL_RX_PROMISC	0
156 #define	VIRTIO_NET_CTRL_RX_ALLMULTI	1
157 
158 #define	VIRTIO_NET_CTRL_MAC		1
159 #define	VIRTIO_NET_CTRL_MAC_TABLE_SET	0
160 
161 #define	VIRTIO_NET_CTRL_VLAN		2
162 #define	VIRTIO_NET_CTRL_VLAN_ADD	0
163 #define	VIRTIO_NET_CTRL_VLAN_DEL	1
164 
165 #pragma pack(1)
166 struct virtio_net_ctrl_status {
167 	uint8_t	ack;
168 };
169 
170 struct virtio_net_ctrl_rx {
171 	uint8_t	onoff;
172 };
173 
174 struct virtio_net_ctrl_mac_tbl {
175 	uint32_t nentries;
176 	uint8_t macs[][ETHERADDRL];
177 };
178 
179 struct virtio_net_ctrl_vlan {
180 	uint16_t id;
181 };
182 #pragma pack()
183 
184 static int vioif_quiesce(dev_info_t *);
185 static int vioif_attach(dev_info_t *, ddi_attach_cmd_t);
186 static int vioif_detach(dev_info_t *, ddi_detach_cmd_t);
187 
188 DDI_DEFINE_STREAM_OPS(vioif_ops,
189     nulldev,		/* identify */
190     nulldev,		/* probe */
191     vioif_attach,	/* attach */
192     vioif_detach,	/* detach */
193     nodev,		/* reset */
194     NULL,		/* cb_ops */
195     D_MP,		/* bus_ops */
196     NULL,		/* power */
197     vioif_quiesce	/* quiesce */);
198 
199 static char vioif_ident[] = "VirtIO ethernet driver";
200 
201 /* Standard Module linkage initialization for a Streams driver */
202 extern struct mod_ops mod_driverops;
203 
204 static struct modldrv modldrv = {
205 	&mod_driverops,		/* Type of module.  This one is a driver */
206 	vioif_ident,		/* short description */
207 	&vioif_ops		/* driver specific ops */
208 };
209 
210 static struct modlinkage modlinkage = {
211 	MODREV_1,
212 	{
213 		(void *)&modldrv,
214 		NULL,
215 	},
216 };
217 
218 ddi_device_acc_attr_t vioif_attr = {
219 	DDI_DEVICE_ATTR_V0,
220 	DDI_NEVERSWAP_ACC,	/* virtio is always native byte order */
221 	DDI_STORECACHING_OK_ACC,
222 	DDI_DEFAULT_ACC
223 };
224 
225 /*
226  * A mapping represents a binding for a single buffer that is contiguous in the
227  * virtual address space.
228  */
229 struct vioif_buf_mapping {
230 	caddr_t			vbm_buf;
231 	ddi_dma_handle_t	vbm_dmah;
232 	ddi_acc_handle_t	vbm_acch;
233 	ddi_dma_cookie_t	vbm_dmac;
234 	unsigned int		vbm_ncookies;
235 };
236 
237 /*
238  * Rx buffers can be loaned upstream, so the code has
239  * to allocate them dynamically.
240  */
241 struct vioif_rx_buf {
242 	struct vioif_softc	*rb_sc;
243 	frtn_t			rb_frtn;
244 
245 	struct vioif_buf_mapping rb_mapping;
246 };
247 
248 /*
249  * Tx buffers have two mapping types. One, "inline", is pre-allocated and is
250  * used to hold the virtio_net_header. Small packets also get copied there, as
251  * it's faster then mapping them. Bigger packets get mapped using the "external"
252  * mapping array. An array is used, because a packet may consist of muptiple
253  * fragments, so each fragment gets bound to an entry. According to my
254  * observations, the number of fragments does not exceed 2, but just in case,
255  * a bigger, up to VIOIF_INDIRECT_MAX - 1 array is allocated. To save resources,
256  * the dma handles are allocated lazily in the tx path.
257  */
258 struct vioif_tx_buf {
259 	mblk_t			*tb_mp;
260 
261 	/* inline buffer */
262 	struct vioif_buf_mapping tb_inline_mapping;
263 
264 	/* External buffers */
265 	struct vioif_buf_mapping *tb_external_mapping;
266 	unsigned int		tb_external_num;
267 };
268 
269 struct vioif_softc {
270 	dev_info_t		*sc_dev; /* mirrors virtio_softc->sc_dev */
271 	struct virtio_softc	sc_virtio;
272 
273 	mac_handle_t sc_mac_handle;
274 	mac_register_t *sc_macp;
275 
276 	struct virtqueue	*sc_rx_vq;
277 	struct virtqueue	*sc_tx_vq;
278 	struct virtqueue	*sc_ctrl_vq;
279 
280 	unsigned int		sc_tx_stopped:1;
281 
282 	/* Feature bits. */
283 	unsigned int		sc_rx_csum:1;
284 	unsigned int		sc_tx_csum:1;
285 	unsigned int		sc_tx_tso4:1;
286 
287 	int			sc_mtu;
288 	uint8_t			sc_mac[ETHERADDRL];
289 	/*
290 	 * For rx buffers, we keep a pointer array, because the buffers
291 	 * can be loaned upstream, and we have to repopulate the array with
292 	 * new members.
293 	 */
294 	struct vioif_rx_buf	**sc_rxbufs;
295 
296 	/*
297 	 * For tx, we just allocate an array of buffers. The packet can
298 	 * either be copied into the inline buffer, or the external mapping
299 	 * could be used to map the packet
300 	 */
301 	struct vioif_tx_buf	*sc_txbufs;
302 
303 	kstat_t			*sc_intrstat;
304 	/*
305 	 * We "loan" rx buffers upstream and reuse them after they are
306 	 * freed. This lets us avoid allocations in the hot path.
307 	 */
308 	kmem_cache_t		*sc_rxbuf_cache;
309 	ulong_t			sc_rxloan;
310 
311 	/* Copying small packets turns out to be faster then mapping them. */
312 	unsigned long		sc_rxcopy_thresh;
313 	unsigned long		sc_txcopy_thresh;
314 	/* Some statistic coming here */
315 	uint64_t		sc_ipackets;
316 	uint64_t		sc_opackets;
317 	uint64_t		sc_rbytes;
318 	uint64_t		sc_obytes;
319 	uint64_t		sc_brdcstxmt;
320 	uint64_t		sc_brdcstrcv;
321 	uint64_t		sc_multixmt;
322 	uint64_t		sc_multircv;
323 	uint64_t		sc_norecvbuf;
324 	uint64_t		sc_notxbuf;
325 	uint64_t		sc_ierrors;
326 	uint64_t		sc_oerrors;
327 };
328 
329 #define	ETHER_HEADER_LEN		sizeof (struct ether_header)
330 
331 /* MTU + the ethernet header. */
332 #define	MAX_PAYLOAD	65535
333 #define	MAX_MTU		(MAX_PAYLOAD - ETHER_HEADER_LEN)
334 #define	DEFAULT_MTU	ETHERMTU
335 
336 /*
337  * Yeah, we spend 8M per device. Turns out, there is no point
338  * being smart and using merged rx buffers (VIRTIO_NET_F_MRG_RXBUF),
339  * because vhost does not support them, and we expect to be used with
340  * vhost in production environment.
341  */
342 /* The buffer keeps both the packet data and the virtio_net_header. */
343 #define	VIOIF_RX_SIZE (MAX_PAYLOAD + sizeof (struct virtio_net_hdr))
344 
345 /*
346  * We win a bit on header alignment, but the host wins a lot
347  * more on moving aligned buffers. Might need more thought.
348  */
349 #define	VIOIF_IP_ALIGN 0
350 
351 /* Maximum number of indirect descriptors, somewhat arbitrary. */
352 #define	VIOIF_INDIRECT_MAX 128
353 
354 /*
355  * We pre-allocate a reasonably large buffer to copy small packets
356  * there. Bigger packets are mapped, packets with multiple
357  * cookies are mapped as indirect buffers.
358  */
359 #define	VIOIF_TX_INLINE_SIZE 2048
360 
361 /* Native queue size for all queues */
362 #define	VIOIF_RX_QLEN 0
363 #define	VIOIF_TX_QLEN 0
364 #define	VIOIF_CTRL_QLEN 0
365 
366 static uchar_t vioif_broadcast[ETHERADDRL] = {
367 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff
368 };
369 
370 #define	VIOIF_TX_THRESH_MAX	640
371 #define	VIOIF_RX_THRESH_MAX	640
372 
373 #define	CACHE_NAME_SIZE	32
374 
375 static char vioif_txcopy_thresh[] =
376 	"vioif_txcopy_thresh";
377 static char vioif_rxcopy_thresh[] =
378 	"vioif_rxcopy_thresh";
379 
380 static char *vioif_priv_props[] = {
381 	vioif_txcopy_thresh,
382 	vioif_rxcopy_thresh,
383 	NULL
384 };
385 
386 /* Add up to ddi? */
387 static ddi_dma_cookie_t *
388 vioif_dma_curr_cookie(ddi_dma_handle_t dmah)
389 {
390 	ddi_dma_impl_t *dmah_impl = (void *) dmah;
391 	ASSERT(dmah_impl->dmai_cookie);
392 	return (dmah_impl->dmai_cookie);
393 }
394 
395 static void
396 vioif_dma_reset_cookie(ddi_dma_handle_t dmah, ddi_dma_cookie_t *dmac)
397 {
398 	ddi_dma_impl_t *dmah_impl = (void *) dmah;
399 	dmah_impl->dmai_cookie = dmac;
400 }
401 
402 static link_state_t
403 vioif_link_state(struct vioif_softc *sc)
404 {
405 	if (sc->sc_virtio.sc_features & VIRTIO_NET_F_STATUS) {
406 		if (virtio_read_device_config_2(&sc->sc_virtio,
407 		    VIRTIO_NET_CONFIG_STATUS) & VIRTIO_NET_S_LINK_UP) {
408 			return (LINK_STATE_UP);
409 		} else {
410 			return (LINK_STATE_DOWN);
411 		}
412 	}
413 
414 	return (LINK_STATE_UP);
415 }
416 
417 static ddi_dma_attr_t vioif_inline_buf_dma_attr = {
418 	DMA_ATTR_V0,		/* Version number */
419 	0,			/* low address */
420 	0xFFFFFFFFFFFFFFFF,	/* high address */
421 	0xFFFFFFFF,		/* counter register max */
422 	1,			/* page alignment */
423 	1,			/* burst sizes: 1 - 32 */
424 	1,			/* minimum transfer size */
425 	0xFFFFFFFF,		/* max transfer size */
426 	0xFFFFFFFFFFFFFFF,	/* address register max */
427 	1,			/* scatter-gather capacity */
428 	1,			/* device operates on bytes */
429 	0,			/* attr flag: set to 0 */
430 };
431 
432 static ddi_dma_attr_t vioif_mapped_buf_dma_attr = {
433 	DMA_ATTR_V0,		/* Version number */
434 	0,			/* low address */
435 	0xFFFFFFFFFFFFFFFF,	/* high address */
436 	0xFFFFFFFF,		/* counter register max */
437 	1,			/* page alignment */
438 	1,			/* burst sizes: 1 - 32 */
439 	1,			/* minimum transfer size */
440 	0xFFFFFFFF,		/* max transfer size */
441 	0xFFFFFFFFFFFFFFF,	/* address register max */
442 
443 	/* One entry is used for the virtio_net_hdr on the tx path */
444 	VIOIF_INDIRECT_MAX - 1,	/* scatter-gather capacity */
445 	1,			/* device operates on bytes */
446 	0,			/* attr flag: set to 0 */
447 };
448 
449 static ddi_device_acc_attr_t vioif_bufattr = {
450 	DDI_DEVICE_ATTR_V0,
451 	DDI_NEVERSWAP_ACC,
452 	DDI_STORECACHING_OK_ACC,
453 	DDI_DEFAULT_ACC
454 };
455 
456 static void
457 vioif_rx_free(caddr_t free_arg)
458 {
459 	struct vioif_rx_buf *buf = (void *) free_arg;
460 	struct vioif_softc *sc = buf->rb_sc;
461 
462 	kmem_cache_free(sc->sc_rxbuf_cache, buf);
463 	atomic_dec_ulong(&sc->sc_rxloan);
464 }
465 
466 static int
467 vioif_rx_construct(void *buffer, void *user_arg, int kmflags)
468 {
469 	_NOTE(ARGUNUSED(kmflags));
470 	struct vioif_softc *sc = user_arg;
471 	struct vioif_rx_buf *buf = buffer;
472 	size_t len;
473 
474 	if (ddi_dma_alloc_handle(sc->sc_dev, &vioif_mapped_buf_dma_attr,
475 	    DDI_DMA_SLEEP, NULL, &buf->rb_mapping.vbm_dmah)) {
476 		dev_err(sc->sc_dev, CE_WARN,
477 		    "Can't allocate dma handle for rx buffer");
478 		goto exit_handle;
479 	}
480 
481 	if (ddi_dma_mem_alloc(buf->rb_mapping.vbm_dmah,
482 	    VIOIF_RX_SIZE + sizeof (struct virtio_net_hdr),
483 	    &vioif_bufattr, DDI_DMA_STREAMING, DDI_DMA_SLEEP,
484 	    NULL, &buf->rb_mapping.vbm_buf, &len, &buf->rb_mapping.vbm_acch)) {
485 		dev_err(sc->sc_dev, CE_WARN,
486 		    "Can't allocate rx buffer");
487 		goto exit_alloc;
488 	}
489 	ASSERT(len >= VIOIF_RX_SIZE);
490 
491 	if (ddi_dma_addr_bind_handle(buf->rb_mapping.vbm_dmah, NULL,
492 	    buf->rb_mapping.vbm_buf, len, DDI_DMA_READ | DDI_DMA_STREAMING,
493 	    DDI_DMA_SLEEP, NULL, &buf->rb_mapping.vbm_dmac,
494 	    &buf->rb_mapping.vbm_ncookies)) {
495 		dev_err(sc->sc_dev, CE_WARN, "Can't bind tx buffer");
496 
497 		goto exit_bind;
498 	}
499 
500 	ASSERT(buf->rb_mapping.vbm_ncookies <= VIOIF_INDIRECT_MAX);
501 
502 	buf->rb_sc = sc;
503 	buf->rb_frtn.free_arg = (void *) buf;
504 	buf->rb_frtn.free_func = vioif_rx_free;
505 
506 	return (0);
507 exit_bind:
508 	ddi_dma_mem_free(&buf->rb_mapping.vbm_acch);
509 exit_alloc:
510 	ddi_dma_free_handle(&buf->rb_mapping.vbm_dmah);
511 exit_handle:
512 
513 	return (ENOMEM);
514 }
515 
516 static void
517 vioif_rx_destruct(void *buffer, void *user_arg)
518 {
519 	_NOTE(ARGUNUSED(user_arg));
520 	struct vioif_rx_buf *buf = buffer;
521 
522 	ASSERT(buf->rb_mapping.vbm_acch);
523 	ASSERT(buf->rb_mapping.vbm_acch);
524 
525 	(void) ddi_dma_unbind_handle(buf->rb_mapping.vbm_dmah);
526 	ddi_dma_mem_free(&buf->rb_mapping.vbm_acch);
527 	ddi_dma_free_handle(&buf->rb_mapping.vbm_dmah);
528 }
529 
530 static void
531 vioif_free_mems(struct vioif_softc *sc)
532 {
533 	int i;
534 
535 	for (i = 0; i < sc->sc_tx_vq->vq_num; i++) {
536 		struct vioif_tx_buf *buf = &sc->sc_txbufs[i];
537 		int j;
538 
539 		/* Tear down the internal mapping. */
540 
541 		ASSERT(buf->tb_inline_mapping.vbm_acch);
542 		ASSERT(buf->tb_inline_mapping.vbm_dmah);
543 
544 		(void) ddi_dma_unbind_handle(buf->tb_inline_mapping.vbm_dmah);
545 		ddi_dma_mem_free(&buf->tb_inline_mapping.vbm_acch);
546 		ddi_dma_free_handle(&buf->tb_inline_mapping.vbm_dmah);
547 
548 		/* We should not see any in-flight buffers at this point. */
549 		ASSERT(!buf->tb_mp);
550 
551 		/* Free all the dma hdnales we allocated lazily. */
552 		for (j = 0; buf->tb_external_mapping[j].vbm_dmah; j++)
553 			ddi_dma_free_handle(
554 			    &buf->tb_external_mapping[j].vbm_dmah);
555 		/* Free the external mapping array. */
556 		kmem_free(buf->tb_external_mapping,
557 		    sizeof (struct vioif_tx_buf) * VIOIF_INDIRECT_MAX - 1);
558 	}
559 
560 	kmem_free(sc->sc_txbufs, sizeof (struct vioif_tx_buf) *
561 	    sc->sc_tx_vq->vq_num);
562 
563 	for (i = 0; i < sc->sc_rx_vq->vq_num; i++) {
564 		struct vioif_rx_buf *buf = sc->sc_rxbufs[i];
565 
566 		if (buf)
567 			kmem_cache_free(sc->sc_rxbuf_cache, buf);
568 	}
569 	kmem_free(sc->sc_rxbufs, sizeof (struct vioif_rx_buf *) *
570 	    sc->sc_rx_vq->vq_num);
571 }
572 
573 static int
574 vioif_alloc_mems(struct vioif_softc *sc)
575 {
576 	int i, txqsize, rxqsize;
577 	size_t len;
578 	unsigned int nsegments;
579 
580 	txqsize = sc->sc_tx_vq->vq_num;
581 	rxqsize = sc->sc_rx_vq->vq_num;
582 
583 	sc->sc_txbufs = kmem_zalloc(sizeof (struct vioif_tx_buf) * txqsize,
584 	    KM_SLEEP);
585 	if (sc->sc_txbufs == NULL) {
586 		dev_err(sc->sc_dev, CE_WARN,
587 		    "Failed to allocate the tx buffers array");
588 		goto exit_txalloc;
589 	}
590 
591 	/*
592 	 * We don't allocate the rx vioif_bufs, just the pointers, as
593 	 * rx vioif_bufs can be loaned upstream, and we don't know the
594 	 * total number we need.
595 	 */
596 	sc->sc_rxbufs = kmem_zalloc(sizeof (struct vioif_rx_buf *) * rxqsize,
597 	    KM_SLEEP);
598 	if (sc->sc_rxbufs == NULL) {
599 		dev_err(sc->sc_dev, CE_WARN,
600 		    "Failed to allocate the rx buffers pointer array");
601 		goto exit_rxalloc;
602 	}
603 
604 	for (i = 0; i < txqsize; i++) {
605 		struct vioif_tx_buf *buf = &sc->sc_txbufs[i];
606 
607 		/* Allocate and bind an inline mapping. */
608 
609 		if (ddi_dma_alloc_handle(sc->sc_dev,
610 		    &vioif_inline_buf_dma_attr,
611 		    DDI_DMA_SLEEP, NULL, &buf->tb_inline_mapping.vbm_dmah)) {
612 
613 			dev_err(sc->sc_dev, CE_WARN,
614 			    "Can't allocate dma handle for tx buffer %d", i);
615 			goto exit_tx;
616 		}
617 
618 		if (ddi_dma_mem_alloc(buf->tb_inline_mapping.vbm_dmah,
619 		    VIOIF_TX_INLINE_SIZE, &vioif_bufattr, DDI_DMA_STREAMING,
620 		    DDI_DMA_SLEEP, NULL, &buf->tb_inline_mapping.vbm_buf,
621 		    &len, &buf->tb_inline_mapping.vbm_acch)) {
622 
623 			dev_err(sc->sc_dev, CE_WARN,
624 			    "Can't allocate tx buffer %d", i);
625 			goto exit_tx;
626 		}
627 		ASSERT(len >= VIOIF_TX_INLINE_SIZE);
628 
629 		if (ddi_dma_addr_bind_handle(buf->tb_inline_mapping.vbm_dmah,
630 		    NULL, buf->tb_inline_mapping.vbm_buf, len,
631 		    DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL,
632 		    &buf->tb_inline_mapping.vbm_dmac, &nsegments)) {
633 
634 			dev_err(sc->sc_dev, CE_WARN,
635 			    "Can't bind tx buffer %d", i);
636 			goto exit_tx;
637 		}
638 
639 		/* We asked for a single segment */
640 		ASSERT(nsegments == 1);
641 
642 		/*
643 		 * We allow up to VIOIF_INDIRECT_MAX - 1 external mappings.
644 		 * In reality, I don't expect more then 2-3 used, but who
645 		 * knows.
646 		 */
647 		buf->tb_external_mapping = kmem_zalloc(
648 		    sizeof (struct vioif_tx_buf) * VIOIF_INDIRECT_MAX - 1,
649 		    KM_SLEEP);
650 
651 		/*
652 		 * The external mapping's dma handles are allocate lazily,
653 		 * as we don't expect most of them to be used..
654 		 */
655 	}
656 
657 	return (0);
658 
659 exit_tx:
660 	for (i = 0; i < txqsize; i++) {
661 		struct vioif_tx_buf *buf = &sc->sc_txbufs[i];
662 
663 		if (buf->tb_inline_mapping.vbm_dmah)
664 			(void) ddi_dma_unbind_handle(
665 			    buf->tb_inline_mapping.vbm_dmah);
666 
667 		if (buf->tb_inline_mapping.vbm_acch)
668 			ddi_dma_mem_free(
669 			    &buf->tb_inline_mapping.vbm_acch);
670 
671 		if (buf->tb_inline_mapping.vbm_dmah)
672 			ddi_dma_free_handle(
673 			    &buf->tb_inline_mapping.vbm_dmah);
674 
675 		if (buf->tb_external_mapping)
676 			kmem_free(buf->tb_external_mapping,
677 			    sizeof (struct vioif_tx_buf) *
678 			    VIOIF_INDIRECT_MAX - 1);
679 	}
680 
681 	kmem_free(sc->sc_rxbufs, sizeof (struct vioif_rx_buf) * rxqsize);
682 
683 exit_rxalloc:
684 	kmem_free(sc->sc_txbufs, sizeof (struct vioif_tx_buf) * txqsize);
685 exit_txalloc:
686 	return (ENOMEM);
687 }
688 
689 /* ARGSUSED */
690 int
691 vioif_multicst(void *arg, boolean_t add, const uint8_t *macaddr)
692 {
693 	return (DDI_SUCCESS);
694 }
695 
696 /* ARGSUSED */
697 int
698 vioif_promisc(void *arg, boolean_t on)
699 {
700 	return (DDI_SUCCESS);
701 }
702 
703 /* ARGSUSED */
704 int
705 vioif_unicst(void *arg, const uint8_t *macaddr)
706 {
707 	return (DDI_FAILURE);
708 }
709 
710 
711 static uint_t
712 vioif_add_rx(struct vioif_softc *sc, int kmflag)
713 {
714 	uint_t num_added = 0;
715 	struct vq_entry *ve;
716 
717 	while ((ve = vq_alloc_entry(sc->sc_rx_vq)) != NULL) {
718 		struct vioif_rx_buf *buf = sc->sc_rxbufs[ve->qe_index];
719 
720 		if (!buf) {
721 			/* First run, allocate the buffer. */
722 			buf = kmem_cache_alloc(sc->sc_rxbuf_cache, kmflag);
723 			sc->sc_rxbufs[ve->qe_index] = buf;
724 		}
725 
726 		/* Still nothing? Bye. */
727 		if (!buf) {
728 			dev_err(sc->sc_dev, CE_WARN,
729 			    "Can't allocate rx buffer");
730 			sc->sc_norecvbuf++;
731 			vq_free_entry(sc->sc_rx_vq, ve);
732 			break;
733 		}
734 
735 		ASSERT(buf->rb_mapping.vbm_ncookies >= 1);
736 
737 		/*
738 		 * For an unknown reason, the virtio_net_hdr must be placed
739 		 * as a separate virtio queue entry.
740 		 */
741 		virtio_ve_add_indirect_buf(ve,
742 		    buf->rb_mapping.vbm_dmac.dmac_laddress,
743 		    sizeof (struct virtio_net_hdr), B_FALSE);
744 
745 		/* Add the rest of the first cookie. */
746 		virtio_ve_add_indirect_buf(ve,
747 		    buf->rb_mapping.vbm_dmac.dmac_laddress +
748 		    sizeof (struct virtio_net_hdr),
749 		    buf->rb_mapping.vbm_dmac.dmac_size -
750 		    sizeof (struct virtio_net_hdr), B_FALSE);
751 
752 		/*
753 		 * If the buffer consists of a single cookie (unlikely for a
754 		 * 64-k buffer), we are done. Otherwise, add the rest of the
755 		 * cookies using indirect entries.
756 		 */
757 		if (buf->rb_mapping.vbm_ncookies > 1) {
758 			ddi_dma_cookie_t *first_extra_dmac;
759 			ddi_dma_cookie_t dmac;
760 			first_extra_dmac =
761 			    vioif_dma_curr_cookie(buf->rb_mapping.vbm_dmah);
762 
763 			ddi_dma_nextcookie(buf->rb_mapping.vbm_dmah, &dmac);
764 			virtio_ve_add_cookie(ve, buf->rb_mapping.vbm_dmah,
765 			    dmac, buf->rb_mapping.vbm_ncookies - 1, B_FALSE);
766 			vioif_dma_reset_cookie(buf->rb_mapping.vbm_dmah,
767 			    first_extra_dmac);
768 		}
769 
770 		virtio_push_chain(ve, B_FALSE);
771 		num_added++;
772 	}
773 
774 	return (num_added);
775 }
776 
777 static uint_t
778 vioif_populate_rx(struct vioif_softc *sc, int kmflag)
779 {
780 	uint_t num_added = vioif_add_rx(sc, kmflag);
781 
782 	if (num_added > 0)
783 		virtio_sync_vq(sc->sc_rx_vq);
784 
785 	return (num_added);
786 }
787 
788 static uint_t
789 vioif_process_rx(struct vioif_softc *sc)
790 {
791 	struct vq_entry *ve;
792 	struct vioif_rx_buf *buf;
793 	mblk_t *mphead = NULL, *lastmp = NULL, *mp;
794 	uint32_t len;
795 	uint_t num_processed = 0;
796 
797 	while ((ve = virtio_pull_chain(sc->sc_rx_vq, &len))) {
798 
799 		buf = sc->sc_rxbufs[ve->qe_index];
800 		ASSERT(buf);
801 
802 		if (len < sizeof (struct virtio_net_hdr)) {
803 			dev_err(sc->sc_dev, CE_WARN, "RX: Cnain too small: %u",
804 			    len - (uint32_t)sizeof (struct virtio_net_hdr));
805 			sc->sc_ierrors++;
806 			virtio_free_chain(ve);
807 			continue;
808 		}
809 
810 		len -= sizeof (struct virtio_net_hdr);
811 		/*
812 		 * We copy small packets that happen to fit into a single
813 		 * cookie and reuse the buffers. For bigger ones, we loan
814 		 * the buffers upstream.
815 		 */
816 		if (len < sc->sc_rxcopy_thresh) {
817 			mp = allocb(len, 0);
818 			if (!mp) {
819 				sc->sc_norecvbuf++;
820 				sc->sc_ierrors++;
821 
822 				virtio_free_chain(ve);
823 				break;
824 			}
825 
826 			bcopy((char *)buf->rb_mapping.vbm_buf +
827 			    sizeof (struct virtio_net_hdr), mp->b_rptr, len);
828 			mp->b_wptr = mp->b_rptr + len;
829 
830 		} else {
831 			mp = desballoc((unsigned char *)
832 			    buf->rb_mapping.vbm_buf +
833 			    sizeof (struct virtio_net_hdr) +
834 			    VIOIF_IP_ALIGN, len, 0, &buf->rb_frtn);
835 			if (!mp) {
836 				sc->sc_norecvbuf++;
837 				sc->sc_ierrors++;
838 
839 				virtio_free_chain(ve);
840 				break;
841 			}
842 			mp->b_wptr = mp->b_rptr + len;
843 
844 			atomic_inc_ulong(&sc->sc_rxloan);
845 			/*
846 			 * Buffer loaned, we will have to allocate a new one
847 			 * for this slot.
848 			 */
849 			sc->sc_rxbufs[ve->qe_index] = NULL;
850 		}
851 
852 		/*
853 		 * virtio-net does not tell us if this packet is multicast
854 		 * or broadcast, so we have to check it.
855 		 */
856 		if (mp->b_rptr[0] & 0x1) {
857 			if (bcmp(mp->b_rptr, vioif_broadcast, ETHERADDRL) != 0)
858 				sc->sc_multircv++;
859 			else
860 				sc->sc_brdcstrcv++;
861 		}
862 
863 		sc->sc_rbytes += len;
864 		sc->sc_ipackets++;
865 
866 		virtio_free_chain(ve);
867 
868 		if (lastmp == NULL) {
869 			mphead = mp;
870 		} else {
871 			lastmp->b_next = mp;
872 		}
873 		lastmp = mp;
874 		num_processed++;
875 	}
876 
877 	if (mphead != NULL) {
878 		mac_rx(sc->sc_mac_handle, NULL, mphead);
879 	}
880 
881 	return (num_processed);
882 }
883 
884 static uint_t
885 vioif_reclaim_used_tx(struct vioif_softc *sc)
886 {
887 	struct vq_entry *ve;
888 	struct vioif_tx_buf *buf;
889 	uint32_t len;
890 	mblk_t *mp;
891 	uint_t num_reclaimed = 0;
892 
893 	while ((ve = virtio_pull_chain(sc->sc_tx_vq, &len))) {
894 		/* We don't chain descriptors for tx, so don't expect any. */
895 		ASSERT(!ve->qe_next);
896 
897 		buf = &sc->sc_txbufs[ve->qe_index];
898 		mp = buf->tb_mp;
899 		buf->tb_mp = NULL;
900 
901 		if (mp) {
902 			for (int i = 0; i < buf->tb_external_num; i++)
903 				(void) ddi_dma_unbind_handle(
904 				    buf->tb_external_mapping[i].vbm_dmah);
905 		}
906 
907 		virtio_free_chain(ve);
908 
909 		/* External mapping used, mp was not freed in vioif_send() */
910 		if (mp)
911 			freemsg(mp);
912 		num_reclaimed++;
913 	}
914 
915 	if (sc->sc_tx_stopped && num_reclaimed > 0) {
916 		sc->sc_tx_stopped = 0;
917 		mac_tx_update(sc->sc_mac_handle);
918 	}
919 
920 	return (num_reclaimed);
921 }
922 
923 /* sc will be used to update stat counters. */
924 /* ARGSUSED */
925 static inline void
926 vioif_tx_inline(struct vioif_softc *sc, struct vq_entry *ve, mblk_t *mp,
927     size_t msg_size)
928 {
929 	struct vioif_tx_buf *buf;
930 	buf = &sc->sc_txbufs[ve->qe_index];
931 
932 	ASSERT(buf);
933 
934 	/* Frees mp */
935 	mcopymsg(mp, buf->tb_inline_mapping.vbm_buf +
936 	    sizeof (struct virtio_net_hdr));
937 
938 	virtio_ve_add_indirect_buf(ve,
939 	    buf->tb_inline_mapping.vbm_dmac.dmac_laddress +
940 	    sizeof (struct virtio_net_hdr), msg_size, B_TRUE);
941 }
942 
943 static inline int
944 vioif_tx_lazy_handle_alloc(struct vioif_softc *sc, struct vioif_tx_buf *buf,
945     int i)
946 {
947 	int ret = DDI_SUCCESS;
948 
949 	if (!buf->tb_external_mapping[i].vbm_dmah) {
950 		ret = ddi_dma_alloc_handle(sc->sc_dev,
951 		    &vioif_mapped_buf_dma_attr, DDI_DMA_SLEEP, NULL,
952 		    &buf->tb_external_mapping[i].vbm_dmah);
953 		if (ret != DDI_SUCCESS) {
954 			dev_err(sc->sc_dev, CE_WARN,
955 			    "Can't allocate dma handle for external tx buffer");
956 		}
957 	}
958 
959 	return (ret);
960 }
961 
962 static inline int
963 vioif_tx_external(struct vioif_softc *sc, struct vq_entry *ve, mblk_t *mp,
964     size_t msg_size)
965 {
966 	_NOTE(ARGUNUSED(msg_size));
967 
968 	struct vioif_tx_buf *buf;
969 	mblk_t *nmp;
970 	int i, j;
971 	int ret = DDI_SUCCESS;
972 
973 	buf = &sc->sc_txbufs[ve->qe_index];
974 
975 	ASSERT(buf);
976 
977 	buf->tb_external_num = 0;
978 	i = 0;
979 	nmp = mp;
980 
981 	while (nmp) {
982 		size_t len;
983 		ddi_dma_cookie_t dmac;
984 		unsigned int ncookies;
985 
986 		len = MBLKL(nmp);
987 		/*
988 		 * For some reason, the network stack can
989 		 * actually send us zero-length fragments.
990 		 */
991 		if (len == 0) {
992 			nmp = nmp->b_cont;
993 			continue;
994 		}
995 
996 		ret = vioif_tx_lazy_handle_alloc(sc, buf, i);
997 		if (ret != DDI_SUCCESS) {
998 			sc->sc_notxbuf++;
999 			sc->sc_oerrors++;
1000 			goto exit_lazy_alloc;
1001 		}
1002 		ret = ddi_dma_addr_bind_handle(
1003 		    buf->tb_external_mapping[i].vbm_dmah, NULL,
1004 		    (caddr_t)nmp->b_rptr, len,
1005 		    DDI_DMA_WRITE | DDI_DMA_STREAMING,
1006 		    DDI_DMA_SLEEP, NULL, &dmac, &ncookies);
1007 
1008 		if (ret != DDI_SUCCESS) {
1009 			sc->sc_oerrors++;
1010 			dev_err(sc->sc_dev, CE_NOTE,
1011 			    "TX: Failed to bind external handle");
1012 			goto exit_bind;
1013 		}
1014 
1015 		/* Check if we still fit into the indirect table. */
1016 		if (virtio_ve_indirect_available(ve) < ncookies) {
1017 			dev_err(sc->sc_dev, CE_NOTE,
1018 			    "TX: Indirect descriptor table limit reached."
1019 			    " It took %d fragments.", i);
1020 			sc->sc_notxbuf++;
1021 			sc->sc_oerrors++;
1022 
1023 			ret = DDI_FAILURE;
1024 			goto exit_limit;
1025 		}
1026 
1027 		virtio_ve_add_cookie(ve, buf->tb_external_mapping[i].vbm_dmah,
1028 		    dmac, ncookies, B_TRUE);
1029 
1030 		nmp = nmp->b_cont;
1031 		i++;
1032 	}
1033 
1034 	buf->tb_external_num = i;
1035 	/* Save the mp to free it when the packet is sent. */
1036 	buf->tb_mp = mp;
1037 
1038 	return (DDI_SUCCESS);
1039 
1040 exit_limit:
1041 exit_bind:
1042 exit_lazy_alloc:
1043 
1044 	for (j = 0; j < i; j++) {
1045 		(void) ddi_dma_unbind_handle(
1046 		    buf->tb_external_mapping[j].vbm_dmah);
1047 	}
1048 
1049 	return (ret);
1050 }
1051 
1052 static boolean_t
1053 vioif_send(struct vioif_softc *sc, mblk_t *mp)
1054 {
1055 	struct vq_entry *ve;
1056 	struct vioif_tx_buf *buf;
1057 	struct virtio_net_hdr *net_header = NULL;
1058 	size_t msg_size = 0;
1059 	uint32_t csum_start;
1060 	uint32_t csum_stuff;
1061 	uint32_t csum_flags;
1062 	uint32_t lso_flags;
1063 	uint32_t lso_mss;
1064 	mblk_t *nmp;
1065 	int ret;
1066 	boolean_t lso_required = B_FALSE;
1067 
1068 	for (nmp = mp; nmp; nmp = nmp->b_cont)
1069 		msg_size += MBLKL(nmp);
1070 
1071 	if (sc->sc_tx_tso4) {
1072 		mac_lso_get(mp, &lso_mss, &lso_flags);
1073 		lso_required = (lso_flags & HW_LSO);
1074 	}
1075 
1076 	ve = vq_alloc_entry(sc->sc_tx_vq);
1077 
1078 	if (!ve) {
1079 		sc->sc_notxbuf++;
1080 		/* Out of free descriptors - try later. */
1081 		return (B_FALSE);
1082 	}
1083 	buf = &sc->sc_txbufs[ve->qe_index];
1084 
1085 	/* Use the inline buffer of the first entry for the virtio_net_hdr. */
1086 	(void) memset(buf->tb_inline_mapping.vbm_buf, 0,
1087 	    sizeof (struct virtio_net_hdr));
1088 
1089 	net_header = (struct virtio_net_hdr *)buf->tb_inline_mapping.vbm_buf;
1090 
1091 	mac_hcksum_get(mp, &csum_start, &csum_stuff, NULL,
1092 	    NULL, &csum_flags);
1093 
1094 	/* They want us to do the TCP/UDP csum calculation. */
1095 	if (csum_flags & HCK_PARTIALCKSUM) {
1096 		struct ether_header *eth_header;
1097 		int eth_hsize;
1098 
1099 		/* Did we ask for it? */
1100 		ASSERT(sc->sc_tx_csum);
1101 
1102 		/* We only asked for partial csum packets. */
1103 		ASSERT(!(csum_flags & HCK_IPV4_HDRCKSUM));
1104 		ASSERT(!(csum_flags & HCK_FULLCKSUM));
1105 
1106 		eth_header = (void *) mp->b_rptr;
1107 		if (eth_header->ether_type == htons(ETHERTYPE_VLAN)) {
1108 			eth_hsize = sizeof (struct ether_vlan_header);
1109 		} else {
1110 			eth_hsize = sizeof (struct ether_header);
1111 		}
1112 		net_header->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
1113 		net_header->csum_start = eth_hsize + csum_start;
1114 		net_header->csum_offset = csum_stuff - csum_start;
1115 	}
1116 
1117 	/* setup LSO fields if required */
1118 	if (lso_required) {
1119 		net_header->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
1120 		net_header->gso_size = (uint16_t)lso_mss;
1121 	}
1122 
1123 	virtio_ve_add_indirect_buf(ve,
1124 	    buf->tb_inline_mapping.vbm_dmac.dmac_laddress,
1125 	    sizeof (struct virtio_net_hdr), B_TRUE);
1126 
1127 	/* meanwhile update the statistic */
1128 	if (mp->b_rptr[0] & 0x1) {
1129 		if (bcmp(mp->b_rptr, vioif_broadcast, ETHERADDRL) != 0)
1130 				sc->sc_multixmt++;
1131 			else
1132 				sc->sc_brdcstxmt++;
1133 	}
1134 
1135 	/*
1136 	 * We copy small packets into the inline buffer. The bigger ones
1137 	 * get mapped using the mapped buffer.
1138 	 */
1139 	if (msg_size < sc->sc_txcopy_thresh) {
1140 		vioif_tx_inline(sc, ve, mp, msg_size);
1141 	} else {
1142 		/* statistic gets updated by vioif_tx_external when fail */
1143 		ret = vioif_tx_external(sc, ve, mp, msg_size);
1144 		if (ret != DDI_SUCCESS)
1145 			goto exit_tx_external;
1146 	}
1147 
1148 	virtio_push_chain(ve, B_TRUE);
1149 
1150 	sc->sc_opackets++;
1151 	sc->sc_obytes += msg_size;
1152 
1153 	return (B_TRUE);
1154 
1155 exit_tx_external:
1156 
1157 	vq_free_entry(sc->sc_tx_vq, ve);
1158 	/*
1159 	 * vioif_tx_external can fail when the buffer does not fit into the
1160 	 * indirect descriptor table. Free the mp. I don't expect this ever
1161 	 * to happen.
1162 	 */
1163 	freemsg(mp);
1164 
1165 	return (B_TRUE);
1166 }
1167 
1168 mblk_t *
1169 vioif_tx(void *arg, mblk_t *mp)
1170 {
1171 	struct vioif_softc *sc = arg;
1172 	mblk_t	*nmp;
1173 
1174 	while (mp != NULL) {
1175 		nmp = mp->b_next;
1176 		mp->b_next = NULL;
1177 
1178 		if (!vioif_send(sc, mp)) {
1179 			sc->sc_tx_stopped = 1;
1180 			mp->b_next = nmp;
1181 			break;
1182 		}
1183 		mp = nmp;
1184 	}
1185 
1186 	return (mp);
1187 }
1188 
1189 int
1190 vioif_start(void *arg)
1191 {
1192 	struct vioif_softc *sc = arg;
1193 	struct vq_entry *ve;
1194 	uint32_t len;
1195 
1196 	mac_link_update(sc->sc_mac_handle,
1197 	    vioif_link_state(sc));
1198 
1199 	virtio_start_vq_intr(sc->sc_rx_vq);
1200 
1201 	/*
1202 	 * Don't start interrupts on sc_tx_vq. We use VIRTIO_F_NOTIFY_ON_EMPTY,
1203 	 * so the device will send a transmit interrupt when the queue is empty
1204 	 * and we can reclaim it in one sweep.
1205 	 */
1206 
1207 	/*
1208 	 * Clear any data that arrived early on the receive queue and populate
1209 	 * it with free buffers that the device can use moving forward.
1210 	 */
1211 	while ((ve = virtio_pull_chain(sc->sc_rx_vq, &len)) != NULL) {
1212 		virtio_free_chain(ve);
1213 	}
1214 	(void) vioif_populate_rx(sc, KM_SLEEP);
1215 
1216 	return (DDI_SUCCESS);
1217 }
1218 
1219 void
1220 vioif_stop(void *arg)
1221 {
1222 	struct vioif_softc *sc = arg;
1223 
1224 	virtio_stop_vq_intr(sc->sc_rx_vq);
1225 }
1226 
1227 /* ARGSUSED */
1228 static int
1229 vioif_stat(void *arg, uint_t stat, uint64_t *val)
1230 {
1231 	struct vioif_softc *sc = arg;
1232 
1233 	switch (stat) {
1234 	case MAC_STAT_IERRORS:
1235 		*val = sc->sc_ierrors;
1236 		break;
1237 	case MAC_STAT_OERRORS:
1238 		*val = sc->sc_oerrors;
1239 		break;
1240 	case MAC_STAT_MULTIRCV:
1241 		*val = sc->sc_multircv;
1242 		break;
1243 	case MAC_STAT_BRDCSTRCV:
1244 		*val = sc->sc_brdcstrcv;
1245 		break;
1246 	case MAC_STAT_MULTIXMT:
1247 		*val = sc->sc_multixmt;
1248 		break;
1249 	case MAC_STAT_BRDCSTXMT:
1250 		*val = sc->sc_brdcstxmt;
1251 		break;
1252 	case MAC_STAT_IPACKETS:
1253 		*val = sc->sc_ipackets;
1254 		break;
1255 	case MAC_STAT_RBYTES:
1256 		*val = sc->sc_rbytes;
1257 		break;
1258 	case MAC_STAT_OPACKETS:
1259 		*val = sc->sc_opackets;
1260 		break;
1261 	case MAC_STAT_OBYTES:
1262 		*val = sc->sc_obytes;
1263 		break;
1264 	case MAC_STAT_NORCVBUF:
1265 		*val = sc->sc_norecvbuf;
1266 		break;
1267 	case MAC_STAT_NOXMTBUF:
1268 		*val = sc->sc_notxbuf;
1269 		break;
1270 	case MAC_STAT_IFSPEED:
1271 		/* always 1 Gbit */
1272 		*val = 1000000000ULL;
1273 		break;
1274 	case ETHER_STAT_LINK_DUPLEX:
1275 		/* virtual device, always full-duplex */
1276 		*val = LINK_DUPLEX_FULL;
1277 		break;
1278 
1279 	default:
1280 		return (ENOTSUP);
1281 	}
1282 
1283 	return (DDI_SUCCESS);
1284 }
1285 
1286 static int
1287 vioif_set_prop_private(struct vioif_softc *sc, const char *pr_name,
1288     uint_t pr_valsize, const void *pr_val)
1289 {
1290 	_NOTE(ARGUNUSED(pr_valsize));
1291 
1292 	long result;
1293 
1294 	if (strcmp(pr_name, vioif_txcopy_thresh) == 0) {
1295 
1296 		if (pr_val == NULL)
1297 			return (EINVAL);
1298 
1299 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1300 
1301 		if (result < 0 || result > VIOIF_TX_THRESH_MAX)
1302 			return (EINVAL);
1303 		sc->sc_txcopy_thresh = result;
1304 	}
1305 	if (strcmp(pr_name, vioif_rxcopy_thresh) == 0) {
1306 
1307 		if (pr_val == NULL)
1308 			return (EINVAL);
1309 
1310 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1311 
1312 		if (result < 0 || result > VIOIF_RX_THRESH_MAX)
1313 			return (EINVAL);
1314 		sc->sc_rxcopy_thresh = result;
1315 	}
1316 	return (0);
1317 }
1318 
1319 static int
1320 vioif_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1321     uint_t pr_valsize, const void *pr_val)
1322 {
1323 	struct vioif_softc *sc = arg;
1324 	const uint32_t *new_mtu;
1325 	int err;
1326 
1327 	switch (pr_num) {
1328 	case MAC_PROP_MTU:
1329 		new_mtu = pr_val;
1330 
1331 		if (*new_mtu > MAX_MTU) {
1332 			return (EINVAL);
1333 		}
1334 
1335 		err = mac_maxsdu_update(sc->sc_mac_handle, *new_mtu);
1336 		if (err) {
1337 			return (err);
1338 		}
1339 		break;
1340 	case MAC_PROP_PRIVATE:
1341 		err = vioif_set_prop_private(sc, pr_name,
1342 		    pr_valsize, pr_val);
1343 		if (err)
1344 			return (err);
1345 		break;
1346 	default:
1347 		return (ENOTSUP);
1348 	}
1349 
1350 	return (0);
1351 }
1352 
1353 static int
1354 vioif_get_prop_private(struct vioif_softc *sc, const char *pr_name,
1355     uint_t pr_valsize, void *pr_val)
1356 {
1357 	int err = ENOTSUP;
1358 	int value;
1359 
1360 	if (strcmp(pr_name, vioif_txcopy_thresh) == 0) {
1361 
1362 		value = sc->sc_txcopy_thresh;
1363 		err = 0;
1364 		goto done;
1365 	}
1366 	if (strcmp(pr_name, vioif_rxcopy_thresh) == 0) {
1367 
1368 		value = sc->sc_rxcopy_thresh;
1369 		err = 0;
1370 		goto done;
1371 	}
1372 done:
1373 	if (err == 0) {
1374 		(void) snprintf(pr_val, pr_valsize, "%d", value);
1375 	}
1376 	return (err);
1377 }
1378 
1379 static int
1380 vioif_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1381     uint_t pr_valsize, void *pr_val)
1382 {
1383 	struct vioif_softc *sc = arg;
1384 	int err = ENOTSUP;
1385 
1386 	switch (pr_num) {
1387 	case MAC_PROP_PRIVATE:
1388 		err = vioif_get_prop_private(sc, pr_name,
1389 		    pr_valsize, pr_val);
1390 		break;
1391 	default:
1392 		break;
1393 	}
1394 	return (err);
1395 }
1396 
1397 static void
1398 vioif_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1399     mac_prop_info_handle_t prh)
1400 {
1401 	struct vioif_softc *sc = arg;
1402 	char valstr[64];
1403 	int value;
1404 
1405 	switch (pr_num) {
1406 	case MAC_PROP_MTU:
1407 		mac_prop_info_set_range_uint32(prh, ETHERMIN, MAX_MTU);
1408 		break;
1409 
1410 	case MAC_PROP_PRIVATE:
1411 		bzero(valstr, sizeof (valstr));
1412 		if (strcmp(pr_name, vioif_txcopy_thresh) == 0) {
1413 
1414 			value = sc->sc_txcopy_thresh;
1415 		} else	if (strcmp(pr_name,
1416 		    vioif_rxcopy_thresh) == 0) {
1417 			value = sc->sc_rxcopy_thresh;
1418 		} else {
1419 			return;
1420 		}
1421 		(void) snprintf(valstr, sizeof (valstr), "%d", value);
1422 		break;
1423 
1424 	default:
1425 		break;
1426 	}
1427 }
1428 
1429 static boolean_t
1430 vioif_getcapab(void *arg, mac_capab_t cap, void *cap_data)
1431 {
1432 	struct vioif_softc *sc = arg;
1433 
1434 	switch (cap) {
1435 	case MAC_CAPAB_HCKSUM:
1436 		if (sc->sc_tx_csum) {
1437 			uint32_t *txflags = cap_data;
1438 
1439 			*txflags = HCKSUM_INET_PARTIAL;
1440 			return (B_TRUE);
1441 		}
1442 		return (B_FALSE);
1443 	case MAC_CAPAB_LSO:
1444 		if (sc->sc_tx_tso4) {
1445 			mac_capab_lso_t *cap_lso = cap_data;
1446 
1447 			cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
1448 			cap_lso->lso_basic_tcp_ipv4.lso_max = MAX_MTU;
1449 			return (B_TRUE);
1450 		}
1451 		return (B_FALSE);
1452 	default:
1453 		break;
1454 	}
1455 	return (B_FALSE);
1456 }
1457 
1458 static mac_callbacks_t vioif_m_callbacks = {
1459 	.mc_callbacks	= (MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO),
1460 	.mc_getstat	= vioif_stat,
1461 	.mc_start	= vioif_start,
1462 	.mc_stop	= vioif_stop,
1463 	.mc_setpromisc	= vioif_promisc,
1464 	.mc_multicst	= vioif_multicst,
1465 	.mc_unicst	= vioif_unicst,
1466 	.mc_tx		= vioif_tx,
1467 	/* Optional callbacks */
1468 	.mc_reserved	= NULL,		/* reserved */
1469 	.mc_ioctl	= NULL,		/* mc_ioctl */
1470 	.mc_getcapab	= vioif_getcapab,		/* mc_getcapab */
1471 	.mc_open	= NULL,		/* mc_open */
1472 	.mc_close	= NULL,		/* mc_close */
1473 	.mc_setprop	= vioif_setprop,
1474 	.mc_getprop	= vioif_getprop,
1475 	.mc_propinfo	= vioif_propinfo,
1476 };
1477 
1478 static void
1479 vioif_show_features(struct vioif_softc *sc, const char *prefix,
1480     uint32_t features)
1481 {
1482 	char buf[512];
1483 	char *bufp = buf;
1484 	char *bufend = buf + sizeof (buf);
1485 
1486 	/* LINTED E_PTRDIFF_OVERFLOW */
1487 	bufp += snprintf(bufp, bufend - bufp, prefix);
1488 	/* LINTED E_PTRDIFF_OVERFLOW */
1489 	bufp += virtio_show_features(features, bufp, bufend - bufp);
1490 	*bufp = '\0';
1491 
1492 
1493 	/* Using '!' to only CE_NOTE this to the system log. */
1494 	dev_err(sc->sc_dev, CE_NOTE, "!%s Vioif (%b)", buf, features,
1495 	    VIRTIO_NET_FEATURE_BITS);
1496 }
1497 
1498 /*
1499  * Find out which features are supported by the device and
1500  * choose which ones we wish to use.
1501  */
1502 static int
1503 vioif_dev_features(struct vioif_softc *sc)
1504 {
1505 	uint32_t host_features;
1506 
1507 	host_features = virtio_negotiate_features(&sc->sc_virtio,
1508 	    VIRTIO_NET_F_CSUM |
1509 	    VIRTIO_NET_F_HOST_TSO4 |
1510 	    VIRTIO_NET_F_HOST_ECN |
1511 	    VIRTIO_NET_F_MAC |
1512 	    VIRTIO_NET_F_STATUS |
1513 	    VIRTIO_F_RING_INDIRECT_DESC |
1514 	    VIRTIO_F_NOTIFY_ON_EMPTY);
1515 
1516 	vioif_show_features(sc, "Host features: ", host_features);
1517 	vioif_show_features(sc, "Negotiated features: ",
1518 	    sc->sc_virtio.sc_features);
1519 
1520 	if (!(sc->sc_virtio.sc_features & VIRTIO_F_RING_INDIRECT_DESC)) {
1521 		dev_err(sc->sc_dev, CE_NOTE,
1522 		    "Host does not support RING_INDIRECT_DESC, bye.");
1523 		return (DDI_FAILURE);
1524 	}
1525 
1526 	return (DDI_SUCCESS);
1527 }
1528 
1529 static int
1530 vioif_has_feature(struct vioif_softc *sc, uint32_t feature)
1531 {
1532 	return (virtio_has_feature(&sc->sc_virtio, feature));
1533 }
1534 
1535 static void
1536 vioif_set_mac(struct vioif_softc *sc)
1537 {
1538 	int i;
1539 
1540 	for (i = 0; i < ETHERADDRL; i++) {
1541 		virtio_write_device_config_1(&sc->sc_virtio,
1542 		    VIRTIO_NET_CONFIG_MAC + i, sc->sc_mac[i]);
1543 	}
1544 }
1545 
1546 /* Get the mac address out of the hardware, or make up one. */
1547 static void
1548 vioif_get_mac(struct vioif_softc *sc)
1549 {
1550 	int i;
1551 	if (sc->sc_virtio.sc_features & VIRTIO_NET_F_MAC) {
1552 		for (i = 0; i < ETHERADDRL; i++) {
1553 			sc->sc_mac[i] = virtio_read_device_config_1(
1554 			    &sc->sc_virtio,
1555 			    VIRTIO_NET_CONFIG_MAC + i);
1556 		}
1557 		dev_err(sc->sc_dev, CE_NOTE, "Got MAC address from host: %s",
1558 		    ether_sprintf((struct ether_addr *)sc->sc_mac));
1559 	} else {
1560 		/* Get a few random bytes */
1561 		(void) random_get_pseudo_bytes(sc->sc_mac, ETHERADDRL);
1562 		/* Make sure it's a unicast MAC */
1563 		sc->sc_mac[0] &= ~1;
1564 		/* Set the "locally administered" bit */
1565 		sc->sc_mac[1] |= 2;
1566 
1567 		vioif_set_mac(sc);
1568 
1569 		dev_err(sc->sc_dev, CE_NOTE,
1570 		    "Generated a random MAC address: %s",
1571 		    ether_sprintf((struct ether_addr *)sc->sc_mac));
1572 	}
1573 }
1574 
1575 /*
1576  * Virtqueue interrupt handlers
1577  */
1578 /* ARGSUSED */
1579 uint_t
1580 vioif_rx_handler(caddr_t arg1, caddr_t arg2)
1581 {
1582 	struct virtio_softc *vsc = (void *) arg1;
1583 	struct vioif_softc *sc = container_of(vsc,
1584 	    struct vioif_softc, sc_virtio);
1585 
1586 	/*
1587 	 * The return values of these functions are not needed but they make
1588 	 * debugging interrupts simpler because you can use them to detect when
1589 	 * stuff was processed and repopulated in this handler.
1590 	 */
1591 	(void) vioif_process_rx(sc);
1592 	(void) vioif_populate_rx(sc, KM_NOSLEEP);
1593 
1594 	return (DDI_INTR_CLAIMED);
1595 }
1596 
1597 /* ARGSUSED */
1598 uint_t
1599 vioif_tx_handler(caddr_t arg1, caddr_t arg2)
1600 {
1601 	struct virtio_softc *vsc = (void *)arg1;
1602 	struct vioif_softc *sc = container_of(vsc,
1603 	    struct vioif_softc, sc_virtio);
1604 
1605 	/*
1606 	 * The return value of this function is not needed but makes debugging
1607 	 * interrupts simpler because you can use it to detect if anything was
1608 	 * reclaimed in this handler.
1609 	 */
1610 	(void) vioif_reclaim_used_tx(sc);
1611 
1612 	return (DDI_INTR_CLAIMED);
1613 }
1614 
1615 static int
1616 vioif_register_ints(struct vioif_softc *sc)
1617 {
1618 	int ret;
1619 
1620 	struct virtio_int_handler vioif_vq_h[] = {
1621 		{ vioif_rx_handler },
1622 		{ vioif_tx_handler },
1623 		{ NULL }
1624 	};
1625 
1626 	ret = virtio_register_ints(&sc->sc_virtio, NULL, vioif_vq_h);
1627 
1628 	return (ret);
1629 }
1630 
1631 
1632 static void
1633 vioif_check_features(struct vioif_softc *sc)
1634 {
1635 	if (vioif_has_feature(sc, VIRTIO_NET_F_CSUM)) {
1636 		/* The GSO/GRO featured depend on CSUM, check them here. */
1637 		sc->sc_tx_csum = 1;
1638 		sc->sc_rx_csum = 1;
1639 
1640 		if (!vioif_has_feature(sc, VIRTIO_NET_F_GUEST_CSUM)) {
1641 			sc->sc_rx_csum = 0;
1642 		}
1643 		cmn_err(CE_NOTE, "Csum enabled.");
1644 
1645 		if (vioif_has_feature(sc, VIRTIO_NET_F_HOST_TSO4)) {
1646 
1647 			sc->sc_tx_tso4 = 1;
1648 			/*
1649 			 * We don't seem to have a way to ask the system
1650 			 * not to send us LSO packets with Explicit
1651 			 * Congestion Notification bit set, so we require
1652 			 * the device to support it in order to do
1653 			 * LSO.
1654 			 */
1655 			if (!vioif_has_feature(sc, VIRTIO_NET_F_HOST_ECN)) {
1656 				dev_err(sc->sc_dev, CE_NOTE,
1657 				    "TSO4 supported, but not ECN. "
1658 				    "Not using LSO.");
1659 				sc->sc_tx_tso4 = 0;
1660 			} else {
1661 				cmn_err(CE_NOTE, "LSO enabled");
1662 			}
1663 		}
1664 	}
1665 }
1666 
1667 static int
1668 vioif_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
1669 {
1670 	int ret, instance;
1671 	struct vioif_softc *sc;
1672 	struct virtio_softc *vsc;
1673 	mac_register_t *macp;
1674 	char cache_name[CACHE_NAME_SIZE];
1675 
1676 	instance = ddi_get_instance(devinfo);
1677 
1678 	switch (cmd) {
1679 	case DDI_ATTACH:
1680 		break;
1681 
1682 	case DDI_RESUME:
1683 	case DDI_PM_RESUME:
1684 		/* We do not support suspend/resume for vioif. */
1685 		goto exit;
1686 
1687 	default:
1688 		goto exit;
1689 	}
1690 
1691 	sc = kmem_zalloc(sizeof (struct vioif_softc), KM_SLEEP);
1692 	ddi_set_driver_private(devinfo, sc);
1693 
1694 	vsc = &sc->sc_virtio;
1695 
1696 	/* Duplicate for less typing */
1697 	sc->sc_dev = devinfo;
1698 	vsc->sc_dev = devinfo;
1699 
1700 	/*
1701 	 * Initialize interrupt kstat.
1702 	 */
1703 	sc->sc_intrstat = kstat_create("vioif", instance, "intr", "controller",
1704 	    KSTAT_TYPE_INTR, 1, 0);
1705 	if (sc->sc_intrstat == NULL) {
1706 		dev_err(devinfo, CE_WARN, "kstat_create failed");
1707 		goto exit_intrstat;
1708 	}
1709 	kstat_install(sc->sc_intrstat);
1710 
1711 	/* map BAR 0 */
1712 	ret = ddi_regs_map_setup(devinfo, 1,
1713 	    (caddr_t *)&sc->sc_virtio.sc_io_addr,
1714 	    0, 0, &vioif_attr, &sc->sc_virtio.sc_ioh);
1715 	if (ret != DDI_SUCCESS) {
1716 		dev_err(devinfo, CE_WARN, "unable to map bar 0: %d", ret);
1717 		goto exit_map;
1718 	}
1719 
1720 	virtio_device_reset(&sc->sc_virtio);
1721 	virtio_set_status(&sc->sc_virtio, VIRTIO_CONFIG_DEVICE_STATUS_ACK);
1722 	virtio_set_status(&sc->sc_virtio, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER);
1723 
1724 	ret = vioif_dev_features(sc);
1725 	if (ret)
1726 		goto exit_features;
1727 
1728 	vsc->sc_nvqs = vioif_has_feature(sc, VIRTIO_NET_F_CTRL_VQ) ? 3 : 2;
1729 
1730 	(void) snprintf(cache_name, CACHE_NAME_SIZE, "vioif%d_rx", instance);
1731 	sc->sc_rxbuf_cache = kmem_cache_create(cache_name,
1732 	    sizeof (struct vioif_rx_buf), 0, vioif_rx_construct,
1733 	    vioif_rx_destruct, NULL, sc, NULL, KM_SLEEP);
1734 	if (sc->sc_rxbuf_cache == NULL) {
1735 		dev_err(sc->sc_dev, CE_WARN, "Can't allocate the buffer cache");
1736 		goto exit_cache;
1737 	}
1738 
1739 	ret = vioif_register_ints(sc);
1740 	if (ret) {
1741 		dev_err(sc->sc_dev, CE_WARN,
1742 		    "Failed to allocate interrupt(s)!");
1743 		goto exit_ints;
1744 	}
1745 
1746 	/*
1747 	 * Register layout determined, can now access the
1748 	 * device-specific bits
1749 	 */
1750 	vioif_get_mac(sc);
1751 
1752 	sc->sc_rx_vq = virtio_alloc_vq(&sc->sc_virtio, 0,
1753 	    VIOIF_RX_QLEN, VIOIF_INDIRECT_MAX, "rx");
1754 	if (!sc->sc_rx_vq)
1755 		goto exit_alloc1;
1756 	virtio_stop_vq_intr(sc->sc_rx_vq);
1757 
1758 	sc->sc_tx_vq = virtio_alloc_vq(&sc->sc_virtio, 1,
1759 	    VIOIF_TX_QLEN, VIOIF_INDIRECT_MAX, "tx");
1760 	if (!sc->sc_tx_vq)
1761 		goto exit_alloc2;
1762 	virtio_stop_vq_intr(sc->sc_tx_vq);
1763 
1764 	if (vioif_has_feature(sc, VIRTIO_NET_F_CTRL_VQ)) {
1765 		sc->sc_ctrl_vq = virtio_alloc_vq(&sc->sc_virtio, 2,
1766 		    VIOIF_CTRL_QLEN, 0, "ctrl");
1767 		if (!sc->sc_ctrl_vq) {
1768 			goto exit_alloc3;
1769 		}
1770 		virtio_stop_vq_intr(sc->sc_ctrl_vq);
1771 	}
1772 
1773 	virtio_set_status(&sc->sc_virtio,
1774 	    VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK);
1775 
1776 	sc->sc_rxloan = 0;
1777 
1778 	/* set some reasonable-small default values */
1779 	sc->sc_rxcopy_thresh = 300;
1780 	sc->sc_txcopy_thresh = 300;
1781 	sc->sc_mtu = ETHERMTU;
1782 
1783 	vioif_check_features(sc);
1784 
1785 	if (vioif_alloc_mems(sc))
1786 		goto exit_alloc_mems;
1787 
1788 	if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
1789 		dev_err(devinfo, CE_WARN, "Failed to allocate a mac_register");
1790 		goto exit_macalloc;
1791 	}
1792 
1793 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
1794 	macp->m_driver = sc;
1795 	macp->m_dip = devinfo;
1796 	macp->m_src_addr = sc->sc_mac;
1797 	macp->m_callbacks = &vioif_m_callbacks;
1798 	macp->m_min_sdu = 0;
1799 	macp->m_max_sdu = sc->sc_mtu;
1800 	macp->m_margin = VLAN_TAGSZ;
1801 	macp->m_priv_props = vioif_priv_props;
1802 
1803 	sc->sc_macp = macp;
1804 
1805 	/* Pre-fill the rx ring. */
1806 	(void) vioif_populate_rx(sc, KM_SLEEP);
1807 
1808 	ret = mac_register(macp, &sc->sc_mac_handle);
1809 	if (ret != 0) {
1810 		dev_err(devinfo, CE_WARN, "vioif_attach: "
1811 		    "mac_register() failed, ret=%d", ret);
1812 		goto exit_register;
1813 	}
1814 
1815 	ret = virtio_enable_ints(&sc->sc_virtio);
1816 	if (ret) {
1817 		dev_err(devinfo, CE_WARN, "Failed to enable interrupts");
1818 		goto exit_enable_ints;
1819 	}
1820 
1821 	mac_link_update(sc->sc_mac_handle, LINK_STATE_UP);
1822 	return (DDI_SUCCESS);
1823 
1824 exit_enable_ints:
1825 	(void) mac_unregister(sc->sc_mac_handle);
1826 exit_register:
1827 	mac_free(macp);
1828 exit_macalloc:
1829 	vioif_free_mems(sc);
1830 exit_alloc_mems:
1831 	virtio_release_ints(&sc->sc_virtio);
1832 	if (sc->sc_ctrl_vq)
1833 		virtio_free_vq(sc->sc_ctrl_vq);
1834 exit_alloc3:
1835 	virtio_free_vq(sc->sc_tx_vq);
1836 exit_alloc2:
1837 	virtio_free_vq(sc->sc_rx_vq);
1838 exit_alloc1:
1839 exit_ints:
1840 	kmem_cache_destroy(sc->sc_rxbuf_cache);
1841 exit_cache:
1842 exit_features:
1843 	virtio_set_status(&sc->sc_virtio, VIRTIO_CONFIG_DEVICE_STATUS_FAILED);
1844 	ddi_regs_map_free(&sc->sc_virtio.sc_ioh);
1845 exit_intrstat:
1846 exit_map:
1847 	kstat_delete(sc->sc_intrstat);
1848 	kmem_free(sc, sizeof (struct vioif_softc));
1849 exit:
1850 	return (DDI_FAILURE);
1851 }
1852 
1853 static int
1854 vioif_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
1855 {
1856 	struct vioif_softc *sc;
1857 
1858 	if ((sc = ddi_get_driver_private(devinfo)) == NULL)
1859 		return (DDI_FAILURE);
1860 
1861 	switch (cmd) {
1862 	case DDI_DETACH:
1863 		break;
1864 
1865 	case DDI_PM_SUSPEND:
1866 		/* We do not support suspend/resume for vioif. */
1867 		return (DDI_FAILURE);
1868 
1869 	default:
1870 		return (DDI_FAILURE);
1871 	}
1872 
1873 	if (sc->sc_rxloan) {
1874 		dev_err(devinfo, CE_WARN, "!Some rx buffers are still upstream,"
1875 		    " not detaching.");
1876 		return (DDI_FAILURE);
1877 	}
1878 
1879 	virtio_stop_vq_intr(sc->sc_rx_vq);
1880 	virtio_stop_vq_intr(sc->sc_tx_vq);
1881 
1882 	virtio_release_ints(&sc->sc_virtio);
1883 
1884 	if (mac_unregister(sc->sc_mac_handle)) {
1885 		return (DDI_FAILURE);
1886 	}
1887 
1888 	mac_free(sc->sc_macp);
1889 
1890 	vioif_free_mems(sc);
1891 	virtio_free_vq(sc->sc_rx_vq);
1892 	virtio_free_vq(sc->sc_tx_vq);
1893 
1894 	virtio_device_reset(&sc->sc_virtio);
1895 
1896 	ddi_regs_map_free(&sc->sc_virtio.sc_ioh);
1897 
1898 	kmem_cache_destroy(sc->sc_rxbuf_cache);
1899 	kstat_delete(sc->sc_intrstat);
1900 	kmem_free(sc, sizeof (struct vioif_softc));
1901 
1902 	return (DDI_SUCCESS);
1903 }
1904 
1905 static int
1906 vioif_quiesce(dev_info_t *devinfo)
1907 {
1908 	struct vioif_softc *sc;
1909 
1910 	if ((sc = ddi_get_driver_private(devinfo)) == NULL)
1911 		return (DDI_FAILURE);
1912 
1913 	virtio_stop_vq_intr(sc->sc_rx_vq);
1914 	virtio_stop_vq_intr(sc->sc_tx_vq);
1915 	virtio_device_reset(&sc->sc_virtio);
1916 
1917 	return (DDI_SUCCESS);
1918 }
1919 
1920 int
1921 _init(void)
1922 {
1923 	int ret = 0;
1924 
1925 	mac_init_ops(&vioif_ops, "vioif");
1926 
1927 	ret = mod_install(&modlinkage);
1928 	if (ret != DDI_SUCCESS) {
1929 		mac_fini_ops(&vioif_ops);
1930 		return (ret);
1931 	}
1932 
1933 	return (0);
1934 }
1935 
1936 int
1937 _fini(void)
1938 {
1939 	int ret;
1940 
1941 	ret = mod_remove(&modlinkage);
1942 	if (ret == DDI_SUCCESS) {
1943 		mac_fini_ops(&vioif_ops);
1944 	}
1945 
1946 	return (ret);
1947 }
1948 
1949 int
1950 _info(struct modinfo *pModinfo)
1951 {
1952 	return (mod_info(&modlinkage, pModinfo));
1953 }
1954