xref: /titanic_41/usr/src/uts/sun4v/io/vnet_gen.c (revision cde2885fdf538266ee2a3b08dee2d5075ce8fa2b)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <sys/types.h>
28 #include <sys/errno.h>
29 #include <sys/sysmacros.h>
30 #include <sys/param.h>
31 #include <sys/stream.h>
32 #include <sys/strsubr.h>
33 #include <sys/kmem.h>
34 #include <sys/conf.h>
35 #include <sys/devops.h>
36 #include <sys/ksynch.h>
37 #include <sys/stat.h>
38 #include <sys/modctl.h>
39 #include <sys/debug.h>
40 #include <sys/ethernet.h>
41 #include <sys/ddi.h>
42 #include <sys/sunddi.h>
43 #include <sys/strsun.h>
44 #include <sys/note.h>
45 #include <sys/mac_provider.h>
46 #include <sys/mac_ether.h>
47 #include <sys/ldc.h>
48 #include <sys/mach_descrip.h>
49 #include <sys/mdeg.h>
50 #include <net/if.h>
51 #include <sys/vnet.h>
52 #include <sys/vio_mailbox.h>
53 #include <sys/vio_common.h>
54 #include <sys/vnet_common.h>
55 #include <sys/vnet_mailbox.h>
56 #include <sys/vio_util.h>
57 #include <sys/vnet_gen.h>
58 #include <sys/atomic.h>
59 #include <sys/callb.h>
60 #include <sys/sdt.h>
61 #include <sys/intr.h>
62 #include <sys/pattr.h>
63 #include <sys/vlan.h>
64 
65 /*
66  * Implementation of the mac functionality for vnet using the
67  * generic(default) transport layer of sun4v Logical Domain Channels(LDC).
68  */
69 
70 /*
71  * Function prototypes.
72  */
73 /* vgen proxy entry points */
74 int vgen_init(void *vnetp, uint64_t regprop, dev_info_t *vnetdip,
75     const uint8_t *macaddr, void **vgenhdl);
76 void vgen_uninit(void *arg);
77 int vgen_dds_tx(void *arg, void *dmsg);
78 void vgen_mod_init(void);
79 int vgen_mod_cleanup(void);
80 void vgen_mod_fini(void);
81 static int vgen_start(void *arg);
82 static void vgen_stop(void *arg);
83 static mblk_t *vgen_tx(void *arg, mblk_t *mp);
84 static int vgen_multicst(void *arg, boolean_t add,
85 	const uint8_t *mca);
86 static int vgen_promisc(void *arg, boolean_t on);
87 static int vgen_unicst(void *arg, const uint8_t *mca);
88 static int vgen_stat(void *arg, uint_t stat, uint64_t *val);
89 static void vgen_ioctl(void *arg, queue_t *wq, mblk_t *mp);
90 
91 /* vgen internal functions */
92 static int vgen_read_mdprops(vgen_t *vgenp);
93 static void vgen_update_md_prop(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex);
94 static void vgen_read_pri_eth_types(vgen_t *vgenp, md_t *mdp,
95 	mde_cookie_t node);
96 static void vgen_mtu_read(vgen_t *vgenp, md_t *mdp, mde_cookie_t node,
97 	uint32_t *mtu);
98 static void vgen_detach_ports(vgen_t *vgenp);
99 static void vgen_port_detach(vgen_port_t *portp);
100 static void vgen_port_list_insert(vgen_port_t *portp);
101 static void vgen_port_list_remove(vgen_port_t *portp);
102 static vgen_port_t *vgen_port_lookup(vgen_portlist_t *plistp,
103 	int port_num);
104 static int vgen_mdeg_reg(vgen_t *vgenp);
105 static void vgen_mdeg_unreg(vgen_t *vgenp);
106 static int vgen_mdeg_cb(void *cb_argp, mdeg_result_t *resp);
107 static int vgen_mdeg_port_cb(void *cb_argp, mdeg_result_t *resp);
108 static int vgen_add_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex);
109 static int vgen_port_read_props(vgen_port_t *portp, vgen_t *vgenp, md_t *mdp,
110 	mde_cookie_t mdex);
111 static int vgen_remove_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex);
112 static int vgen_port_attach(vgen_port_t *portp);
113 static void vgen_port_detach_mdeg(vgen_port_t *portp);
114 static void vgen_port_detach_mdeg(vgen_port_t *portp);
115 static int vgen_update_port(vgen_t *vgenp, md_t *curr_mdp,
116 	mde_cookie_t curr_mdex, md_t *prev_mdp, mde_cookie_t prev_mdex);
117 static uint64_t	vgen_port_stat(vgen_port_t *portp, uint_t stat);
118 
119 static int vgen_ldc_attach(vgen_port_t *portp, uint64_t ldc_id);
120 static void vgen_ldc_detach(vgen_ldc_t *ldcp);
121 static int vgen_alloc_tx_ring(vgen_ldc_t *ldcp);
122 static void vgen_free_tx_ring(vgen_ldc_t *ldcp);
123 static void vgen_init_ports(vgen_t *vgenp);
124 static void vgen_port_init(vgen_port_t *portp);
125 static void vgen_uninit_ports(vgen_t *vgenp);
126 static void vgen_port_uninit(vgen_port_t *portp);
127 static void vgen_init_ldcs(vgen_port_t *portp);
128 static void vgen_uninit_ldcs(vgen_port_t *portp);
129 static int vgen_ldc_init(vgen_ldc_t *ldcp);
130 static void vgen_ldc_uninit(vgen_ldc_t *ldcp);
131 static int vgen_init_tbufs(vgen_ldc_t *ldcp);
132 static void vgen_uninit_tbufs(vgen_ldc_t *ldcp);
133 static void vgen_clobber_tbufs(vgen_ldc_t *ldcp);
134 static void vgen_clobber_rxds(vgen_ldc_t *ldcp);
135 static uint64_t	vgen_ldc_stat(vgen_ldc_t *ldcp, uint_t stat);
136 static uint_t vgen_ldc_cb(uint64_t event, caddr_t arg);
137 static int vgen_portsend(vgen_port_t *portp, mblk_t *mp);
138 static int vgen_ldcsend(void *arg, mblk_t *mp);
139 static void vgen_ldcsend_pkt(void *arg, mblk_t *mp);
140 static int vgen_ldcsend_dring(void *arg, mblk_t *mp);
141 static void vgen_reclaim(vgen_ldc_t *ldcp);
142 static void vgen_reclaim_dring(vgen_ldc_t *ldcp);
143 static int vgen_num_txpending(vgen_ldc_t *ldcp);
144 static int vgen_tx_dring_full(vgen_ldc_t *ldcp);
145 static int vgen_ldc_txtimeout(vgen_ldc_t *ldcp);
146 static void vgen_ldc_watchdog(void *arg);
147 
148 /* vgen handshake functions */
149 static vgen_ldc_t *vh_nextphase(vgen_ldc_t *ldcp);
150 static int vgen_sendmsg(vgen_ldc_t *ldcp, caddr_t msg,  size_t msglen,
151 	boolean_t caller_holds_lock);
152 static int vgen_send_version_negotiate(vgen_ldc_t *ldcp);
153 static int vgen_send_attr_info(vgen_ldc_t *ldcp);
154 static int vgen_send_dring_reg(vgen_ldc_t *ldcp);
155 static int vgen_send_rdx_info(vgen_ldc_t *ldcp);
156 static int vgen_send_dring_data(vgen_ldc_t *ldcp, uint32_t start, int32_t end);
157 static int vgen_send_mcast_info(vgen_ldc_t *ldcp);
158 static int vgen_handshake_phase2(vgen_ldc_t *ldcp);
159 static void vgen_handshake_reset(vgen_ldc_t *ldcp);
160 static void vgen_reset_hphase(vgen_ldc_t *ldcp);
161 static void vgen_handshake(vgen_ldc_t *ldcp);
162 static int vgen_handshake_done(vgen_ldc_t *ldcp);
163 static void vgen_handshake_retry(vgen_ldc_t *ldcp);
164 static int vgen_handle_version_negotiate(vgen_ldc_t *ldcp,
165 	vio_msg_tag_t *tagp);
166 static int vgen_handle_attr_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
167 static int vgen_handle_dring_reg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
168 static int vgen_handle_rdx_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
169 static int vgen_handle_mcast_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
170 static int vgen_handle_ctrlmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
171 static void vgen_handle_pkt_data_nop(void *arg1, void *arg2, uint32_t msglen);
172 static void vgen_handle_pkt_data(void *arg1, void *arg2, uint32_t msglen);
173 static int vgen_handle_dring_data(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
174 static int vgen_handle_dring_data_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
175 static int vgen_process_dring_data(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
176 static int vgen_handle_dring_data_ack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
177 static int vgen_handle_dring_data_nack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
178 static int vgen_send_dring_ack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp,
179 	uint32_t start, int32_t end, uint8_t pstate);
180 static int vgen_handle_datamsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp,
181 	uint32_t msglen);
182 static void vgen_handle_errmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
183 static void vgen_handle_evt_up(vgen_ldc_t *ldcp);
184 static void vgen_handle_evt_reset(vgen_ldc_t *ldcp);
185 static int vgen_check_sid(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
186 static int vgen_check_datamsg_seq(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
187 static caddr_t vgen_print_ethaddr(uint8_t *a, char *ebuf);
188 static void vgen_hwatchdog(void *arg);
189 static void vgen_print_attr_info(vgen_ldc_t *ldcp, int endpoint);
190 static void vgen_print_hparams(vgen_hparams_t *hp);
191 static void vgen_print_ldcinfo(vgen_ldc_t *ldcp);
192 static void vgen_stop_rcv_thread(vgen_ldc_t *ldcp);
193 static void vgen_drain_rcv_thread(vgen_ldc_t *ldcp);
194 static void vgen_ldc_rcv_worker(void *arg);
195 static void vgen_handle_evt_read(vgen_ldc_t *ldcp);
196 static void vgen_rx(vgen_ldc_t *ldcp, mblk_t *bp);
197 static void vgen_set_vnet_proto_ops(vgen_ldc_t *ldcp);
198 static void vgen_reset_vnet_proto_ops(vgen_ldc_t *ldcp);
199 
200 /* VLAN routines */
201 static void vgen_vlan_read_ids(void *arg, int type, md_t *mdp,
202 	mde_cookie_t node, uint16_t *pvidp, uint16_t **vidspp,
203 	uint16_t *nvidsp, uint16_t *default_idp);
204 static void vgen_vlan_create_hash(vgen_port_t *portp);
205 static void vgen_vlan_destroy_hash(vgen_port_t *portp);
206 static void vgen_vlan_add_ids(vgen_port_t *portp);
207 static void vgen_vlan_remove_ids(vgen_port_t *portp);
208 static boolean_t vgen_vlan_lookup(mod_hash_t *vlan_hashp, uint16_t vid);
209 static boolean_t vgen_frame_lookup_vid(vnet_t *vnetp, struct ether_header *ehp,
210 	uint16_t *vidp);
211 static mblk_t *vgen_vlan_frame_fixtag(vgen_port_t *portp, mblk_t *mp,
212 	boolean_t is_tagged, uint16_t vid);
213 static void vgen_vlan_unaware_port_reset(vgen_port_t *portp);
214 static void vgen_reset_vlan_unaware_ports(vgen_t *vgenp);
215 static int vgen_dds_rx(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
216 
217 /* externs */
218 extern void vnet_dds_rx(void *arg, void *dmsg);
219 extern int vnet_mtu_update(vnet_t *vnetp, uint32_t mtu);
220 
221 /*
222  * The handshake process consists of 5 phases defined below, with VH_PHASE0
223  * being the pre-handshake phase and VH_DONE is the phase to indicate
224  * successful completion of all phases.
225  * Each phase may have one to several handshake states which are required
226  * to complete successfully to move to the next phase.
227  * Refer to the functions vgen_handshake() and vgen_handshake_done() for
228  * more details.
229  */
230 /* handshake phases */
231 enum {	VH_PHASE0, VH_PHASE1, VH_PHASE2, VH_PHASE3, VH_DONE = 0x80 };
232 
233 /* handshake states */
234 enum {
235 
236 	VER_INFO_SENT	=	0x1,
237 	VER_ACK_RCVD	=	0x2,
238 	VER_INFO_RCVD	=	0x4,
239 	VER_ACK_SENT	=	0x8,
240 	VER_NEGOTIATED	=	(VER_ACK_RCVD | VER_ACK_SENT),
241 
242 	ATTR_INFO_SENT	=	0x10,
243 	ATTR_ACK_RCVD	=	0x20,
244 	ATTR_INFO_RCVD	=	0x40,
245 	ATTR_ACK_SENT	=	0x80,
246 	ATTR_INFO_EXCHANGED	=	(ATTR_ACK_RCVD | ATTR_ACK_SENT),
247 
248 	DRING_INFO_SENT	=	0x100,
249 	DRING_ACK_RCVD	=	0x200,
250 	DRING_INFO_RCVD	=	0x400,
251 	DRING_ACK_SENT	=	0x800,
252 	DRING_INFO_EXCHANGED	=	(DRING_ACK_RCVD | DRING_ACK_SENT),
253 
254 	RDX_INFO_SENT	=	0x1000,
255 	RDX_ACK_RCVD	=	0x2000,
256 	RDX_INFO_RCVD	=	0x4000,
257 	RDX_ACK_SENT	=	0x8000,
258 	RDX_EXCHANGED	=	(RDX_ACK_RCVD | RDX_ACK_SENT)
259 
260 };
261 
262 #define	VGEN_PRI_ETH_DEFINED(vgenp)	((vgenp)->pri_num_types != 0)
263 
264 #define	LDC_LOCK(ldcp)	\
265 				mutex_enter(&((ldcp)->cblock));\
266 				mutex_enter(&((ldcp)->rxlock));\
267 				mutex_enter(&((ldcp)->wrlock));\
268 				mutex_enter(&((ldcp)->txlock));\
269 				mutex_enter(&((ldcp)->tclock));
270 #define	LDC_UNLOCK(ldcp)	\
271 				mutex_exit(&((ldcp)->tclock));\
272 				mutex_exit(&((ldcp)->txlock));\
273 				mutex_exit(&((ldcp)->wrlock));\
274 				mutex_exit(&((ldcp)->rxlock));\
275 				mutex_exit(&((ldcp)->cblock));
276 
277 #define	VGEN_VER_EQ(ldcp, major, minor)	\
278 	((ldcp)->local_hparams.ver_major == (major) &&	\
279 	    (ldcp)->local_hparams.ver_minor == (minor))
280 
281 #define	VGEN_VER_LT(ldcp, major, minor)	\
282 	(((ldcp)->local_hparams.ver_major < (major)) ||	\
283 	    ((ldcp)->local_hparams.ver_major == (major) &&	\
284 	    (ldcp)->local_hparams.ver_minor < (minor)))
285 
286 #define	VGEN_VER_GTEQ(ldcp, major, minor)	\
287 	(((ldcp)->local_hparams.ver_major > (major)) ||	\
288 	    ((ldcp)->local_hparams.ver_major == (major) &&	\
289 	    (ldcp)->local_hparams.ver_minor >= (minor)))
290 
291 static struct ether_addr etherbroadcastaddr = {
292 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff
293 };
294 /*
295  * MIB II broadcast/multicast packets
296  */
297 #define	IS_BROADCAST(ehp) \
298 		(ether_cmp(&ehp->ether_dhost, &etherbroadcastaddr) == 0)
299 #define	IS_MULTICAST(ehp) \
300 		((ehp->ether_dhost.ether_addr_octet[0] & 01) == 1)
301 
302 /*
303  * Property names
304  */
305 static char macaddr_propname[] = "mac-address";
306 static char rmacaddr_propname[] = "remote-mac-address";
307 static char channel_propname[] = "channel-endpoint";
308 static char reg_propname[] = "reg";
309 static char port_propname[] = "port";
310 static char swport_propname[] = "switch-port";
311 static char id_propname[] = "id";
312 static char vdev_propname[] = "virtual-device";
313 static char vnet_propname[] = "network";
314 static char pri_types_propname[] = "priority-ether-types";
315 static char vgen_pvid_propname[] = "port-vlan-id";
316 static char vgen_vid_propname[] = "vlan-id";
317 static char vgen_dvid_propname[] = "default-vlan-id";
318 static char port_pvid_propname[] = "remote-port-vlan-id";
319 static char port_vid_propname[] = "remote-vlan-id";
320 static char vgen_mtu_propname[] = "mtu";
321 
322 /* versions supported - in decreasing order */
323 static vgen_ver_t vgen_versions[VGEN_NUM_VER] = { {1, 4} };
324 
325 /* Tunables */
326 uint32_t vgen_hwd_interval = 5;		/* handshake watchdog freq in sec */
327 uint32_t vgen_max_hretries = VNET_NUM_HANDSHAKES; /* # of handshake retries */
328 uint32_t vgen_ldcwr_retries = 10;	/* max # of ldc_write() retries */
329 uint32_t vgen_ldcup_retries = 5;	/* max # of ldc_up() retries */
330 uint32_t vgen_ldccl_retries = 5;	/* max # of ldc_close() retries */
331 uint32_t vgen_recv_delay = 1;		/* delay when rx descr not ready */
332 uint32_t vgen_recv_retries = 10;	/* retry when rx descr not ready */
333 uint32_t vgen_tx_retries = 0x4;		/* retry when tx descr not available */
334 uint32_t vgen_tx_delay = 0x30;		/* delay when tx descr not available */
335 
336 int vgen_rcv_thread_enabled = 1;	/* Enable Recieve thread */
337 
338 static vio_mblk_pool_t	*vgen_rx_poolp = NULL;
339 static krwlock_t	vgen_rw;
340 
341 /*
342  * max # of packets accumulated prior to sending them up. It is best
343  * to keep this at 60% of the number of recieve buffers.
344  */
345 uint32_t vgen_chain_len = (VGEN_NRBUFS * 0.6);
346 
347 /*
348  * Internal tunables for receive buffer pools, that is,  the size and number of
349  * mblks for each pool. At least 3 sizes must be specified if these are used.
350  * The sizes must be specified in increasing order. Non-zero value of the first
351  * size will be used as a hint to use these values instead of the algorithm
352  * that determines the sizes based on MTU.
353  */
354 uint32_t vgen_rbufsz1 = 0;
355 uint32_t vgen_rbufsz2 = 0;
356 uint32_t vgen_rbufsz3 = 0;
357 uint32_t vgen_rbufsz4 = 0;
358 
359 uint32_t vgen_nrbufs1 = VGEN_NRBUFS;
360 uint32_t vgen_nrbufs2 = VGEN_NRBUFS;
361 uint32_t vgen_nrbufs3 = VGEN_NRBUFS;
362 uint32_t vgen_nrbufs4 = VGEN_NRBUFS;
363 
364 /*
365  * In the absence of "priority-ether-types" property in MD, the following
366  * internal tunable can be set to specify a single priority ethertype.
367  */
368 uint64_t vgen_pri_eth_type = 0;
369 
370 /*
371  * Number of transmit priority buffers that are preallocated per device.
372  * This number is chosen to be a small value to throttle transmission
373  * of priority packets. Note: Must be a power of 2 for vio_create_mblks().
374  */
375 uint32_t vgen_pri_tx_nmblks = 64;
376 
377 uint32_t	vgen_vlan_nchains = 4;	/* # of chains in vlan id hash table */
378 
379 #ifdef DEBUG
380 /* flags to simulate error conditions for debugging */
381 int vgen_trigger_txtimeout = 0;
382 int vgen_trigger_rxlost = 0;
383 #endif
384 
385 /*
386  * Matching criteria passed to the MDEG to register interest
387  * in changes to 'virtual-device' nodes (i.e. vnet nodes) identified
388  * by their 'name' and 'cfg-handle' properties.
389  */
390 static md_prop_match_t vdev_prop_match[] = {
391 	{ MDET_PROP_STR,    "name"   },
392 	{ MDET_PROP_VAL,    "cfg-handle" },
393 	{ MDET_LIST_END,    NULL    }
394 };
395 
396 static mdeg_node_match_t vdev_match = { "virtual-device",
397 						vdev_prop_match };
398 
399 /* MD update matching structure */
400 static md_prop_match_t	vport_prop_match[] = {
401 	{ MDET_PROP_VAL,	"id" },
402 	{ MDET_LIST_END,	NULL }
403 };
404 
405 static mdeg_node_match_t vport_match = { "virtual-device-port",
406 					vport_prop_match };
407 
408 /* template for matching a particular vnet instance */
409 static mdeg_prop_spec_t vgen_prop_template[] = {
410 	{ MDET_PROP_STR,	"name",		"network" },
411 	{ MDET_PROP_VAL,	"cfg-handle",	NULL },
412 	{ MDET_LIST_END,	NULL,		NULL }
413 };
414 
415 #define	VGEN_SET_MDEG_PROP_INST(specp, val)	(specp)[1].ps_val = (val)
416 
417 static int vgen_mdeg_port_cb(void *cb_argp, mdeg_result_t *resp);
418 
419 static mac_callbacks_t vgen_m_callbacks = {
420 	0,
421 	vgen_stat,
422 	vgen_start,
423 	vgen_stop,
424 	vgen_promisc,
425 	vgen_multicst,
426 	vgen_unicst,
427 	vgen_tx,
428 	NULL,
429 	NULL,
430 	NULL
431 };
432 
433 /* externs */
434 extern pri_t	maxclsyspri;
435 extern proc_t	p0;
436 extern uint32_t vnet_ntxds;
437 extern uint32_t vnet_ldcwd_interval;
438 extern uint32_t vnet_ldcwd_txtimeout;
439 extern uint32_t vnet_ldc_mtu;
440 extern uint32_t vnet_nrbufs;
441 extern uint32_t	vnet_ethermtu;
442 extern uint16_t	vnet_default_vlan_id;
443 extern boolean_t vnet_jumbo_rxpools;
444 
445 #ifdef DEBUG
446 
447 extern int vnet_dbglevel;
448 static void debug_printf(const char *fname, vgen_t *vgenp,
449 	vgen_ldc_t *ldcp, const char *fmt, ...);
450 
451 /* -1 for all LDCs info, or ldc_id for a specific LDC info */
452 int vgendbg_ldcid = -1;
453 
454 /* simulate handshake error conditions for debug */
455 uint32_t vgen_hdbg;
456 #define	HDBG_VERSION	0x1
457 #define	HDBG_TIMEOUT	0x2
458 #define	HDBG_BAD_SID	0x4
459 #define	HDBG_OUT_STATE	0x8
460 
461 #endif
462 
463 /*
464  * vgen_init() is called by an instance of vnet driver to initialize the
465  * corresponding generic proxy transport layer. The arguments passed by vnet
466  * are - an opaque pointer to the vnet instance, pointers to dev_info_t and
467  * the mac address of the vnet device, and a pointer to vgen_t is passed
468  * back as a handle to vnet.
469  */
470 int
471 vgen_init(void *vnetp, uint64_t regprop, dev_info_t *vnetdip,
472     const uint8_t *macaddr, void **vgenhdl)
473 {
474 	vgen_t *vgenp;
475 	int instance;
476 	int rv;
477 
478 	if ((vnetp == NULL) || (vnetdip == NULL))
479 		return (DDI_FAILURE);
480 
481 	instance = ddi_get_instance(vnetdip);
482 
483 	DBG1(NULL, NULL, "vnet(%d): enter\n", instance);
484 
485 	vgenp = kmem_zalloc(sizeof (vgen_t), KM_SLEEP);
486 
487 	vgenp->vnetp = vnetp;
488 	vgenp->instance = instance;
489 	vgenp->regprop = regprop;
490 	vgenp->vnetdip = vnetdip;
491 	bcopy(macaddr, &(vgenp->macaddr), ETHERADDRL);
492 
493 	/* allocate multicast table */
494 	vgenp->mctab = kmem_zalloc(VGEN_INIT_MCTAB_SIZE *
495 	    sizeof (struct ether_addr), KM_SLEEP);
496 	vgenp->mccount = 0;
497 	vgenp->mcsize = VGEN_INIT_MCTAB_SIZE;
498 
499 	mutex_init(&vgenp->lock, NULL, MUTEX_DRIVER, NULL);
500 	rw_init(&vgenp->vgenports.rwlock, NULL, RW_DRIVER, NULL);
501 
502 	rv = vgen_read_mdprops(vgenp);
503 	if (rv != 0) {
504 		goto vgen_init_fail;
505 	}
506 
507 	/* register with MD event generator */
508 	rv = vgen_mdeg_reg(vgenp);
509 	if (rv != DDI_SUCCESS) {
510 		goto vgen_init_fail;
511 	}
512 
513 	*vgenhdl = (void *)vgenp;
514 
515 	DBG1(NULL, NULL, "vnet(%d): exit\n", instance);
516 	return (DDI_SUCCESS);
517 
518 vgen_init_fail:
519 	rw_destroy(&vgenp->vgenports.rwlock);
520 	mutex_destroy(&vgenp->lock);
521 	kmem_free(vgenp->mctab, VGEN_INIT_MCTAB_SIZE *
522 	    sizeof (struct ether_addr));
523 	if (VGEN_PRI_ETH_DEFINED(vgenp)) {
524 		kmem_free(vgenp->pri_types,
525 		    sizeof (uint16_t) * vgenp->pri_num_types);
526 		(void) vio_destroy_mblks(vgenp->pri_tx_vmp);
527 	}
528 	KMEM_FREE(vgenp);
529 	return (DDI_FAILURE);
530 }
531 
532 /*
533  * Called by vnet to undo the initializations done by vgen_init().
534  * The handle provided by generic transport during vgen_init() is the argument.
535  */
536 void
537 vgen_uninit(void *arg)
538 {
539 	vgen_t		*vgenp = (vgen_t *)arg;
540 	vio_mblk_pool_t	*rp;
541 	vio_mblk_pool_t	*nrp;
542 
543 	if (vgenp == NULL) {
544 		return;
545 	}
546 
547 	DBG1(vgenp, NULL, "enter\n");
548 
549 	/* unregister with MD event generator */
550 	vgen_mdeg_unreg(vgenp);
551 
552 	mutex_enter(&vgenp->lock);
553 
554 	/* detach all ports from the device */
555 	vgen_detach_ports(vgenp);
556 
557 	/*
558 	 * free any pending rx mblk pools,
559 	 * that couldn't be freed previously during channel detach.
560 	 */
561 	rp = vgenp->rmp;
562 	while (rp != NULL) {
563 		nrp = vgenp->rmp = rp->nextp;
564 		if (vio_destroy_mblks(rp)) {
565 			WRITE_ENTER(&vgen_rw);
566 			rp->nextp = vgen_rx_poolp;
567 			vgen_rx_poolp = rp;
568 			RW_EXIT(&vgen_rw);
569 		}
570 		rp = nrp;
571 	}
572 
573 	/* free multicast table */
574 	kmem_free(vgenp->mctab, vgenp->mcsize * sizeof (struct ether_addr));
575 
576 	/* free pri_types table */
577 	if (VGEN_PRI_ETH_DEFINED(vgenp)) {
578 		kmem_free(vgenp->pri_types,
579 		    sizeof (uint16_t) * vgenp->pri_num_types);
580 		(void) vio_destroy_mblks(vgenp->pri_tx_vmp);
581 	}
582 
583 	mutex_exit(&vgenp->lock);
584 
585 	rw_destroy(&vgenp->vgenports.rwlock);
586 	mutex_destroy(&vgenp->lock);
587 
588 	DBG1(vgenp, NULL, "exit\n");
589 	KMEM_FREE(vgenp);
590 }
591 
592 /*
593  * module specific initialization common to all instances of vnet/vgen.
594  */
595 void
596 vgen_mod_init(void)
597 {
598 	rw_init(&vgen_rw, NULL, RW_DRIVER, NULL);
599 }
600 
601 /*
602  * module specific cleanup common to all instances of vnet/vgen.
603  */
604 int
605 vgen_mod_cleanup(void)
606 {
607 	vio_mblk_pool_t	*poolp, *npoolp;
608 
609 	/*
610 	 * If any rx mblk pools are still in use, return
611 	 * error and stop the module from unloading.
612 	 */
613 	WRITE_ENTER(&vgen_rw);
614 	poolp = vgen_rx_poolp;
615 	while (poolp != NULL) {
616 		npoolp = vgen_rx_poolp = poolp->nextp;
617 		if (vio_destroy_mblks(poolp) != 0) {
618 			vgen_rx_poolp = poolp;
619 			RW_EXIT(&vgen_rw);
620 			return (EBUSY);
621 		}
622 		poolp = npoolp;
623 	}
624 	RW_EXIT(&vgen_rw);
625 
626 	return (0);
627 }
628 
629 /*
630  * module specific uninitialization common to all instances of vnet/vgen.
631  */
632 void
633 vgen_mod_fini(void)
634 {
635 	rw_destroy(&vgen_rw);
636 }
637 
638 /* enable transmit/receive for the device */
639 int
640 vgen_start(void *arg)
641 {
642 	vgen_port_t	*portp = (vgen_port_t *)arg;
643 	vgen_t		*vgenp = portp->vgenp;
644 
645 	DBG1(vgenp, NULL, "enter\n");
646 	mutex_enter(&portp->lock);
647 	vgen_port_init(portp);
648 	portp->flags |= VGEN_STARTED;
649 	mutex_exit(&portp->lock);
650 	DBG1(vgenp, NULL, "exit\n");
651 
652 	return (DDI_SUCCESS);
653 }
654 
655 /* stop transmit/receive */
656 void
657 vgen_stop(void *arg)
658 {
659 	vgen_port_t	*portp = (vgen_port_t *)arg;
660 	vgen_t		*vgenp = portp->vgenp;
661 
662 	DBG1(vgenp, NULL, "enter\n");
663 
664 	mutex_enter(&portp->lock);
665 	vgen_port_uninit(portp);
666 	portp->flags &= ~(VGEN_STARTED);
667 	mutex_exit(&portp->lock);
668 	DBG1(vgenp, NULL, "exit\n");
669 
670 }
671 
672 /* vgen transmit function */
673 static mblk_t *
674 vgen_tx(void *arg, mblk_t *mp)
675 {
676 	int i;
677 	vgen_port_t *portp;
678 	int status = VGEN_FAILURE;
679 
680 	portp = (vgen_port_t *)arg;
681 	/*
682 	 * Retry so that we avoid reporting a failure
683 	 * to the upper layer. Returning a failure may cause the
684 	 * upper layer to go into single threaded mode there by
685 	 * causing performance degradation, especially for a large
686 	 * number of connections.
687 	 */
688 	for (i = 0; i < vgen_tx_retries; ) {
689 		status = vgen_portsend(portp, mp);
690 		if (status == VGEN_SUCCESS) {
691 			break;
692 		}
693 		if (++i < vgen_tx_retries)
694 			delay(drv_usectohz(vgen_tx_delay));
695 	}
696 	if (status != VGEN_SUCCESS) {
697 		/* failure */
698 		return (mp);
699 	}
700 	/* success */
701 	return (NULL);
702 }
703 
704 /*
705  * This function provides any necessary tagging/untagging of the frames
706  * that are being transmitted over the port. It first verifies the vlan
707  * membership of the destination(port) and drops the packet if the
708  * destination doesn't belong to the given vlan.
709  *
710  * Arguments:
711  *   portp:     port over which the frames should be transmitted
712  *   mp:        frame to be transmitted
713  *   is_tagged:
714  *              B_TRUE: indicates frame header contains the vlan tag already.
715  *              B_FALSE: indicates frame is untagged.
716  *   vid:       vlan in which the frame should be transmitted.
717  *
718  * Returns:
719  *              Sucess: frame(mblk_t *) after doing the necessary tag/untag.
720  *              Failure: NULL
721  */
722 static mblk_t *
723 vgen_vlan_frame_fixtag(vgen_port_t *portp, mblk_t *mp, boolean_t is_tagged,
724 	uint16_t vid)
725 {
726 	vgen_t				*vgenp;
727 	boolean_t			dst_tagged;
728 	int				rv;
729 
730 	vgenp = portp->vgenp;
731 
732 	/*
733 	 * If the packet is going to a vnet:
734 	 *   Check if the destination vnet is in the same vlan.
735 	 *   Check the frame header if tag or untag is needed.
736 	 *
737 	 * We do not check the above conditions if the packet is going to vsw:
738 	 *   vsw must be present implicitly in all the vlans that a vnet device
739 	 *   is configured into; even if vsw itself is not assigned to those
740 	 *   vlans as an interface. For instance, the packet might be destined
741 	 *   to another vnet(indirectly through vsw) or to an external host
742 	 *   which is in the same vlan as this vnet and vsw itself may not be
743 	 *   present in that vlan. Similarly packets going to vsw must be
744 	 *   always tagged(unless in the default-vlan) if not already tagged,
745 	 *   as we do not know the final destination. This is needed because
746 	 *   vsw must always invoke its switching function only after tagging
747 	 *   the packet; otherwise after switching function determines the
748 	 *   destination we cannot figure out if the destination belongs to the
749 	 *   the same vlan that the frame originated from and if it needs tag/
750 	 *   untag. Note that vsw will tag the packet itself when it receives
751 	 *   it over the channel from a client if needed. However, that is
752 	 *   needed only in the case of vlan unaware clients such as obp or
753 	 *   earlier versions of vnet.
754 	 *
755 	 */
756 	if (portp != vgenp->vsw_portp) {
757 		/*
758 		 * Packet going to a vnet. Check if the destination vnet is in
759 		 * the same vlan. Then check the frame header if tag/untag is
760 		 * needed.
761 		 */
762 		rv = vgen_vlan_lookup(portp->vlan_hashp, vid);
763 		if (rv == B_FALSE) {
764 			/* drop the packet */
765 			freemsg(mp);
766 			return (NULL);
767 		}
768 
769 		/* is the destination tagged or untagged in this vlan? */
770 		(vid == portp->pvid) ? (dst_tagged = B_FALSE) :
771 		    (dst_tagged = B_TRUE);
772 
773 		if (is_tagged == dst_tagged) {
774 			/* no tagging/untagging needed */
775 			return (mp);
776 		}
777 
778 		if (is_tagged == B_TRUE) {
779 			/* frame is tagged; destination needs untagged */
780 			mp = vnet_vlan_remove_tag(mp);
781 			return (mp);
782 		}
783 
784 		/* (is_tagged == B_FALSE): fallthru to tag tx packet: */
785 	}
786 
787 	/*
788 	 * Packet going to a vnet needs tagging.
789 	 * OR
790 	 * If the packet is going to vsw, then it must be tagged in all cases:
791 	 * unknown unicast, broadcast/multicast or to vsw interface.
792 	 */
793 
794 	if (is_tagged == B_FALSE) {
795 		mp = vnet_vlan_insert_tag(mp, vid);
796 	}
797 
798 	return (mp);
799 }
800 
801 /* transmit packets over the given port */
802 static int
803 vgen_portsend(vgen_port_t *portp, mblk_t *mp)
804 {
805 	vgen_ldclist_t		*ldclp;
806 	vgen_ldc_t		*ldcp;
807 	int			status;
808 	int			rv = VGEN_SUCCESS;
809 	vgen_t			*vgenp = portp->vgenp;
810 	vnet_t			*vnetp = vgenp->vnetp;
811 	boolean_t		is_tagged;
812 	boolean_t		dec_refcnt = B_FALSE;
813 	uint16_t		vlan_id;
814 	struct ether_header	*ehp;
815 
816 	if (portp->use_vsw_port) {
817 		(void) atomic_inc_32(&vgenp->vsw_port_refcnt);
818 		portp = portp->vgenp->vsw_portp;
819 		dec_refcnt = B_TRUE;
820 	}
821 	if (portp == NULL) {
822 		return (VGEN_FAILURE);
823 	}
824 
825 	/*
826 	 * Determine the vlan id that the frame belongs to.
827 	 */
828 	ehp = (struct ether_header *)mp->b_rptr;
829 	is_tagged = vgen_frame_lookup_vid(vnetp, ehp, &vlan_id);
830 
831 	if (vlan_id == vnetp->default_vlan_id) {
832 
833 		/* Frames in default vlan must be untagged */
834 		ASSERT(is_tagged == B_FALSE);
835 
836 		/*
837 		 * If the destination is a vnet-port verify it belongs to the
838 		 * default vlan; otherwise drop the packet. We do not need
839 		 * this check for vsw-port, as it should implicitly belong to
840 		 * this vlan; see comments in vgen_vlan_frame_fixtag().
841 		 */
842 		if (portp != vgenp->vsw_portp &&
843 		    portp->pvid != vnetp->default_vlan_id) {
844 			freemsg(mp);
845 			goto portsend_ret;
846 		}
847 
848 	} else {	/* frame not in default-vlan */
849 
850 		mp = vgen_vlan_frame_fixtag(portp, mp, is_tagged, vlan_id);
851 		if (mp == NULL) {
852 			goto portsend_ret;
853 		}
854 
855 	}
856 
857 	ldclp = &portp->ldclist;
858 	READ_ENTER(&ldclp->rwlock);
859 	/*
860 	 * NOTE: for now, we will assume we have a single channel.
861 	 */
862 	if (ldclp->headp == NULL) {
863 		RW_EXIT(&ldclp->rwlock);
864 		rv = VGEN_FAILURE;
865 		goto portsend_ret;
866 	}
867 	ldcp = ldclp->headp;
868 
869 	status = ldcp->tx(ldcp, mp);
870 
871 	RW_EXIT(&ldclp->rwlock);
872 
873 	if (status != VGEN_TX_SUCCESS) {
874 		rv = VGEN_FAILURE;
875 	}
876 
877 portsend_ret:
878 	if (dec_refcnt == B_TRUE) {
879 		(void) atomic_dec_32(&vgenp->vsw_port_refcnt);
880 	}
881 	return (rv);
882 }
883 
884 /*
885  * Wrapper function to transmit normal and/or priority frames over the channel.
886  */
887 static int
888 vgen_ldcsend(void *arg, mblk_t *mp)
889 {
890 	vgen_ldc_t		*ldcp = (vgen_ldc_t *)arg;
891 	int			status;
892 	struct ether_header	*ehp;
893 	vgen_t			*vgenp = LDC_TO_VGEN(ldcp);
894 	uint32_t		num_types;
895 	uint16_t		*types;
896 	int			i;
897 
898 	ASSERT(VGEN_PRI_ETH_DEFINED(vgenp));
899 
900 	num_types = vgenp->pri_num_types;
901 	types = vgenp->pri_types;
902 	ehp = (struct ether_header *)mp->b_rptr;
903 
904 	for (i = 0; i < num_types; i++) {
905 
906 		if (ehp->ether_type == types[i]) {
907 			/* priority frame, use pri tx function */
908 			vgen_ldcsend_pkt(ldcp, mp);
909 			return (VGEN_SUCCESS);
910 		}
911 
912 	}
913 
914 	status  = vgen_ldcsend_dring(ldcp, mp);
915 
916 	return (status);
917 }
918 
919 /*
920  * This functions handles ldc channel reset while in the context
921  * of transmit routines: vgen_ldcsend_pkt() or vgen_ldcsend_dring().
922  */
923 static void
924 vgen_ldcsend_process_reset(vgen_ldc_t *ldcp)
925 {
926 	ldc_status_t	istatus;
927 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
928 
929 	if (mutex_tryenter(&ldcp->cblock)) {
930 		if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
931 			DWARN(vgenp, ldcp, "ldc_status() error\n");
932 		} else {
933 			ldcp->ldc_status = istatus;
934 		}
935 		if (ldcp->ldc_status != LDC_UP) {
936 			vgen_handle_evt_reset(ldcp);
937 		}
938 		mutex_exit(&ldcp->cblock);
939 	}
940 }
941 
942 /*
943  * This function transmits the frame in the payload of a raw data
944  * (VIO_PKT_DATA) message. Thus, it provides an Out-Of-Band path to
945  * send special frames with high priorities, without going through
946  * the normal data path which uses descriptor ring mechanism.
947  */
948 static void
949 vgen_ldcsend_pkt(void *arg, mblk_t *mp)
950 {
951 	vgen_ldc_t		*ldcp = (vgen_ldc_t *)arg;
952 	vio_raw_data_msg_t	*pkt;
953 	mblk_t			*bp;
954 	mblk_t			*nmp = NULL;
955 	caddr_t			dst;
956 	uint32_t		mblksz;
957 	uint32_t		size;
958 	uint32_t		nbytes;
959 	int			rv;
960 	vgen_t			*vgenp = LDC_TO_VGEN(ldcp);
961 	vgen_stats_t		*statsp = &ldcp->stats;
962 
963 	/* drop the packet if ldc is not up or handshake is not done */
964 	if (ldcp->ldc_status != LDC_UP) {
965 		(void) atomic_inc_32(&statsp->tx_pri_fail);
966 		DWARN(vgenp, ldcp, "status(%d), dropping packet\n",
967 		    ldcp->ldc_status);
968 		goto send_pkt_exit;
969 	}
970 
971 	if (ldcp->hphase != VH_DONE) {
972 		(void) atomic_inc_32(&statsp->tx_pri_fail);
973 		DWARN(vgenp, ldcp, "hphase(%x), dropping packet\n",
974 		    ldcp->hphase);
975 		goto send_pkt_exit;
976 	}
977 
978 	size = msgsize(mp);
979 
980 	/* frame size bigger than available payload len of raw data msg ? */
981 	if (size > (size_t)(ldcp->msglen - VIO_PKT_DATA_HDRSIZE)) {
982 		(void) atomic_inc_32(&statsp->tx_pri_fail);
983 		DWARN(vgenp, ldcp, "invalid size(%d)\n", size);
984 		goto send_pkt_exit;
985 	}
986 
987 	if (size < ETHERMIN)
988 		size = ETHERMIN;
989 
990 	/* alloc space for a raw data message */
991 	nmp = vio_allocb(vgenp->pri_tx_vmp);
992 	if (nmp == NULL) {
993 		(void) atomic_inc_32(&statsp->tx_pri_fail);
994 		DWARN(vgenp, ldcp, "vio_allocb failed\n");
995 		goto send_pkt_exit;
996 	}
997 	pkt = (vio_raw_data_msg_t *)nmp->b_rptr;
998 
999 	/* copy frame into the payload of raw data message */
1000 	dst = (caddr_t)pkt->data;
1001 	for (bp = mp; bp != NULL; bp = bp->b_cont) {
1002 		mblksz = MBLKL(bp);
1003 		bcopy(bp->b_rptr, dst, mblksz);
1004 		dst += mblksz;
1005 	}
1006 
1007 	/* setup the raw data msg */
1008 	pkt->tag.vio_msgtype = VIO_TYPE_DATA;
1009 	pkt->tag.vio_subtype = VIO_SUBTYPE_INFO;
1010 	pkt->tag.vio_subtype_env = VIO_PKT_DATA;
1011 	pkt->tag.vio_sid = ldcp->local_sid;
1012 	nbytes = VIO_PKT_DATA_HDRSIZE + size;
1013 
1014 	/* send the msg over ldc */
1015 	rv = vgen_sendmsg(ldcp, (caddr_t)pkt, nbytes, B_FALSE);
1016 	if (rv != VGEN_SUCCESS) {
1017 		(void) atomic_inc_32(&statsp->tx_pri_fail);
1018 		DWARN(vgenp, ldcp, "Error sending priority frame\n");
1019 		if (rv == ECONNRESET) {
1020 			vgen_ldcsend_process_reset(ldcp);
1021 		}
1022 		goto send_pkt_exit;
1023 	}
1024 
1025 	/* update stats */
1026 	(void) atomic_inc_64(&statsp->tx_pri_packets);
1027 	(void) atomic_add_64(&statsp->tx_pri_bytes, size);
1028 
1029 send_pkt_exit:
1030 	if (nmp != NULL)
1031 		freemsg(nmp);
1032 	freemsg(mp);
1033 }
1034 
1035 /*
1036  * This function transmits normal (non-priority) data frames over
1037  * the channel. It queues the frame into the transmit descriptor ring
1038  * and sends a VIO_DRING_DATA message if needed, to wake up the
1039  * peer to (re)start processing.
1040  */
1041 static int
1042 vgen_ldcsend_dring(void *arg, mblk_t *mp)
1043 {
1044 	vgen_ldc_t		*ldcp = (vgen_ldc_t *)arg;
1045 	vgen_private_desc_t	*tbufp;
1046 	vgen_private_desc_t	*rtbufp;
1047 	vnet_public_desc_t	*rtxdp;
1048 	vgen_private_desc_t	*ntbufp;
1049 	vnet_public_desc_t	*txdp;
1050 	vio_dring_entry_hdr_t	*hdrp;
1051 	vgen_stats_t		*statsp;
1052 	struct ether_header	*ehp;
1053 	boolean_t		is_bcast = B_FALSE;
1054 	boolean_t		is_mcast = B_FALSE;
1055 	size_t			mblksz;
1056 	caddr_t			dst;
1057 	mblk_t			*bp;
1058 	size_t			size;
1059 	int			rv = 0;
1060 	vgen_t			*vgenp = LDC_TO_VGEN(ldcp);
1061 	vgen_hparams_t		*lp = &ldcp->local_hparams;
1062 
1063 	statsp = &ldcp->stats;
1064 	size = msgsize(mp);
1065 
1066 	DBG1(vgenp, ldcp, "enter\n");
1067 
1068 	if (ldcp->ldc_status != LDC_UP) {
1069 		DWARN(vgenp, ldcp, "status(%d), dropping packet\n",
1070 		    ldcp->ldc_status);
1071 		/* retry ldc_up() if needed */
1072 		if (ldcp->flags & CHANNEL_STARTED)
1073 			(void) ldc_up(ldcp->ldc_handle);
1074 		goto send_dring_exit;
1075 	}
1076 
1077 	/* drop the packet if ldc is not up or handshake is not done */
1078 	if (ldcp->hphase != VH_DONE) {
1079 		DWARN(vgenp, ldcp, "hphase(%x), dropping packet\n",
1080 		    ldcp->hphase);
1081 		goto send_dring_exit;
1082 	}
1083 
1084 	if (size > (size_t)lp->mtu) {
1085 		DWARN(vgenp, ldcp, "invalid size(%d)\n", size);
1086 		goto send_dring_exit;
1087 	}
1088 	if (size < ETHERMIN)
1089 		size = ETHERMIN;
1090 
1091 	ehp = (struct ether_header *)mp->b_rptr;
1092 	is_bcast = IS_BROADCAST(ehp);
1093 	is_mcast = IS_MULTICAST(ehp);
1094 
1095 	mutex_enter(&ldcp->txlock);
1096 	/*
1097 	 * allocate a descriptor
1098 	 */
1099 	tbufp = ldcp->next_tbufp;
1100 	ntbufp = NEXTTBUF(ldcp, tbufp);
1101 	if (ntbufp == ldcp->cur_tbufp) { /* out of tbufs/txds */
1102 
1103 		mutex_enter(&ldcp->tclock);
1104 		/* Try reclaiming now */
1105 		vgen_reclaim_dring(ldcp);
1106 		ldcp->reclaim_lbolt = ddi_get_lbolt();
1107 
1108 		if (ntbufp == ldcp->cur_tbufp) {
1109 			/* Now we are really out of tbuf/txds */
1110 			ldcp->need_resched = B_TRUE;
1111 			mutex_exit(&ldcp->tclock);
1112 
1113 			statsp->tx_no_desc++;
1114 			mutex_exit(&ldcp->txlock);
1115 
1116 			return (VGEN_TX_NORESOURCES);
1117 		}
1118 		mutex_exit(&ldcp->tclock);
1119 	}
1120 	/* update next available tbuf in the ring and update tx index */
1121 	ldcp->next_tbufp = ntbufp;
1122 	INCR_TXI(ldcp->next_txi, ldcp);
1123 
1124 	/* Mark the buffer busy before releasing the lock */
1125 	tbufp->flags = VGEN_PRIV_DESC_BUSY;
1126 	mutex_exit(&ldcp->txlock);
1127 
1128 	/* copy data into pre-allocated transmit buffer */
1129 	dst = tbufp->datap + VNET_IPALIGN;
1130 	for (bp = mp; bp != NULL; bp = bp->b_cont) {
1131 		mblksz = MBLKL(bp);
1132 		bcopy(bp->b_rptr, dst, mblksz);
1133 		dst += mblksz;
1134 	}
1135 
1136 	tbufp->datalen = size;
1137 
1138 	/* initialize the corresponding public descriptor (txd) */
1139 	txdp = tbufp->descp;
1140 	hdrp = &txdp->hdr;
1141 	txdp->nbytes = size;
1142 	txdp->ncookies = tbufp->ncookies;
1143 	bcopy((tbufp->memcookie), (txdp->memcookie),
1144 	    tbufp->ncookies * sizeof (ldc_mem_cookie_t));
1145 
1146 	mutex_enter(&ldcp->wrlock);
1147 	/*
1148 	 * If the flags not set to BUSY, it implies that the clobber
1149 	 * was done while we were copying the data. In such case,
1150 	 * discard the packet and return.
1151 	 */
1152 	if (tbufp->flags != VGEN_PRIV_DESC_BUSY) {
1153 		statsp->oerrors++;
1154 		mutex_exit(&ldcp->wrlock);
1155 		goto send_dring_exit;
1156 	}
1157 	hdrp->dstate = VIO_DESC_READY;
1158 
1159 	/* update stats */
1160 	statsp->opackets++;
1161 	statsp->obytes += size;
1162 	if (is_bcast)
1163 		statsp->brdcstxmt++;
1164 	else if (is_mcast)
1165 		statsp->multixmt++;
1166 
1167 	/* send dring datamsg to the peer */
1168 	if (ldcp->resched_peer) {
1169 
1170 		rtbufp = &ldcp->tbufp[ldcp->resched_peer_txi];
1171 		rtxdp = rtbufp->descp;
1172 
1173 		if (rtxdp->hdr.dstate == VIO_DESC_READY) {
1174 
1175 			rv = vgen_send_dring_data(ldcp,
1176 			    (uint32_t)ldcp->resched_peer_txi, -1);
1177 			if (rv != 0) {
1178 				/* error: drop the packet */
1179 				DWARN(vgenp, ldcp, "vgen_send_dring_data "
1180 				    "failed: rv(%d) len(%d)\n",
1181 				    ldcp->ldc_id, rv, size);
1182 				statsp->oerrors++;
1183 			} else {
1184 				ldcp->resched_peer = B_FALSE;
1185 			}
1186 
1187 		}
1188 
1189 	}
1190 
1191 	mutex_exit(&ldcp->wrlock);
1192 
1193 send_dring_exit:
1194 	if (rv == ECONNRESET) {
1195 		vgen_ldcsend_process_reset(ldcp);
1196 	}
1197 	freemsg(mp);
1198 	DBG1(vgenp, ldcp, "exit\n");
1199 	return (VGEN_TX_SUCCESS);
1200 }
1201 
1202 /* enable/disable a multicast address */
1203 int
1204 vgen_multicst(void *arg, boolean_t add, const uint8_t *mca)
1205 {
1206 	vgen_t			*vgenp;
1207 	vnet_mcast_msg_t	mcastmsg;
1208 	vio_msg_tag_t		*tagp;
1209 	vgen_port_t		*portp;
1210 	vgen_portlist_t		*plistp;
1211 	vgen_ldc_t		*ldcp;
1212 	vgen_ldclist_t		*ldclp;
1213 	struct ether_addr	*addrp;
1214 	int			rv = DDI_FAILURE;
1215 	uint32_t		i;
1216 
1217 	portp = (vgen_port_t *)arg;
1218 	vgenp = portp->vgenp;
1219 
1220 	if (portp != vgenp->vsw_portp) {
1221 		return (DDI_SUCCESS);
1222 	}
1223 
1224 	addrp = (struct ether_addr *)mca;
1225 	tagp = &mcastmsg.tag;
1226 	bzero(&mcastmsg, sizeof (mcastmsg));
1227 
1228 	mutex_enter(&vgenp->lock);
1229 
1230 	plistp = &(vgenp->vgenports);
1231 
1232 	READ_ENTER(&plistp->rwlock);
1233 
1234 	portp = vgenp->vsw_portp;
1235 	if (portp == NULL) {
1236 		RW_EXIT(&plistp->rwlock);
1237 		mutex_exit(&vgenp->lock);
1238 		return (rv);
1239 	}
1240 	ldclp = &portp->ldclist;
1241 
1242 	READ_ENTER(&ldclp->rwlock);
1243 
1244 	ldcp = ldclp->headp;
1245 	if (ldcp == NULL)
1246 		goto vgen_mcast_exit;
1247 
1248 	mutex_enter(&ldcp->cblock);
1249 
1250 	if (ldcp->hphase == VH_DONE) {
1251 		/*
1252 		 * If handshake is done, send a msg to vsw to add/remove
1253 		 * the multicast address. Otherwise, we just update this
1254 		 * mcast address in our table and the table will be sync'd
1255 		 * with vsw when handshake completes.
1256 		 */
1257 		tagp->vio_msgtype = VIO_TYPE_CTRL;
1258 		tagp->vio_subtype = VIO_SUBTYPE_INFO;
1259 		tagp->vio_subtype_env = VNET_MCAST_INFO;
1260 		tagp->vio_sid = ldcp->local_sid;
1261 		bcopy(mca, &(mcastmsg.mca), ETHERADDRL);
1262 		mcastmsg.set = add;
1263 		mcastmsg.count = 1;
1264 		if (vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (mcastmsg),
1265 		    B_FALSE) != VGEN_SUCCESS) {
1266 			DWARN(vgenp, ldcp, "vgen_sendmsg failed\n");
1267 			mutex_exit(&ldcp->cblock);
1268 			goto vgen_mcast_exit;
1269 		}
1270 	}
1271 
1272 	mutex_exit(&ldcp->cblock);
1273 
1274 	if (add) {
1275 
1276 		/* expand multicast table if necessary */
1277 		if (vgenp->mccount >= vgenp->mcsize) {
1278 			struct ether_addr	*newtab;
1279 			uint32_t		newsize;
1280 
1281 
1282 			newsize = vgenp->mcsize * 2;
1283 
1284 			newtab = kmem_zalloc(newsize *
1285 			    sizeof (struct ether_addr), KM_NOSLEEP);
1286 			if (newtab == NULL)
1287 				goto vgen_mcast_exit;
1288 			bcopy(vgenp->mctab, newtab, vgenp->mcsize *
1289 			    sizeof (struct ether_addr));
1290 			kmem_free(vgenp->mctab,
1291 			    vgenp->mcsize * sizeof (struct ether_addr));
1292 
1293 			vgenp->mctab = newtab;
1294 			vgenp->mcsize = newsize;
1295 		}
1296 
1297 		/* add address to the table */
1298 		vgenp->mctab[vgenp->mccount++] = *addrp;
1299 
1300 	} else {
1301 
1302 		/* delete address from the table */
1303 		for (i = 0; i < vgenp->mccount; i++) {
1304 			if (ether_cmp(addrp, &(vgenp->mctab[i])) == 0) {
1305 
1306 				/*
1307 				 * If there's more than one address in this
1308 				 * table, delete the unwanted one by moving
1309 				 * the last one in the list over top of it;
1310 				 * otherwise, just remove it.
1311 				 */
1312 				if (vgenp->mccount > 1) {
1313 					vgenp->mctab[i] =
1314 					    vgenp->mctab[vgenp->mccount-1];
1315 				}
1316 				vgenp->mccount--;
1317 				break;
1318 			}
1319 		}
1320 	}
1321 
1322 	rv = DDI_SUCCESS;
1323 
1324 vgen_mcast_exit:
1325 	RW_EXIT(&ldclp->rwlock);
1326 	RW_EXIT(&plistp->rwlock);
1327 
1328 	mutex_exit(&vgenp->lock);
1329 	return (rv);
1330 }
1331 
1332 /* set or clear promiscuous mode on the device */
1333 static int
1334 vgen_promisc(void *arg, boolean_t on)
1335 {
1336 	_NOTE(ARGUNUSED(arg, on))
1337 	return (DDI_SUCCESS);
1338 }
1339 
1340 /* set the unicast mac address of the device */
1341 static int
1342 vgen_unicst(void *arg, const uint8_t *mca)
1343 {
1344 	_NOTE(ARGUNUSED(arg, mca))
1345 	return (DDI_SUCCESS);
1346 }
1347 
1348 /* get device statistics */
1349 int
1350 vgen_stat(void *arg, uint_t stat, uint64_t *val)
1351 {
1352 	vgen_port_t	*portp = (vgen_port_t *)arg;
1353 
1354 	*val = vgen_port_stat(portp, stat);
1355 
1356 	return (0);
1357 }
1358 
1359 static void
1360 vgen_ioctl(void *arg, queue_t *wq, mblk_t *mp)
1361 {
1362 	 _NOTE(ARGUNUSED(arg, wq, mp))
1363 }
1364 
1365 /* vgen internal functions */
1366 /* detach all ports from the device */
1367 static void
1368 vgen_detach_ports(vgen_t *vgenp)
1369 {
1370 	vgen_port_t	*portp;
1371 	vgen_portlist_t	*plistp;
1372 
1373 	plistp = &(vgenp->vgenports);
1374 	WRITE_ENTER(&plistp->rwlock);
1375 	while ((portp = plistp->headp) != NULL) {
1376 		vgen_port_detach(portp);
1377 	}
1378 	RW_EXIT(&plistp->rwlock);
1379 }
1380 
1381 /*
1382  * detach the given port.
1383  */
1384 static void
1385 vgen_port_detach(vgen_port_t *portp)
1386 {
1387 	vgen_t		*vgenp;
1388 	vgen_ldclist_t	*ldclp;
1389 	int		port_num;
1390 
1391 	vgenp = portp->vgenp;
1392 	port_num = portp->port_num;
1393 
1394 	DBG1(vgenp, NULL, "port(%d):enter\n", port_num);
1395 
1396 	/*
1397 	 * If this port is connected to the vswitch, then
1398 	 * potentially there could be ports that may be using
1399 	 * this port to transmit packets. To address this do
1400 	 * the following:
1401 	 *	- First set vgenp->vsw_portp to NULL, so that
1402 	 *	  its not used after that.
1403 	 *	- Then wait for the refcnt to go down to 0.
1404 	 *	- Now we can safely detach this port.
1405 	 */
1406 	if (vgenp->vsw_portp == portp) {
1407 		vgenp->vsw_portp = NULL;
1408 		while (vgenp->vsw_port_refcnt > 0) {
1409 			delay(drv_usectohz(vgen_tx_delay));
1410 		}
1411 		(void) atomic_swap_32(&vgenp->vsw_port_refcnt, 0);
1412 	}
1413 
1414 	if (portp->vhp != NULL) {
1415 		vio_net_resource_unreg(portp->vhp);
1416 		portp->vhp = NULL;
1417 	}
1418 
1419 	vgen_vlan_destroy_hash(portp);
1420 
1421 	/* remove it from port list */
1422 	vgen_port_list_remove(portp);
1423 
1424 	/* detach channels from this port */
1425 	ldclp = &portp->ldclist;
1426 	WRITE_ENTER(&ldclp->rwlock);
1427 	while (ldclp->headp) {
1428 		vgen_ldc_detach(ldclp->headp);
1429 	}
1430 	RW_EXIT(&ldclp->rwlock);
1431 	rw_destroy(&ldclp->rwlock);
1432 
1433 	if (portp->num_ldcs != 0) {
1434 		kmem_free(portp->ldc_ids, portp->num_ldcs * sizeof (uint64_t));
1435 		portp->num_ldcs = 0;
1436 	}
1437 
1438 	mutex_destroy(&portp->lock);
1439 	KMEM_FREE(portp);
1440 
1441 	DBG1(vgenp, NULL, "port(%d):exit\n", port_num);
1442 }
1443 
1444 /* add a port to port list */
1445 static void
1446 vgen_port_list_insert(vgen_port_t *portp)
1447 {
1448 	vgen_portlist_t *plistp;
1449 	vgen_t *vgenp;
1450 
1451 	vgenp = portp->vgenp;
1452 	plistp = &(vgenp->vgenports);
1453 
1454 	if (plistp->headp == NULL) {
1455 		plistp->headp = portp;
1456 	} else {
1457 		plistp->tailp->nextp = portp;
1458 	}
1459 	plistp->tailp = portp;
1460 	portp->nextp = NULL;
1461 }
1462 
1463 /* remove a port from port list */
1464 static void
1465 vgen_port_list_remove(vgen_port_t *portp)
1466 {
1467 	vgen_port_t *prevp;
1468 	vgen_port_t *nextp;
1469 	vgen_portlist_t *plistp;
1470 	vgen_t *vgenp;
1471 
1472 	vgenp = portp->vgenp;
1473 
1474 	plistp = &(vgenp->vgenports);
1475 
1476 	if (plistp->headp == NULL)
1477 		return;
1478 
1479 	if (portp == plistp->headp) {
1480 		plistp->headp = portp->nextp;
1481 		if (portp == plistp->tailp)
1482 			plistp->tailp = plistp->headp;
1483 	} else {
1484 		for (prevp = plistp->headp;
1485 		    ((nextp = prevp->nextp) != NULL) && (nextp != portp);
1486 		    prevp = nextp)
1487 			;
1488 		if (nextp == portp) {
1489 			prevp->nextp = portp->nextp;
1490 		}
1491 		if (portp == plistp->tailp)
1492 			plistp->tailp = prevp;
1493 	}
1494 }
1495 
1496 /* lookup a port in the list based on port_num */
1497 static vgen_port_t *
1498 vgen_port_lookup(vgen_portlist_t *plistp, int port_num)
1499 {
1500 	vgen_port_t *portp = NULL;
1501 
1502 	for (portp = plistp->headp; portp != NULL; portp = portp->nextp) {
1503 		if (portp->port_num == port_num) {
1504 			break;
1505 		}
1506 	}
1507 
1508 	return (portp);
1509 }
1510 
1511 /* enable ports for transmit/receive */
1512 static void
1513 vgen_init_ports(vgen_t *vgenp)
1514 {
1515 	vgen_port_t	*portp;
1516 	vgen_portlist_t	*plistp;
1517 
1518 	plistp = &(vgenp->vgenports);
1519 	READ_ENTER(&plistp->rwlock);
1520 
1521 	for (portp = plistp->headp; portp != NULL; portp = portp->nextp) {
1522 		vgen_port_init(portp);
1523 	}
1524 
1525 	RW_EXIT(&plistp->rwlock);
1526 }
1527 
1528 static void
1529 vgen_port_init(vgen_port_t *portp)
1530 {
1531 	/* Add the port to the specified vlans */
1532 	vgen_vlan_add_ids(portp);
1533 
1534 	/* Bring up the channels of this port */
1535 	vgen_init_ldcs(portp);
1536 }
1537 
1538 /* disable transmit/receive on ports */
1539 static void
1540 vgen_uninit_ports(vgen_t *vgenp)
1541 {
1542 	vgen_port_t	*portp;
1543 	vgen_portlist_t	*plistp;
1544 
1545 	plistp = &(vgenp->vgenports);
1546 	READ_ENTER(&plistp->rwlock);
1547 
1548 	for (portp = plistp->headp; portp != NULL; portp = portp->nextp) {
1549 		vgen_port_uninit(portp);
1550 	}
1551 
1552 	RW_EXIT(&plistp->rwlock);
1553 }
1554 
1555 static void
1556 vgen_port_uninit(vgen_port_t *portp)
1557 {
1558 	vgen_uninit_ldcs(portp);
1559 
1560 	/* remove the port from vlans it has been assigned to */
1561 	vgen_vlan_remove_ids(portp);
1562 }
1563 
1564 /*
1565  * Scan the machine description for this instance of vnet
1566  * and read its properties. Called only from vgen_init().
1567  * Returns: 0 on success, 1 on failure.
1568  */
1569 static int
1570 vgen_read_mdprops(vgen_t *vgenp)
1571 {
1572 	vnet_t		*vnetp = vgenp->vnetp;
1573 	md_t		*mdp = NULL;
1574 	mde_cookie_t	rootnode;
1575 	mde_cookie_t	*listp = NULL;
1576 	uint64_t	cfgh;
1577 	char		*name;
1578 	int		rv = 1;
1579 	int		num_nodes = 0;
1580 	int		num_devs = 0;
1581 	int		listsz = 0;
1582 	int		i;
1583 
1584 	if ((mdp = md_get_handle()) == NULL) {
1585 		return (rv);
1586 	}
1587 
1588 	num_nodes = md_node_count(mdp);
1589 	ASSERT(num_nodes > 0);
1590 
1591 	listsz = num_nodes * sizeof (mde_cookie_t);
1592 	listp = (mde_cookie_t *)kmem_zalloc(listsz, KM_SLEEP);
1593 
1594 	rootnode = md_root_node(mdp);
1595 
1596 	/* search for all "virtual_device" nodes */
1597 	num_devs = md_scan_dag(mdp, rootnode,
1598 	    md_find_name(mdp, vdev_propname),
1599 	    md_find_name(mdp, "fwd"), listp);
1600 	if (num_devs <= 0) {
1601 		goto vgen_readmd_exit;
1602 	}
1603 
1604 	/*
1605 	 * Now loop through the list of virtual-devices looking for
1606 	 * devices with name "network" and for each such device compare
1607 	 * its instance with what we have from the 'reg' property to
1608 	 * find the right node in MD and then read all its properties.
1609 	 */
1610 	for (i = 0; i < num_devs; i++) {
1611 
1612 		if (md_get_prop_str(mdp, listp[i], "name", &name) != 0) {
1613 			goto vgen_readmd_exit;
1614 		}
1615 
1616 		/* is this a "network" device? */
1617 		if (strcmp(name, vnet_propname) != 0)
1618 			continue;
1619 
1620 		if (md_get_prop_val(mdp, listp[i], "cfg-handle", &cfgh) != 0) {
1621 			goto vgen_readmd_exit;
1622 		}
1623 
1624 		/* is this the required instance of vnet? */
1625 		if (vgenp->regprop != cfgh)
1626 			continue;
1627 
1628 		/*
1629 		 * Read the mtu. Note that we set the mtu of vnet device within
1630 		 * this routine itself, after validating the range.
1631 		 */
1632 		vgen_mtu_read(vgenp, mdp, listp[i], &vnetp->mtu);
1633 		if (vnetp->mtu < ETHERMTU || vnetp->mtu > VNET_MAX_MTU) {
1634 			vnetp->mtu = ETHERMTU;
1635 		}
1636 		vgenp->max_frame_size = vnetp->mtu +
1637 		    sizeof (struct ether_header) + VLAN_TAGSZ;
1638 
1639 		/* read priority ether types */
1640 		vgen_read_pri_eth_types(vgenp, mdp, listp[i]);
1641 
1642 		/* read vlan id properties of this vnet instance */
1643 		vgen_vlan_read_ids(vgenp, VGEN_LOCAL, mdp, listp[i],
1644 		    &vnetp->pvid, &vnetp->vids, &vnetp->nvids,
1645 		    &vnetp->default_vlan_id);
1646 
1647 		rv = 0;
1648 		break;
1649 	}
1650 
1651 vgen_readmd_exit:
1652 
1653 	kmem_free(listp, listsz);
1654 	(void) md_fini_handle(mdp);
1655 	return (rv);
1656 }
1657 
1658 /*
1659  * Read vlan id properties of the given MD node.
1660  * Arguments:
1661  *   arg:          device argument(vnet device or a port)
1662  *   type:         type of arg; VGEN_LOCAL(vnet device) or VGEN_PEER(port)
1663  *   mdp:          machine description
1664  *   node:         md node cookie
1665  *
1666  * Returns:
1667  *   pvidp:        port-vlan-id of the node
1668  *   vidspp:       list of vlan-ids of the node
1669  *   nvidsp:       # of vlan-ids in the list
1670  *   default_idp:  default-vlan-id of the node(if node is vnet device)
1671  */
1672 static void
1673 vgen_vlan_read_ids(void *arg, int type, md_t *mdp, mde_cookie_t node,
1674 	uint16_t *pvidp, uint16_t **vidspp, uint16_t *nvidsp,
1675 	uint16_t *default_idp)
1676 {
1677 	vgen_t		*vgenp;
1678 	vnet_t		*vnetp;
1679 	vgen_port_t	*portp;
1680 	char		*pvid_propname;
1681 	char		*vid_propname;
1682 	uint_t		nvids;
1683 	uint32_t	vids_size;
1684 	int		rv;
1685 	int		i;
1686 	uint64_t	*data;
1687 	uint64_t	val;
1688 	int		size;
1689 	int		inst;
1690 
1691 	if (type == VGEN_LOCAL) {
1692 
1693 		vgenp = (vgen_t *)arg;
1694 		vnetp = vgenp->vnetp;
1695 		pvid_propname = vgen_pvid_propname;
1696 		vid_propname = vgen_vid_propname;
1697 		inst = vnetp->instance;
1698 
1699 	} else if (type == VGEN_PEER) {
1700 
1701 		portp = (vgen_port_t *)arg;
1702 		vgenp = portp->vgenp;
1703 		vnetp = vgenp->vnetp;
1704 		pvid_propname = port_pvid_propname;
1705 		vid_propname = port_vid_propname;
1706 		inst = portp->port_num;
1707 
1708 	} else {
1709 		return;
1710 	}
1711 
1712 	if (type == VGEN_LOCAL && default_idp != NULL) {
1713 		rv = md_get_prop_val(mdp, node, vgen_dvid_propname, &val);
1714 		if (rv != 0) {
1715 			DWARN(vgenp, NULL, "prop(%s) not found",
1716 			    vgen_dvid_propname);
1717 
1718 			*default_idp = vnet_default_vlan_id;
1719 		} else {
1720 			*default_idp = val & 0xFFF;
1721 			DBG2(vgenp, NULL, "%s(%d): (%d)\n", vgen_dvid_propname,
1722 			    inst, *default_idp);
1723 		}
1724 	}
1725 
1726 	rv = md_get_prop_val(mdp, node, pvid_propname, &val);
1727 	if (rv != 0) {
1728 		DWARN(vgenp, NULL, "prop(%s) not found", pvid_propname);
1729 		*pvidp = vnet_default_vlan_id;
1730 	} else {
1731 
1732 		*pvidp = val & 0xFFF;
1733 		DBG2(vgenp, NULL, "%s(%d): (%d)\n",
1734 		    pvid_propname, inst, *pvidp);
1735 	}
1736 
1737 	rv = md_get_prop_data(mdp, node, vid_propname, (uint8_t **)&data,
1738 	    &size);
1739 	if (rv != 0) {
1740 		DBG2(vgenp, NULL, "prop(%s) not found", vid_propname);
1741 		size = 0;
1742 	} else {
1743 		size /= sizeof (uint64_t);
1744 	}
1745 	nvids = size;
1746 
1747 	if (nvids != 0) {
1748 		DBG2(vgenp, NULL, "%s(%d): ", vid_propname, inst);
1749 		vids_size = sizeof (uint16_t) * nvids;
1750 		*vidspp = kmem_zalloc(vids_size, KM_SLEEP);
1751 		for (i = 0; i < nvids; i++) {
1752 			(*vidspp)[i] = data[i] & 0xFFFF;
1753 			DBG2(vgenp, NULL, " %d ", (*vidspp)[i]);
1754 		}
1755 		DBG2(vgenp, NULL, "\n");
1756 	}
1757 
1758 	*nvidsp = nvids;
1759 }
1760 
1761 /*
1762  * Create a vlan id hash table for the given port.
1763  */
1764 static void
1765 vgen_vlan_create_hash(vgen_port_t *portp)
1766 {
1767 	char		hashname[MAXNAMELEN];
1768 
1769 	(void) snprintf(hashname, MAXNAMELEN, "port%d-vlan-hash",
1770 	    portp->port_num);
1771 
1772 	portp->vlan_nchains = vgen_vlan_nchains;
1773 	portp->vlan_hashp = mod_hash_create_idhash(hashname,
1774 	    portp->vlan_nchains, mod_hash_null_valdtor);
1775 }
1776 
1777 /*
1778  * Destroy the vlan id hash table in the given port.
1779  */
1780 static void
1781 vgen_vlan_destroy_hash(vgen_port_t *portp)
1782 {
1783 	if (portp->vlan_hashp != NULL) {
1784 		mod_hash_destroy_hash(portp->vlan_hashp);
1785 		portp->vlan_hashp = NULL;
1786 		portp->vlan_nchains = 0;
1787 	}
1788 }
1789 
1790 /*
1791  * Add a port to the vlans specified in its port properites.
1792  */
1793 static void
1794 vgen_vlan_add_ids(vgen_port_t *portp)
1795 {
1796 	int		rv;
1797 	int		i;
1798 
1799 	rv = mod_hash_insert(portp->vlan_hashp,
1800 	    (mod_hash_key_t)VLAN_ID_KEY(portp->pvid),
1801 	    (mod_hash_val_t)B_TRUE);
1802 	ASSERT(rv == 0);
1803 
1804 	for (i = 0; i < portp->nvids; i++) {
1805 		rv = mod_hash_insert(portp->vlan_hashp,
1806 		    (mod_hash_key_t)VLAN_ID_KEY(portp->vids[i]),
1807 		    (mod_hash_val_t)B_TRUE);
1808 		ASSERT(rv == 0);
1809 	}
1810 }
1811 
1812 /*
1813  * Remove a port from the vlans it has been assigned to.
1814  */
1815 static void
1816 vgen_vlan_remove_ids(vgen_port_t *portp)
1817 {
1818 	int		rv;
1819 	int		i;
1820 	mod_hash_val_t	vp;
1821 
1822 	rv = mod_hash_remove(portp->vlan_hashp,
1823 	    (mod_hash_key_t)VLAN_ID_KEY(portp->pvid),
1824 	    (mod_hash_val_t *)&vp);
1825 	ASSERT(rv == 0);
1826 
1827 	for (i = 0; i < portp->nvids; i++) {
1828 		rv = mod_hash_remove(portp->vlan_hashp,
1829 		    (mod_hash_key_t)VLAN_ID_KEY(portp->vids[i]),
1830 		    (mod_hash_val_t *)&vp);
1831 		ASSERT(rv == 0);
1832 	}
1833 }
1834 
1835 /*
1836  * Lookup the vlan id of the given tx frame. If it is a vlan-tagged frame,
1837  * then the vlan-id is available in the tag; otherwise, its vlan id is
1838  * implicitly obtained from the port-vlan-id of the vnet device.
1839  * The vlan id determined is returned in vidp.
1840  * Returns: B_TRUE if it is a tagged frame; B_FALSE if it is untagged.
1841  */
1842 static boolean_t
1843 vgen_frame_lookup_vid(vnet_t *vnetp, struct ether_header *ehp, uint16_t *vidp)
1844 {
1845 	struct ether_vlan_header	*evhp;
1846 
1847 	/* If it's a tagged frame, get the vlan id from vlan header */
1848 	if (ehp->ether_type == ETHERTYPE_VLAN) {
1849 
1850 		evhp = (struct ether_vlan_header *)ehp;
1851 		*vidp = VLAN_ID(ntohs(evhp->ether_tci));
1852 		return (B_TRUE);
1853 	}
1854 
1855 	/* Untagged frame, vlan-id is the pvid of vnet device */
1856 	*vidp = vnetp->pvid;
1857 	return (B_FALSE);
1858 }
1859 
1860 /*
1861  * Find the given vlan id in the hash table.
1862  * Return: B_TRUE if the id is found; B_FALSE if not found.
1863  */
1864 static boolean_t
1865 vgen_vlan_lookup(mod_hash_t *vlan_hashp, uint16_t vid)
1866 {
1867 	int		rv;
1868 	mod_hash_val_t	vp;
1869 
1870 	rv = mod_hash_find(vlan_hashp, VLAN_ID_KEY(vid), (mod_hash_val_t *)&vp);
1871 
1872 	if (rv != 0)
1873 		return (B_FALSE);
1874 
1875 	return (B_TRUE);
1876 }
1877 
1878 /*
1879  * This function reads "priority-ether-types" property from md. This property
1880  * is used to enable support for priority frames. Applications which need
1881  * guaranteed and timely delivery of certain high priority frames to/from
1882  * a vnet or vsw within ldoms, should configure this property by providing
1883  * the ether type(s) for which the priority facility is needed.
1884  * Normal data frames are delivered over a ldc channel using the descriptor
1885  * ring mechanism which is constrained by factors such as descriptor ring size,
1886  * the rate at which the ring is processed at the peer ldc end point, etc.
1887  * The priority mechanism provides an Out-Of-Band path to send/receive frames
1888  * as raw pkt data (VIO_PKT_DATA) messages over the channel, avoiding the
1889  * descriptor ring path and enables a more reliable and timely delivery of
1890  * frames to the peer.
1891  */
1892 static void
1893 vgen_read_pri_eth_types(vgen_t *vgenp, md_t *mdp, mde_cookie_t node)
1894 {
1895 	int		rv;
1896 	uint16_t	*types;
1897 	uint64_t	*data;
1898 	int		size;
1899 	int		i;
1900 	size_t		mblk_sz;
1901 
1902 	rv = md_get_prop_data(mdp, node, pri_types_propname,
1903 	    (uint8_t **)&data, &size);
1904 	if (rv != 0) {
1905 		/*
1906 		 * Property may not exist if we are running pre-ldoms1.1 f/w.
1907 		 * Check if 'vgen_pri_eth_type' has been set in that case.
1908 		 */
1909 		if (vgen_pri_eth_type != 0) {
1910 			size = sizeof (vgen_pri_eth_type);
1911 			data = &vgen_pri_eth_type;
1912 		} else {
1913 			DBG2(vgenp, NULL,
1914 			    "prop(%s) not found", pri_types_propname);
1915 			size = 0;
1916 		}
1917 	}
1918 
1919 	if (size == 0) {
1920 		vgenp->pri_num_types = 0;
1921 		return;
1922 	}
1923 
1924 	/*
1925 	 * we have some priority-ether-types defined;
1926 	 * allocate a table of these types and also
1927 	 * allocate a pool of mblks to transmit these
1928 	 * priority packets.
1929 	 */
1930 	size /= sizeof (uint64_t);
1931 	vgenp->pri_num_types = size;
1932 	vgenp->pri_types = kmem_zalloc(size * sizeof (uint16_t), KM_SLEEP);
1933 	for (i = 0, types = vgenp->pri_types; i < size; i++) {
1934 		types[i] = data[i] & 0xFFFF;
1935 	}
1936 	mblk_sz = (VIO_PKT_DATA_HDRSIZE + vgenp->max_frame_size + 7) & ~7;
1937 	(void) vio_create_mblks(vgen_pri_tx_nmblks, mblk_sz,
1938 	    &vgenp->pri_tx_vmp);
1939 }
1940 
1941 static void
1942 vgen_mtu_read(vgen_t *vgenp, md_t *mdp, mde_cookie_t node, uint32_t *mtu)
1943 {
1944 	int		rv;
1945 	uint64_t	val;
1946 	char		*mtu_propname;
1947 
1948 	mtu_propname = vgen_mtu_propname;
1949 
1950 	rv = md_get_prop_val(mdp, node, mtu_propname, &val);
1951 	if (rv != 0) {
1952 		DWARN(vgenp, NULL, "prop(%s) not found", mtu_propname);
1953 		*mtu = vnet_ethermtu;
1954 	} else {
1955 
1956 		*mtu = val & 0xFFFF;
1957 		DBG2(vgenp, NULL, "%s(%d): (%d)\n", mtu_propname,
1958 		    vgenp->instance, *mtu);
1959 	}
1960 }
1961 
1962 /* register with MD event generator */
1963 static int
1964 vgen_mdeg_reg(vgen_t *vgenp)
1965 {
1966 	mdeg_prop_spec_t	*pspecp;
1967 	mdeg_node_spec_t	*parentp;
1968 	uint_t			templatesz;
1969 	int			rv;
1970 	mdeg_handle_t		dev_hdl = NULL;
1971 	mdeg_handle_t		port_hdl = NULL;
1972 
1973 	templatesz = sizeof (vgen_prop_template);
1974 	pspecp = kmem_zalloc(templatesz, KM_NOSLEEP);
1975 	if (pspecp == NULL) {
1976 		return (DDI_FAILURE);
1977 	}
1978 	parentp = kmem_zalloc(sizeof (mdeg_node_spec_t), KM_NOSLEEP);
1979 	if (parentp == NULL) {
1980 		kmem_free(pspecp, templatesz);
1981 		return (DDI_FAILURE);
1982 	}
1983 
1984 	bcopy(vgen_prop_template, pspecp, templatesz);
1985 
1986 	/*
1987 	 * NOTE: The instance here refers to the value of "reg" property and
1988 	 * not the dev_info instance (ddi_get_instance()) of vnet.
1989 	 */
1990 	VGEN_SET_MDEG_PROP_INST(pspecp, vgenp->regprop);
1991 
1992 	parentp->namep = "virtual-device";
1993 	parentp->specp = pspecp;
1994 
1995 	/* save parentp in vgen_t */
1996 	vgenp->mdeg_parentp = parentp;
1997 
1998 	/*
1999 	 * Register an interest in 'virtual-device' nodes with a
2000 	 * 'name' property of 'network'
2001 	 */
2002 	rv = mdeg_register(parentp, &vdev_match, vgen_mdeg_cb, vgenp, &dev_hdl);
2003 	if (rv != MDEG_SUCCESS) {
2004 		DERR(vgenp, NULL, "mdeg_register failed\n");
2005 		goto mdeg_reg_fail;
2006 	}
2007 
2008 	/* Register an interest in 'port' nodes */
2009 	rv = mdeg_register(parentp, &vport_match, vgen_mdeg_port_cb, vgenp,
2010 	    &port_hdl);
2011 	if (rv != MDEG_SUCCESS) {
2012 		DERR(vgenp, NULL, "mdeg_register failed\n");
2013 		goto mdeg_reg_fail;
2014 	}
2015 
2016 	/* save mdeg handle in vgen_t */
2017 	vgenp->mdeg_dev_hdl = dev_hdl;
2018 	vgenp->mdeg_port_hdl = port_hdl;
2019 
2020 	return (DDI_SUCCESS);
2021 
2022 mdeg_reg_fail:
2023 	if (dev_hdl != NULL) {
2024 		(void) mdeg_unregister(dev_hdl);
2025 	}
2026 	KMEM_FREE(parentp);
2027 	kmem_free(pspecp, templatesz);
2028 	vgenp->mdeg_parentp = NULL;
2029 	return (DDI_FAILURE);
2030 }
2031 
2032 /* unregister with MD event generator */
2033 static void
2034 vgen_mdeg_unreg(vgen_t *vgenp)
2035 {
2036 	(void) mdeg_unregister(vgenp->mdeg_dev_hdl);
2037 	(void) mdeg_unregister(vgenp->mdeg_port_hdl);
2038 	kmem_free(vgenp->mdeg_parentp->specp, sizeof (vgen_prop_template));
2039 	KMEM_FREE(vgenp->mdeg_parentp);
2040 	vgenp->mdeg_parentp = NULL;
2041 	vgenp->mdeg_dev_hdl = NULL;
2042 	vgenp->mdeg_port_hdl = NULL;
2043 }
2044 
2045 /* mdeg callback function for the port node */
2046 static int
2047 vgen_mdeg_port_cb(void *cb_argp, mdeg_result_t *resp)
2048 {
2049 	int idx;
2050 	int vsw_idx = -1;
2051 	uint64_t val;
2052 	vgen_t *vgenp;
2053 
2054 	if ((resp == NULL) || (cb_argp == NULL)) {
2055 		return (MDEG_FAILURE);
2056 	}
2057 
2058 	vgenp = (vgen_t *)cb_argp;
2059 	DBG1(vgenp, NULL, "enter\n");
2060 
2061 	mutex_enter(&vgenp->lock);
2062 
2063 	DBG1(vgenp, NULL, "ports: removed(%x), "
2064 	"added(%x), updated(%x)\n", resp->removed.nelem,
2065 	    resp->added.nelem, resp->match_curr.nelem);
2066 
2067 	for (idx = 0; idx < resp->removed.nelem; idx++) {
2068 		(void) vgen_remove_port(vgenp, resp->removed.mdp,
2069 		    resp->removed.mdep[idx]);
2070 	}
2071 
2072 	if (vgenp->vsw_portp == NULL) {
2073 		/*
2074 		 * find vsw_port and add it first, because other ports need
2075 		 * this when adding fdb entry (see vgen_port_init()).
2076 		 */
2077 		for (idx = 0; idx < resp->added.nelem; idx++) {
2078 			if (!(md_get_prop_val(resp->added.mdp,
2079 			    resp->added.mdep[idx], swport_propname, &val))) {
2080 				if (val == 0) {
2081 					/*
2082 					 * This port is connected to the
2083 					 * vsw on service domain.
2084 					 */
2085 					vsw_idx = idx;
2086 					if (vgen_add_port(vgenp,
2087 					    resp->added.mdp,
2088 					    resp->added.mdep[idx]) !=
2089 					    DDI_SUCCESS) {
2090 						cmn_err(CE_NOTE, "vnet%d Could "
2091 						    "not initialize virtual "
2092 						    "switch port.",
2093 						    vgenp->instance);
2094 						mutex_exit(&vgenp->lock);
2095 						return (MDEG_FAILURE);
2096 					}
2097 					break;
2098 				}
2099 			}
2100 		}
2101 		if (vsw_idx == -1) {
2102 			DWARN(vgenp, NULL, "can't find vsw_port\n");
2103 			mutex_exit(&vgenp->lock);
2104 			return (MDEG_FAILURE);
2105 		}
2106 	}
2107 
2108 	for (idx = 0; idx < resp->added.nelem; idx++) {
2109 		if ((vsw_idx != -1) && (vsw_idx == idx)) /* skip vsw_port */
2110 			continue;
2111 
2112 		/* If this port can't be added just skip it. */
2113 		(void) vgen_add_port(vgenp, resp->added.mdp,
2114 		    resp->added.mdep[idx]);
2115 	}
2116 
2117 	for (idx = 0; idx < resp->match_curr.nelem; idx++) {
2118 		(void) vgen_update_port(vgenp, resp->match_curr.mdp,
2119 		    resp->match_curr.mdep[idx],
2120 		    resp->match_prev.mdp,
2121 		    resp->match_prev.mdep[idx]);
2122 	}
2123 
2124 	mutex_exit(&vgenp->lock);
2125 	DBG1(vgenp, NULL, "exit\n");
2126 	return (MDEG_SUCCESS);
2127 }
2128 
2129 /* mdeg callback function for the vnet node */
2130 static int
2131 vgen_mdeg_cb(void *cb_argp, mdeg_result_t *resp)
2132 {
2133 	vgen_t		*vgenp;
2134 	vnet_t		*vnetp;
2135 	md_t		*mdp;
2136 	mde_cookie_t	node;
2137 	uint64_t	inst;
2138 	char		*node_name = NULL;
2139 
2140 	if ((resp == NULL) || (cb_argp == NULL)) {
2141 		return (MDEG_FAILURE);
2142 	}
2143 
2144 	vgenp = (vgen_t *)cb_argp;
2145 	vnetp = vgenp->vnetp;
2146 
2147 	DBG1(vgenp, NULL, "added %d : removed %d : curr matched %d"
2148 	    " : prev matched %d", resp->added.nelem, resp->removed.nelem,
2149 	    resp->match_curr.nelem, resp->match_prev.nelem);
2150 
2151 	mutex_enter(&vgenp->lock);
2152 
2153 	/*
2154 	 * We get an initial callback for this node as 'added' after
2155 	 * registering with mdeg. Note that we would have already gathered
2156 	 * information about this vnet node by walking MD earlier during attach
2157 	 * (in vgen_read_mdprops()). So, there is a window where the properties
2158 	 * of this node might have changed when we get this initial 'added'
2159 	 * callback. We handle this as if an update occured and invoke the same
2160 	 * function which handles updates to the properties of this vnet-node
2161 	 * if any. A non-zero 'match' value indicates that the MD has been
2162 	 * updated and that a 'network' node is present which may or may not
2163 	 * have been updated. It is up to the clients to examine their own
2164 	 * nodes and determine if they have changed.
2165 	 */
2166 	if (resp->added.nelem != 0) {
2167 
2168 		if (resp->added.nelem != 1) {
2169 			cmn_err(CE_NOTE, "!vnet%d: number of nodes added "
2170 			    "invalid: %d\n", vnetp->instance,
2171 			    resp->added.nelem);
2172 			goto vgen_mdeg_cb_err;
2173 		}
2174 
2175 		mdp = resp->added.mdp;
2176 		node = resp->added.mdep[0];
2177 
2178 	} else if (resp->match_curr.nelem != 0) {
2179 
2180 		if (resp->match_curr.nelem != 1) {
2181 			cmn_err(CE_NOTE, "!vnet%d: number of nodes updated "
2182 			    "invalid: %d\n", vnetp->instance,
2183 			    resp->match_curr.nelem);
2184 			goto vgen_mdeg_cb_err;
2185 		}
2186 
2187 		mdp = resp->match_curr.mdp;
2188 		node = resp->match_curr.mdep[0];
2189 
2190 	} else {
2191 		goto vgen_mdeg_cb_err;
2192 	}
2193 
2194 	/* Validate name and instance */
2195 	if (md_get_prop_str(mdp, node, "name", &node_name) != 0) {
2196 		DERR(vgenp, NULL, "unable to get node name\n");
2197 		goto vgen_mdeg_cb_err;
2198 	}
2199 
2200 	/* is this a virtual-network device? */
2201 	if (strcmp(node_name, vnet_propname) != 0) {
2202 		DERR(vgenp, NULL, "%s: Invalid node name: %s\n", node_name);
2203 		goto vgen_mdeg_cb_err;
2204 	}
2205 
2206 	if (md_get_prop_val(mdp, node, "cfg-handle", &inst)) {
2207 		DERR(vgenp, NULL, "prop(cfg-handle) not found\n");
2208 		goto vgen_mdeg_cb_err;
2209 	}
2210 
2211 	/* is this the right instance of vnet? */
2212 	if (inst != vgenp->regprop) {
2213 		DERR(vgenp, NULL,  "Invalid cfg-handle: %lx\n", inst);
2214 		goto vgen_mdeg_cb_err;
2215 	}
2216 
2217 	vgen_update_md_prop(vgenp, mdp, node);
2218 
2219 	mutex_exit(&vgenp->lock);
2220 	return (MDEG_SUCCESS);
2221 
2222 vgen_mdeg_cb_err:
2223 	mutex_exit(&vgenp->lock);
2224 	return (MDEG_FAILURE);
2225 }
2226 
2227 /*
2228  * Check to see if the relevant properties in the specified node have
2229  * changed, and if so take the appropriate action.
2230  */
2231 static void
2232 vgen_update_md_prop(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex)
2233 {
2234 	uint16_t	pvid;
2235 	uint16_t	*vids;
2236 	uint16_t	nvids;
2237 	vnet_t		*vnetp = vgenp->vnetp;
2238 	uint32_t	mtu;
2239 	enum		{ MD_init = 0x1,
2240 			    MD_vlans = 0x2,
2241 			    MD_mtu = 0x4 } updated;
2242 	int		rv;
2243 
2244 	updated = MD_init;
2245 
2246 	/* Read the vlan ids */
2247 	vgen_vlan_read_ids(vgenp, VGEN_LOCAL, mdp, mdex, &pvid, &vids,
2248 	    &nvids, NULL);
2249 
2250 	/* Determine if there are any vlan id updates */
2251 	if ((pvid != vnetp->pvid) ||		/* pvid changed? */
2252 	    (nvids != vnetp->nvids) ||		/* # of vids changed? */
2253 	    ((nvids != 0) && (vnetp->nvids != 0) &&	/* vids changed? */
2254 	    bcmp(vids, vnetp->vids, sizeof (uint16_t) * nvids))) {
2255 		updated |= MD_vlans;
2256 	}
2257 
2258 	/* Read mtu */
2259 	vgen_mtu_read(vgenp, mdp, mdex, &mtu);
2260 	if (mtu != vnetp->mtu) {
2261 		if (mtu >= ETHERMTU && mtu <= VNET_MAX_MTU) {
2262 			updated |= MD_mtu;
2263 		} else {
2264 			cmn_err(CE_NOTE, "!vnet%d: Unable to process mtu update"
2265 			    " as the specified value:%d is invalid\n",
2266 			    vnetp->instance, mtu);
2267 		}
2268 	}
2269 
2270 	/* Now process the updated props */
2271 
2272 	if (updated & MD_vlans) {
2273 
2274 		/* save the new vlan ids */
2275 		vnetp->pvid = pvid;
2276 		if (vnetp->nvids != 0) {
2277 			kmem_free(vnetp->vids,
2278 			    sizeof (uint16_t) * vnetp->nvids);
2279 			vnetp->nvids = 0;
2280 		}
2281 		if (nvids != 0) {
2282 			vnetp->nvids = nvids;
2283 			vnetp->vids = vids;
2284 		}
2285 
2286 		/* reset vlan-unaware peers (ver < 1.3) and restart handshake */
2287 		vgen_reset_vlan_unaware_ports(vgenp);
2288 
2289 	} else {
2290 
2291 		if (nvids != 0) {
2292 			kmem_free(vids, sizeof (uint16_t) * nvids);
2293 		}
2294 	}
2295 
2296 	if (updated & MD_mtu) {
2297 
2298 		DBG2(vgenp, NULL, "curr_mtu(%d) new_mtu(%d)\n",
2299 		    vnetp->mtu, mtu);
2300 
2301 		rv = vnet_mtu_update(vnetp, mtu);
2302 		if (rv == 0) {
2303 			vgenp->max_frame_size = mtu +
2304 			    sizeof (struct ether_header) + VLAN_TAGSZ;
2305 		}
2306 	}
2307 }
2308 
2309 /* add a new port to the device */
2310 static int
2311 vgen_add_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex)
2312 {
2313 	vgen_port_t	*portp;
2314 	int		rv;
2315 
2316 	portp = kmem_zalloc(sizeof (vgen_port_t), KM_SLEEP);
2317 
2318 	rv = vgen_port_read_props(portp, vgenp, mdp, mdex);
2319 	if (rv != DDI_SUCCESS) {
2320 		KMEM_FREE(portp);
2321 		return (DDI_FAILURE);
2322 	}
2323 
2324 	rv = vgen_port_attach(portp);
2325 	if (rv != DDI_SUCCESS) {
2326 		return (DDI_FAILURE);
2327 	}
2328 
2329 	return (DDI_SUCCESS);
2330 }
2331 
2332 /* read properties of the port from its md node */
2333 static int
2334 vgen_port_read_props(vgen_port_t *portp, vgen_t *vgenp, md_t *mdp,
2335 	mde_cookie_t mdex)
2336 {
2337 	uint64_t		port_num;
2338 	uint64_t		*ldc_ids;
2339 	uint64_t		macaddr;
2340 	uint64_t		val;
2341 	int			num_ldcs;
2342 	int			i;
2343 	int			addrsz;
2344 	int			num_nodes = 0;
2345 	int			listsz = 0;
2346 	mde_cookie_t		*listp = NULL;
2347 	uint8_t			*addrp;
2348 	struct ether_addr	ea;
2349 
2350 	/* read "id" property to get the port number */
2351 	if (md_get_prop_val(mdp, mdex, id_propname, &port_num)) {
2352 		DWARN(vgenp, NULL, "prop(%s) not found\n", id_propname);
2353 		return (DDI_FAILURE);
2354 	}
2355 
2356 	/*
2357 	 * Find the channel endpoint node(s) under this port node.
2358 	 */
2359 	if ((num_nodes = md_node_count(mdp)) <= 0) {
2360 		DWARN(vgenp, NULL, "invalid number of nodes found (%d)",
2361 		    num_nodes);
2362 		return (DDI_FAILURE);
2363 	}
2364 
2365 	/* allocate space for node list */
2366 	listsz = num_nodes * sizeof (mde_cookie_t);
2367 	listp = kmem_zalloc(listsz, KM_NOSLEEP);
2368 	if (listp == NULL)
2369 		return (DDI_FAILURE);
2370 
2371 	num_ldcs = md_scan_dag(mdp, mdex,
2372 	    md_find_name(mdp, channel_propname),
2373 	    md_find_name(mdp, "fwd"), listp);
2374 
2375 	if (num_ldcs <= 0) {
2376 		DWARN(vgenp, NULL, "can't find %s nodes", channel_propname);
2377 		kmem_free(listp, listsz);
2378 		return (DDI_FAILURE);
2379 	}
2380 
2381 	DBG2(vgenp, NULL, "num_ldcs %d", num_ldcs);
2382 
2383 	ldc_ids = kmem_zalloc(num_ldcs * sizeof (uint64_t), KM_NOSLEEP);
2384 	if (ldc_ids == NULL) {
2385 		kmem_free(listp, listsz);
2386 		return (DDI_FAILURE);
2387 	}
2388 
2389 	for (i = 0; i < num_ldcs; i++) {
2390 		/* read channel ids */
2391 		if (md_get_prop_val(mdp, listp[i], id_propname, &ldc_ids[i])) {
2392 			DWARN(vgenp, NULL, "prop(%s) not found\n",
2393 			    id_propname);
2394 			kmem_free(listp, listsz);
2395 			kmem_free(ldc_ids, num_ldcs * sizeof (uint64_t));
2396 			return (DDI_FAILURE);
2397 		}
2398 		DBG2(vgenp, NULL, "ldc_id 0x%llx", ldc_ids[i]);
2399 	}
2400 
2401 	kmem_free(listp, listsz);
2402 
2403 	if (md_get_prop_data(mdp, mdex, rmacaddr_propname, &addrp,
2404 	    &addrsz)) {
2405 		DWARN(vgenp, NULL, "prop(%s) not found\n", rmacaddr_propname);
2406 		kmem_free(ldc_ids, num_ldcs * sizeof (uint64_t));
2407 		return (DDI_FAILURE);
2408 	}
2409 
2410 	if (addrsz < ETHERADDRL) {
2411 		DWARN(vgenp, NULL, "invalid address size (%d)\n", addrsz);
2412 		kmem_free(ldc_ids, num_ldcs * sizeof (uint64_t));
2413 		return (DDI_FAILURE);
2414 	}
2415 
2416 	macaddr = *((uint64_t *)addrp);
2417 
2418 	DBG2(vgenp, NULL, "remote mac address 0x%llx\n", macaddr);
2419 
2420 	for (i = ETHERADDRL - 1; i >= 0; i--) {
2421 		ea.ether_addr_octet[i] = macaddr & 0xFF;
2422 		macaddr >>= 8;
2423 	}
2424 
2425 	if (vgenp->vsw_portp == NULL) {
2426 		if (!(md_get_prop_val(mdp, mdex, swport_propname, &val))) {
2427 			if (val == 0) {
2428 				(void) atomic_swap_32(
2429 				    &vgenp->vsw_port_refcnt, 0);
2430 				/* This port is connected to the vsw */
2431 				vgenp->vsw_portp = portp;
2432 			}
2433 		}
2434 	}
2435 
2436 	/* now update all properties into the port */
2437 	portp->vgenp = vgenp;
2438 	portp->port_num = port_num;
2439 	ether_copy(&ea, &portp->macaddr);
2440 	portp->ldc_ids = kmem_zalloc(sizeof (uint64_t) * num_ldcs, KM_SLEEP);
2441 	bcopy(ldc_ids, portp->ldc_ids, sizeof (uint64_t) * num_ldcs);
2442 	portp->num_ldcs = num_ldcs;
2443 
2444 	/* read vlan id properties of this port node */
2445 	vgen_vlan_read_ids(portp, VGEN_PEER, mdp, mdex, &portp->pvid,
2446 	    &portp->vids, &portp->nvids, NULL);
2447 
2448 	kmem_free(ldc_ids, num_ldcs * sizeof (uint64_t));
2449 
2450 	return (DDI_SUCCESS);
2451 }
2452 
2453 /* remove a port from the device */
2454 static int
2455 vgen_remove_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex)
2456 {
2457 	uint64_t	port_num;
2458 	vgen_port_t	*portp;
2459 	vgen_portlist_t	*plistp;
2460 
2461 	/* read "id" property to get the port number */
2462 	if (md_get_prop_val(mdp, mdex, id_propname, &port_num)) {
2463 		DWARN(vgenp, NULL, "prop(%s) not found\n", id_propname);
2464 		return (DDI_FAILURE);
2465 	}
2466 
2467 	plistp = &(vgenp->vgenports);
2468 
2469 	WRITE_ENTER(&plistp->rwlock);
2470 	portp = vgen_port_lookup(plistp, (int)port_num);
2471 	if (portp == NULL) {
2472 		DWARN(vgenp, NULL, "can't find port(%lx)\n", port_num);
2473 		RW_EXIT(&plistp->rwlock);
2474 		return (DDI_FAILURE);
2475 	}
2476 
2477 	vgen_port_detach_mdeg(portp);
2478 	RW_EXIT(&plistp->rwlock);
2479 
2480 	return (DDI_SUCCESS);
2481 }
2482 
2483 /* attach a port to the device based on mdeg data */
2484 static int
2485 vgen_port_attach(vgen_port_t *portp)
2486 {
2487 	int			i;
2488 	vgen_portlist_t		*plistp;
2489 	vgen_t			*vgenp;
2490 	uint64_t		*ldcids;
2491 	uint32_t		num_ldcs;
2492 	mac_register_t		*macp;
2493 	vio_net_res_type_t	type;
2494 	int			rv;
2495 
2496 	ASSERT(portp != NULL);
2497 
2498 	vgenp = portp->vgenp;
2499 	ldcids = portp->ldc_ids;
2500 	num_ldcs = portp->num_ldcs;
2501 
2502 	DBG1(vgenp, NULL, "port_num(%d)\n", portp->port_num);
2503 
2504 	mutex_init(&portp->lock, NULL, MUTEX_DRIVER, NULL);
2505 	rw_init(&portp->ldclist.rwlock, NULL, RW_DRIVER, NULL);
2506 	portp->ldclist.headp = NULL;
2507 
2508 	for (i = 0; i < num_ldcs; i++) {
2509 		DBG2(vgenp, NULL, "ldcid (%lx)\n", ldcids[i]);
2510 		if (vgen_ldc_attach(portp, ldcids[i]) == DDI_FAILURE) {
2511 			vgen_port_detach(portp);
2512 			return (DDI_FAILURE);
2513 		}
2514 	}
2515 
2516 	/* create vlan id hash table */
2517 	vgen_vlan_create_hash(portp);
2518 
2519 	if (portp == vgenp->vsw_portp) {
2520 		/* This port is connected to the switch port */
2521 		vgenp->vsw_portp = portp;
2522 		(void) atomic_swap_32(&portp->use_vsw_port, B_FALSE);
2523 		type = VIO_NET_RES_LDC_SERVICE;
2524 	} else {
2525 		(void) atomic_swap_32(&portp->use_vsw_port, B_TRUE);
2526 		type = VIO_NET_RES_LDC_GUEST;
2527 	}
2528 
2529 	if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
2530 		vgen_port_detach(portp);
2531 		return (DDI_FAILURE);
2532 	}
2533 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
2534 	macp->m_driver = portp;
2535 	macp->m_dip = vgenp->vnetdip;
2536 	macp->m_src_addr = (uint8_t *)&(vgenp->macaddr);
2537 	macp->m_callbacks = &vgen_m_callbacks;
2538 	macp->m_min_sdu = 0;
2539 	macp->m_max_sdu = ETHERMTU;
2540 
2541 	mutex_enter(&portp->lock);
2542 	rv = vio_net_resource_reg(macp, type, vgenp->macaddr,
2543 	    portp->macaddr, &portp->vhp, &portp->vcb);
2544 	mutex_exit(&portp->lock);
2545 	mac_free(macp);
2546 
2547 	if (rv == 0) {
2548 		/* link it into the list of ports */
2549 		plistp = &(vgenp->vgenports);
2550 		WRITE_ENTER(&plistp->rwlock);
2551 		vgen_port_list_insert(portp);
2552 		RW_EXIT(&plistp->rwlock);
2553 	} else {
2554 		DERR(vgenp, NULL, "vio_net_resource_reg failed for portp=0x%p",
2555 		    portp);
2556 		vgen_port_detach(portp);
2557 	}
2558 
2559 	DBG1(vgenp, NULL, "exit: port_num(%d)\n", portp->port_num);
2560 	return (DDI_SUCCESS);
2561 }
2562 
2563 /* detach a port from the device based on mdeg data */
2564 static void
2565 vgen_port_detach_mdeg(vgen_port_t *portp)
2566 {
2567 	vgen_t *vgenp = portp->vgenp;
2568 
2569 	DBG1(vgenp, NULL, "enter: port_num(%d)\n", portp->port_num);
2570 
2571 	mutex_enter(&portp->lock);
2572 
2573 	/* stop the port if needed */
2574 	if (portp->flags & VGEN_STARTED) {
2575 		vgen_port_uninit(portp);
2576 	}
2577 
2578 	mutex_exit(&portp->lock);
2579 	vgen_port_detach(portp);
2580 
2581 	DBG1(vgenp, NULL, "exit: port_num(%d)\n", portp->port_num);
2582 }
2583 
2584 static int
2585 vgen_update_port(vgen_t *vgenp, md_t *curr_mdp, mde_cookie_t curr_mdex,
2586 	md_t *prev_mdp, mde_cookie_t prev_mdex)
2587 {
2588 	uint64_t	cport_num;
2589 	uint64_t	pport_num;
2590 	vgen_portlist_t	*plistp;
2591 	vgen_port_t	*portp;
2592 	boolean_t	updated_vlans = B_FALSE;
2593 	uint16_t	pvid;
2594 	uint16_t	*vids;
2595 	uint16_t	nvids;
2596 
2597 	/*
2598 	 * For now, we get port updates only if vlan ids changed.
2599 	 * We read the port num and do some sanity check.
2600 	 */
2601 	if (md_get_prop_val(curr_mdp, curr_mdex, id_propname, &cport_num)) {
2602 		DWARN(vgenp, NULL, "prop(%s) not found\n", id_propname);
2603 		return (DDI_FAILURE);
2604 	}
2605 
2606 	if (md_get_prop_val(prev_mdp, prev_mdex, id_propname, &pport_num)) {
2607 		DWARN(vgenp, NULL, "prop(%s) not found\n", id_propname);
2608 		return (DDI_FAILURE);
2609 	}
2610 	if (cport_num != pport_num)
2611 		return (DDI_FAILURE);
2612 
2613 	plistp = &(vgenp->vgenports);
2614 
2615 	READ_ENTER(&plistp->rwlock);
2616 
2617 	portp = vgen_port_lookup(plistp, (int)cport_num);
2618 	if (portp == NULL) {
2619 		DWARN(vgenp, NULL, "can't find port(%lx)\n", cport_num);
2620 		RW_EXIT(&plistp->rwlock);
2621 		return (DDI_FAILURE);
2622 	}
2623 
2624 	/* Read the vlan ids */
2625 	vgen_vlan_read_ids(portp, VGEN_PEER, curr_mdp, curr_mdex, &pvid, &vids,
2626 	    &nvids, NULL);
2627 
2628 	/* Determine if there are any vlan id updates */
2629 	if ((pvid != portp->pvid) ||		/* pvid changed? */
2630 	    (nvids != portp->nvids) ||		/* # of vids changed? */
2631 	    ((nvids != 0) && (portp->nvids != 0) &&	/* vids changed? */
2632 	    bcmp(vids, portp->vids, sizeof (uint16_t) * nvids))) {
2633 		updated_vlans = B_TRUE;
2634 	}
2635 
2636 	if (updated_vlans == B_FALSE) {
2637 		RW_EXIT(&plistp->rwlock);
2638 		return (DDI_FAILURE);
2639 	}
2640 
2641 	/* remove the port from vlans it has been assigned to */
2642 	vgen_vlan_remove_ids(portp);
2643 
2644 	/* save the new vlan ids */
2645 	portp->pvid = pvid;
2646 	if (portp->nvids != 0) {
2647 		kmem_free(portp->vids, sizeof (uint16_t) * portp->nvids);
2648 		portp->nvids = 0;
2649 	}
2650 	if (nvids != 0) {
2651 		portp->vids = kmem_zalloc(sizeof (uint16_t) * nvids, KM_SLEEP);
2652 		bcopy(vids, portp->vids, sizeof (uint16_t) * nvids);
2653 		portp->nvids = nvids;
2654 		kmem_free(vids, sizeof (uint16_t) * nvids);
2655 	}
2656 
2657 	/* add port to the new vlans */
2658 	vgen_vlan_add_ids(portp);
2659 
2660 	/* reset the port if it is vlan unaware (ver < 1.3) */
2661 	vgen_vlan_unaware_port_reset(portp);
2662 
2663 	RW_EXIT(&plistp->rwlock);
2664 
2665 	return (DDI_SUCCESS);
2666 }
2667 
2668 static uint64_t
2669 vgen_port_stat(vgen_port_t *portp, uint_t stat)
2670 {
2671 	vgen_ldclist_t	*ldclp;
2672 	vgen_ldc_t *ldcp;
2673 	uint64_t	val;
2674 
2675 	val = 0;
2676 	ldclp = &portp->ldclist;
2677 
2678 	READ_ENTER(&ldclp->rwlock);
2679 	for (ldcp = ldclp->headp; ldcp != NULL; ldcp = ldcp->nextp) {
2680 		val += vgen_ldc_stat(ldcp, stat);
2681 	}
2682 	RW_EXIT(&ldclp->rwlock);
2683 
2684 	return (val);
2685 }
2686 
2687 /* allocate receive resources */
2688 static int
2689 vgen_init_multipools(vgen_ldc_t *ldcp)
2690 {
2691 	size_t		data_sz;
2692 	vgen_t		*vgenp = LDC_TO_VGEN(ldcp);
2693 	int		status;
2694 	uint32_t	sz1 = 0;
2695 	uint32_t	sz2 = 0;
2696 	uint32_t	sz3 = 0;
2697 	uint32_t	sz4 = 0;
2698 
2699 	/*
2700 	 * We round up the mtu specified to be a multiple of 2K.
2701 	 * We then create rx pools based on the rounded up size.
2702 	 */
2703 	data_sz = vgenp->max_frame_size + VNET_IPALIGN + VNET_LDCALIGN;
2704 	data_sz = VNET_ROUNDUP_2K(data_sz);
2705 
2706 	/*
2707 	 * If pool sizes are specified, use them. Note that the presence of
2708 	 * the first tunable will be used as a hint.
2709 	 */
2710 	if (vgen_rbufsz1 != 0) {
2711 
2712 		sz1 = vgen_rbufsz1;
2713 		sz2 = vgen_rbufsz2;
2714 		sz3 = vgen_rbufsz3;
2715 		sz4 = vgen_rbufsz4;
2716 
2717 		if (sz4 == 0) { /* need 3 pools */
2718 
2719 			ldcp->max_rxpool_size = sz3;
2720 			status = vio_init_multipools(&ldcp->vmp,
2721 			    VGEN_NUM_VMPOOLS, sz1, sz2, sz3, vgen_nrbufs1,
2722 			    vgen_nrbufs2, vgen_nrbufs3);
2723 
2724 		} else {
2725 
2726 			ldcp->max_rxpool_size = sz4;
2727 			status = vio_init_multipools(&ldcp->vmp,
2728 			    VGEN_NUM_VMPOOLS + 1, sz1, sz2, sz3, sz4,
2729 			    vgen_nrbufs1, vgen_nrbufs2, vgen_nrbufs3,
2730 			    vgen_nrbufs4);
2731 		}
2732 		return (status);
2733 	}
2734 
2735 	/*
2736 	 * Pool sizes are not specified. We select the pool sizes based on the
2737 	 * mtu if vnet_jumbo_rxpools is enabled.
2738 	 */
2739 	if (vnet_jumbo_rxpools == B_FALSE || data_sz == VNET_2K) {
2740 		/*
2741 		 * Receive buffer pool allocation based on mtu is disabled.
2742 		 * Use the default mechanism of standard size pool allocation.
2743 		 */
2744 		sz1 = VGEN_DBLK_SZ_128;
2745 		sz2 = VGEN_DBLK_SZ_256;
2746 		sz3 = VGEN_DBLK_SZ_2048;
2747 		ldcp->max_rxpool_size = sz3;
2748 
2749 		status = vio_init_multipools(&ldcp->vmp, VGEN_NUM_VMPOOLS,
2750 		    sz1, sz2, sz3,
2751 		    vgen_nrbufs1, vgen_nrbufs2, vgen_nrbufs3);
2752 
2753 		return (status);
2754 	}
2755 
2756 	switch (data_sz) {
2757 
2758 	case VNET_4K:
2759 
2760 		sz1 = VGEN_DBLK_SZ_128;
2761 		sz2 = VGEN_DBLK_SZ_256;
2762 		sz3 = VGEN_DBLK_SZ_2048;
2763 		sz4 = sz3 << 1;			/* 4K */
2764 		ldcp->max_rxpool_size = sz4;
2765 
2766 		status = vio_init_multipools(&ldcp->vmp, VGEN_NUM_VMPOOLS + 1,
2767 		    sz1, sz2, sz3, sz4,
2768 		    vgen_nrbufs1, vgen_nrbufs2, vgen_nrbufs3, vgen_nrbufs4);
2769 		break;
2770 
2771 	default:	/* data_sz:  4K+ to 16K */
2772 
2773 		sz1 = VGEN_DBLK_SZ_256;
2774 		sz2 = VGEN_DBLK_SZ_2048;
2775 		sz3 = data_sz >> 1;	/* Jumbo-size/2 */
2776 		sz4 = data_sz;		/* Jumbo-size  */
2777 		ldcp->max_rxpool_size = sz4;
2778 
2779 		status = vio_init_multipools(&ldcp->vmp, VGEN_NUM_VMPOOLS + 1,
2780 		    sz1, sz2, sz3, sz4,
2781 		    vgen_nrbufs1, vgen_nrbufs2, vgen_nrbufs3, vgen_nrbufs4);
2782 		break;
2783 
2784 	}
2785 
2786 	return (status);
2787 }
2788 
2789 /* attach the channel corresponding to the given ldc_id to the port */
2790 static int
2791 vgen_ldc_attach(vgen_port_t *portp, uint64_t ldc_id)
2792 {
2793 	vgen_t 		*vgenp;
2794 	vgen_ldclist_t	*ldclp;
2795 	vgen_ldc_t 	*ldcp, **prev_ldcp;
2796 	ldc_attr_t 	attr;
2797 	int 		status;
2798 	ldc_status_t	istatus;
2799 	char		kname[MAXNAMELEN];
2800 	int		instance;
2801 	enum	{AST_init = 0x0, AST_ldc_alloc = 0x1,
2802 		AST_mutex_init = 0x2, AST_ldc_init = 0x4,
2803 		AST_ldc_reg_cb = 0x8, AST_alloc_tx_ring = 0x10,
2804 		AST_create_rxmblks = 0x20,
2805 		AST_create_rcv_thread = 0x40} attach_state;
2806 
2807 	attach_state = AST_init;
2808 	vgenp = portp->vgenp;
2809 	ldclp = &portp->ldclist;
2810 
2811 	ldcp = kmem_zalloc(sizeof (vgen_ldc_t), KM_NOSLEEP);
2812 	if (ldcp == NULL) {
2813 		goto ldc_attach_failed;
2814 	}
2815 	ldcp->ldc_id = ldc_id;
2816 	ldcp->portp = portp;
2817 
2818 	attach_state |= AST_ldc_alloc;
2819 
2820 	mutex_init(&ldcp->txlock, NULL, MUTEX_DRIVER, NULL);
2821 	mutex_init(&ldcp->cblock, NULL, MUTEX_DRIVER, NULL);
2822 	mutex_init(&ldcp->tclock, NULL, MUTEX_DRIVER, NULL);
2823 	mutex_init(&ldcp->wrlock, NULL, MUTEX_DRIVER, NULL);
2824 	mutex_init(&ldcp->rxlock, NULL, MUTEX_DRIVER, NULL);
2825 
2826 	attach_state |= AST_mutex_init;
2827 
2828 	attr.devclass = LDC_DEV_NT;
2829 	attr.instance = vgenp->instance;
2830 	attr.mode = LDC_MODE_UNRELIABLE;
2831 	attr.mtu = vnet_ldc_mtu;
2832 	status = ldc_init(ldc_id, &attr, &ldcp->ldc_handle);
2833 	if (status != 0) {
2834 		DWARN(vgenp, ldcp, "ldc_init failed,rv (%d)\n", status);
2835 		goto ldc_attach_failed;
2836 	}
2837 	attach_state |= AST_ldc_init;
2838 
2839 	if (vgen_rcv_thread_enabled) {
2840 		ldcp->rcv_thr_flags = 0;
2841 
2842 		mutex_init(&ldcp->rcv_thr_lock, NULL, MUTEX_DRIVER, NULL);
2843 		cv_init(&ldcp->rcv_thr_cv, NULL, CV_DRIVER, NULL);
2844 		ldcp->rcv_thread = thread_create(NULL, 2 * DEFAULTSTKSZ,
2845 		    vgen_ldc_rcv_worker, ldcp, 0, &p0, TS_RUN, maxclsyspri);
2846 
2847 		attach_state |= AST_create_rcv_thread;
2848 		if (ldcp->rcv_thread == NULL) {
2849 			DWARN(vgenp, ldcp, "Failed to create worker thread");
2850 			goto ldc_attach_failed;
2851 		}
2852 	}
2853 
2854 	status = ldc_reg_callback(ldcp->ldc_handle, vgen_ldc_cb, (caddr_t)ldcp);
2855 	if (status != 0) {
2856 		DWARN(vgenp, ldcp, "ldc_reg_callback failed, rv (%d)\n",
2857 		    status);
2858 		goto ldc_attach_failed;
2859 	}
2860 	/*
2861 	 * allocate a message for ldc_read()s, big enough to hold ctrl and
2862 	 * data msgs, including raw data msgs used to recv priority frames.
2863 	 */
2864 	ldcp->msglen = VIO_PKT_DATA_HDRSIZE + vgenp->max_frame_size;
2865 	ldcp->ldcmsg = kmem_alloc(ldcp->msglen, KM_SLEEP);
2866 	attach_state |= AST_ldc_reg_cb;
2867 
2868 	(void) ldc_status(ldcp->ldc_handle, &istatus);
2869 	ASSERT(istatus == LDC_INIT);
2870 	ldcp->ldc_status = istatus;
2871 
2872 	/* allocate transmit resources */
2873 	status = vgen_alloc_tx_ring(ldcp);
2874 	if (status != 0) {
2875 		goto ldc_attach_failed;
2876 	}
2877 	attach_state |= AST_alloc_tx_ring;
2878 
2879 	/* allocate receive resources */
2880 	status = vgen_init_multipools(ldcp);
2881 	if (status != 0) {
2882 		/*
2883 		 * We do not return failure if receive mblk pools can't be
2884 		 * allocated; instead allocb(9F) will be used to dynamically
2885 		 * allocate buffers during receive.
2886 		 */
2887 		DWARN(vgenp, ldcp,
2888 		    "vnet%d: status(%d), failed to allocate rx mblk pools for "
2889 		    "channel(0x%lx)\n",
2890 		    vgenp->instance, status, ldcp->ldc_id);
2891 	} else {
2892 		attach_state |= AST_create_rxmblks;
2893 	}
2894 
2895 	/* Setup kstats for the channel */
2896 	instance = vgenp->instance;
2897 	(void) sprintf(kname, "vnetldc0x%lx", ldcp->ldc_id);
2898 	ldcp->ksp = vgen_setup_kstats("vnet", instance, kname, &ldcp->stats);
2899 	if (ldcp->ksp == NULL) {
2900 		goto ldc_attach_failed;
2901 	}
2902 
2903 	/* initialize vgen_versions supported */
2904 	bcopy(vgen_versions, ldcp->vgen_versions, sizeof (ldcp->vgen_versions));
2905 	vgen_reset_vnet_proto_ops(ldcp);
2906 
2907 	/* link it into the list of channels for this port */
2908 	WRITE_ENTER(&ldclp->rwlock);
2909 	prev_ldcp = (vgen_ldc_t **)(&ldclp->headp);
2910 	ldcp->nextp = *prev_ldcp;
2911 	*prev_ldcp = ldcp;
2912 	RW_EXIT(&ldclp->rwlock);
2913 
2914 	ldcp->flags |= CHANNEL_ATTACHED;
2915 	return (DDI_SUCCESS);
2916 
2917 ldc_attach_failed:
2918 	if (attach_state & AST_ldc_reg_cb) {
2919 		(void) ldc_unreg_callback(ldcp->ldc_handle);
2920 		kmem_free(ldcp->ldcmsg, ldcp->msglen);
2921 	}
2922 	if (attach_state & AST_create_rcv_thread) {
2923 		if (ldcp->rcv_thread != NULL) {
2924 			vgen_stop_rcv_thread(ldcp);
2925 		}
2926 		mutex_destroy(&ldcp->rcv_thr_lock);
2927 		cv_destroy(&ldcp->rcv_thr_cv);
2928 	}
2929 	if (attach_state & AST_create_rxmblks) {
2930 		vio_mblk_pool_t *fvmp = NULL;
2931 		vio_destroy_multipools(&ldcp->vmp, &fvmp);
2932 		ASSERT(fvmp == NULL);
2933 	}
2934 	if (attach_state & AST_alloc_tx_ring) {
2935 		vgen_free_tx_ring(ldcp);
2936 	}
2937 	if (attach_state & AST_ldc_init) {
2938 		(void) ldc_fini(ldcp->ldc_handle);
2939 	}
2940 	if (attach_state & AST_mutex_init) {
2941 		mutex_destroy(&ldcp->tclock);
2942 		mutex_destroy(&ldcp->txlock);
2943 		mutex_destroy(&ldcp->cblock);
2944 		mutex_destroy(&ldcp->wrlock);
2945 		mutex_destroy(&ldcp->rxlock);
2946 	}
2947 	if (attach_state & AST_ldc_alloc) {
2948 		KMEM_FREE(ldcp);
2949 	}
2950 	return (DDI_FAILURE);
2951 }
2952 
2953 /* detach a channel from the port */
2954 static void
2955 vgen_ldc_detach(vgen_ldc_t *ldcp)
2956 {
2957 	vgen_port_t	*portp;
2958 	vgen_t 		*vgenp;
2959 	vgen_ldc_t 	*pldcp;
2960 	vgen_ldc_t	**prev_ldcp;
2961 	vgen_ldclist_t	*ldclp;
2962 
2963 	portp = ldcp->portp;
2964 	vgenp = portp->vgenp;
2965 	ldclp = &portp->ldclist;
2966 
2967 	prev_ldcp =  (vgen_ldc_t **)&ldclp->headp;
2968 	for (; (pldcp = *prev_ldcp) != NULL; prev_ldcp = &pldcp->nextp) {
2969 		if (pldcp == ldcp) {
2970 			break;
2971 		}
2972 	}
2973 
2974 	if (pldcp == NULL) {
2975 		/* invalid ldcp? */
2976 		return;
2977 	}
2978 
2979 	if (ldcp->ldc_status != LDC_INIT) {
2980 		DWARN(vgenp, ldcp, "ldc_status is not INIT\n");
2981 	}
2982 
2983 	if (ldcp->flags & CHANNEL_ATTACHED) {
2984 		ldcp->flags &= ~(CHANNEL_ATTACHED);
2985 
2986 		(void) ldc_unreg_callback(ldcp->ldc_handle);
2987 		if (ldcp->rcv_thread != NULL) {
2988 			/* First stop the receive thread */
2989 			vgen_stop_rcv_thread(ldcp);
2990 			mutex_destroy(&ldcp->rcv_thr_lock);
2991 			cv_destroy(&ldcp->rcv_thr_cv);
2992 		}
2993 		kmem_free(ldcp->ldcmsg, ldcp->msglen);
2994 
2995 		vgen_destroy_kstats(ldcp->ksp);
2996 		ldcp->ksp = NULL;
2997 
2998 		/*
2999 		 * if we cannot reclaim all mblks, put this
3000 		 * on the list of pools(vgenp->rmp) to be reclaimed when the
3001 		 * device gets detached (see vgen_uninit()).
3002 		 */
3003 		vio_destroy_multipools(&ldcp->vmp, &vgenp->rmp);
3004 
3005 		/* free transmit resources */
3006 		vgen_free_tx_ring(ldcp);
3007 
3008 		(void) ldc_fini(ldcp->ldc_handle);
3009 		mutex_destroy(&ldcp->tclock);
3010 		mutex_destroy(&ldcp->txlock);
3011 		mutex_destroy(&ldcp->cblock);
3012 		mutex_destroy(&ldcp->wrlock);
3013 		mutex_destroy(&ldcp->rxlock);
3014 
3015 		/* unlink it from the list */
3016 		*prev_ldcp = ldcp->nextp;
3017 		KMEM_FREE(ldcp);
3018 	}
3019 }
3020 
3021 /*
3022  * This function allocates transmit resources for the channel.
3023  * The resources consist of a transmit descriptor ring and an associated
3024  * transmit buffer ring.
3025  */
3026 static int
3027 vgen_alloc_tx_ring(vgen_ldc_t *ldcp)
3028 {
3029 	void *tbufp;
3030 	ldc_mem_info_t minfo;
3031 	uint32_t txdsize;
3032 	uint32_t tbufsize;
3033 	int status;
3034 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
3035 
3036 	ldcp->num_txds = vnet_ntxds;
3037 	txdsize = sizeof (vnet_public_desc_t);
3038 	tbufsize = sizeof (vgen_private_desc_t);
3039 
3040 	/* allocate transmit buffer ring */
3041 	tbufp = kmem_zalloc(ldcp->num_txds * tbufsize, KM_NOSLEEP);
3042 	if (tbufp == NULL) {
3043 		return (DDI_FAILURE);
3044 	}
3045 
3046 	/* create transmit descriptor ring */
3047 	status = ldc_mem_dring_create(ldcp->num_txds, txdsize,
3048 	    &ldcp->tx_dhandle);
3049 	if (status) {
3050 		DWARN(vgenp, ldcp, "ldc_mem_dring_create() failed\n");
3051 		kmem_free(tbufp, ldcp->num_txds * tbufsize);
3052 		return (DDI_FAILURE);
3053 	}
3054 
3055 	/* get the addr of descripror ring */
3056 	status = ldc_mem_dring_info(ldcp->tx_dhandle, &minfo);
3057 	if (status) {
3058 		DWARN(vgenp, ldcp, "ldc_mem_dring_info() failed\n");
3059 		kmem_free(tbufp, ldcp->num_txds * tbufsize);
3060 		(void) ldc_mem_dring_destroy(ldcp->tx_dhandle);
3061 		ldcp->tbufp = NULL;
3062 		return (DDI_FAILURE);
3063 	}
3064 	ldcp->txdp = (vnet_public_desc_t *)(minfo.vaddr);
3065 	ldcp->tbufp = tbufp;
3066 
3067 	ldcp->txdendp = &((ldcp->txdp)[ldcp->num_txds]);
3068 	ldcp->tbufendp = &((ldcp->tbufp)[ldcp->num_txds]);
3069 
3070 	return (DDI_SUCCESS);
3071 }
3072 
3073 /* Free transmit resources for the channel */
3074 static void
3075 vgen_free_tx_ring(vgen_ldc_t *ldcp)
3076 {
3077 	int tbufsize = sizeof (vgen_private_desc_t);
3078 
3079 	/* free transmit descriptor ring */
3080 	(void) ldc_mem_dring_destroy(ldcp->tx_dhandle);
3081 
3082 	/* free transmit buffer ring */
3083 	kmem_free(ldcp->tbufp, ldcp->num_txds * tbufsize);
3084 	ldcp->txdp = ldcp->txdendp = NULL;
3085 	ldcp->tbufp = ldcp->tbufendp = NULL;
3086 }
3087 
3088 /* enable transmit/receive on the channels for the port */
3089 static void
3090 vgen_init_ldcs(vgen_port_t *portp)
3091 {
3092 	vgen_ldclist_t	*ldclp = &portp->ldclist;
3093 	vgen_ldc_t	*ldcp;
3094 
3095 	READ_ENTER(&ldclp->rwlock);
3096 	ldcp =  ldclp->headp;
3097 	for (; ldcp  != NULL; ldcp = ldcp->nextp) {
3098 		(void) vgen_ldc_init(ldcp);
3099 	}
3100 	RW_EXIT(&ldclp->rwlock);
3101 }
3102 
3103 /* stop transmit/receive on the channels for the port */
3104 static void
3105 vgen_uninit_ldcs(vgen_port_t *portp)
3106 {
3107 	vgen_ldclist_t	*ldclp = &portp->ldclist;
3108 	vgen_ldc_t	*ldcp;
3109 
3110 	READ_ENTER(&ldclp->rwlock);
3111 	ldcp =  ldclp->headp;
3112 	for (; ldcp  != NULL; ldcp = ldcp->nextp) {
3113 		vgen_ldc_uninit(ldcp);
3114 	}
3115 	RW_EXIT(&ldclp->rwlock);
3116 }
3117 
3118 /* enable transmit/receive on the channel */
3119 static int
3120 vgen_ldc_init(vgen_ldc_t *ldcp)
3121 {
3122 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
3123 	ldc_status_t	istatus;
3124 	int		rv;
3125 	uint32_t	retries = 0;
3126 	enum	{ ST_init = 0x0, ST_ldc_open = 0x1,
3127 		ST_init_tbufs = 0x2, ST_cb_enable = 0x4} init_state;
3128 	init_state = ST_init;
3129 
3130 	DBG1(vgenp, ldcp, "enter\n");
3131 	LDC_LOCK(ldcp);
3132 
3133 	rv = ldc_open(ldcp->ldc_handle);
3134 	if (rv != 0) {
3135 		DWARN(vgenp, ldcp, "ldc_open failed: rv(%d)\n", rv);
3136 		goto ldcinit_failed;
3137 	}
3138 	init_state |= ST_ldc_open;
3139 
3140 	(void) ldc_status(ldcp->ldc_handle, &istatus);
3141 	if (istatus != LDC_OPEN && istatus != LDC_READY) {
3142 		DWARN(vgenp, ldcp, "status(%d) is not OPEN/READY\n", istatus);
3143 		goto ldcinit_failed;
3144 	}
3145 	ldcp->ldc_status = istatus;
3146 
3147 	rv = vgen_init_tbufs(ldcp);
3148 	if (rv != 0) {
3149 		DWARN(vgenp, ldcp, "vgen_init_tbufs() failed\n");
3150 		goto ldcinit_failed;
3151 	}
3152 	init_state |= ST_init_tbufs;
3153 
3154 	rv = ldc_set_cb_mode(ldcp->ldc_handle, LDC_CB_ENABLE);
3155 	if (rv != 0) {
3156 		DWARN(vgenp, ldcp, "ldc_set_cb_mode failed: rv(%d)\n", rv);
3157 		goto ldcinit_failed;
3158 	}
3159 
3160 	init_state |= ST_cb_enable;
3161 
3162 	do {
3163 		rv = ldc_up(ldcp->ldc_handle);
3164 		if ((rv != 0) && (rv == EWOULDBLOCK)) {
3165 			DBG2(vgenp, ldcp, "ldc_up err rv(%d)\n", rv);
3166 			drv_usecwait(VGEN_LDC_UP_DELAY);
3167 		}
3168 		if (retries++ >= vgen_ldcup_retries)
3169 			break;
3170 	} while (rv == EWOULDBLOCK);
3171 
3172 	(void) ldc_status(ldcp->ldc_handle, &istatus);
3173 	if (istatus == LDC_UP) {
3174 		DWARN(vgenp, ldcp, "status(%d) is UP\n", istatus);
3175 	}
3176 
3177 	ldcp->ldc_status = istatus;
3178 
3179 	/* initialize transmit watchdog timeout */
3180 	ldcp->wd_tid = timeout(vgen_ldc_watchdog, (caddr_t)ldcp,
3181 	    drv_usectohz(vnet_ldcwd_interval * 1000));
3182 
3183 	ldcp->hphase = -1;
3184 	ldcp->flags |= CHANNEL_STARTED;
3185 
3186 	/* if channel is already UP - start handshake */
3187 	if (istatus == LDC_UP) {
3188 		vgen_t *vgenp = LDC_TO_VGEN(ldcp);
3189 		if (ldcp->portp != vgenp->vsw_portp) {
3190 			/*
3191 			 * As the channel is up, use this port from now on.
3192 			 */
3193 			(void) atomic_swap_32(
3194 			    &ldcp->portp->use_vsw_port, B_FALSE);
3195 		}
3196 
3197 		/* Initialize local session id */
3198 		ldcp->local_sid = ddi_get_lbolt();
3199 
3200 		/* clear peer session id */
3201 		ldcp->peer_sid = 0;
3202 		ldcp->hretries = 0;
3203 
3204 		/* Initiate Handshake process with peer ldc endpoint */
3205 		vgen_reset_hphase(ldcp);
3206 
3207 		mutex_exit(&ldcp->tclock);
3208 		mutex_exit(&ldcp->txlock);
3209 		mutex_exit(&ldcp->wrlock);
3210 		mutex_exit(&ldcp->rxlock);
3211 		vgen_handshake(vh_nextphase(ldcp));
3212 		mutex_exit(&ldcp->cblock);
3213 	} else {
3214 		LDC_UNLOCK(ldcp);
3215 	}
3216 
3217 	return (DDI_SUCCESS);
3218 
3219 ldcinit_failed:
3220 	if (init_state & ST_cb_enable) {
3221 		(void) ldc_set_cb_mode(ldcp->ldc_handle, LDC_CB_DISABLE);
3222 	}
3223 	if (init_state & ST_init_tbufs) {
3224 		vgen_uninit_tbufs(ldcp);
3225 	}
3226 	if (init_state & ST_ldc_open) {
3227 		(void) ldc_close(ldcp->ldc_handle);
3228 	}
3229 	LDC_UNLOCK(ldcp);
3230 	DBG1(vgenp, ldcp, "exit\n");
3231 	return (DDI_FAILURE);
3232 }
3233 
3234 /* stop transmit/receive on the channel */
3235 static void
3236 vgen_ldc_uninit(vgen_ldc_t *ldcp)
3237 {
3238 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
3239 	int	rv;
3240 	uint_t	retries = 0;
3241 
3242 	DBG1(vgenp, ldcp, "enter\n");
3243 	LDC_LOCK(ldcp);
3244 
3245 	if ((ldcp->flags & CHANNEL_STARTED) == 0) {
3246 		LDC_UNLOCK(ldcp);
3247 		DWARN(vgenp, ldcp, "CHANNEL_STARTED flag is not set\n");
3248 		return;
3249 	}
3250 
3251 	/* disable further callbacks */
3252 	rv = ldc_set_cb_mode(ldcp->ldc_handle, LDC_CB_DISABLE);
3253 	if (rv != 0) {
3254 		DWARN(vgenp, ldcp, "ldc_set_cb_mode failed\n");
3255 	}
3256 
3257 	if (vgenp->vsw_portp == ldcp->portp) {
3258 		vio_net_report_err_t rep_err =
3259 		    ldcp->portp->vcb.vio_net_report_err;
3260 		rep_err(ldcp->portp->vhp, VIO_NET_RES_DOWN);
3261 	}
3262 
3263 	/*
3264 	 * clear handshake done bit and wait for pending tx and cb to finish.
3265 	 * release locks before untimeout(9F) is invoked to cancel timeouts.
3266 	 */
3267 	ldcp->hphase &= ~(VH_DONE);
3268 	LDC_UNLOCK(ldcp);
3269 
3270 	/* cancel handshake watchdog timeout */
3271 	if (ldcp->htid) {
3272 		(void) untimeout(ldcp->htid);
3273 		ldcp->htid = 0;
3274 	}
3275 
3276 	if (ldcp->cancel_htid) {
3277 		(void) untimeout(ldcp->cancel_htid);
3278 		ldcp->cancel_htid = 0;
3279 	}
3280 
3281 	/* cancel transmit watchdog timeout */
3282 	if (ldcp->wd_tid) {
3283 		(void) untimeout(ldcp->wd_tid);
3284 		ldcp->wd_tid = 0;
3285 	}
3286 
3287 	drv_usecwait(1000);
3288 
3289 	if (ldcp->rcv_thread != NULL) {
3290 		/*
3291 		 * Note that callbacks have been disabled already(above). The
3292 		 * drain function takes care of the condition when an already
3293 		 * executing callback signals the worker to start processing or
3294 		 * the worker has already been signalled and is in the middle of
3295 		 * processing.
3296 		 */
3297 		vgen_drain_rcv_thread(ldcp);
3298 	}
3299 
3300 	/* acquire locks again; any pending transmits and callbacks are done */
3301 	LDC_LOCK(ldcp);
3302 
3303 	vgen_reset_hphase(ldcp);
3304 
3305 	vgen_uninit_tbufs(ldcp);
3306 
3307 	/* close the channel - retry on EAGAIN */
3308 	while ((rv = ldc_close(ldcp->ldc_handle)) == EAGAIN) {
3309 		if (++retries > vgen_ldccl_retries) {
3310 			break;
3311 		}
3312 		drv_usecwait(VGEN_LDC_CLOSE_DELAY);
3313 	}
3314 	if (rv != 0) {
3315 		cmn_err(CE_NOTE,
3316 		    "!vnet%d: Error(%d) closing the channel(0x%lx)\n",
3317 		    vgenp->instance, rv, ldcp->ldc_id);
3318 	}
3319 
3320 	ldcp->ldc_status = LDC_INIT;
3321 	ldcp->flags &= ~(CHANNEL_STARTED);
3322 
3323 	LDC_UNLOCK(ldcp);
3324 
3325 	DBG1(vgenp, ldcp, "exit\n");
3326 }
3327 
3328 /* Initialize the transmit buffer ring for the channel */
3329 static int
3330 vgen_init_tbufs(vgen_ldc_t *ldcp)
3331 {
3332 	vgen_private_desc_t	*tbufp;
3333 	vnet_public_desc_t	*txdp;
3334 	vio_dring_entry_hdr_t		*hdrp;
3335 	int 			i;
3336 	int 			rv;
3337 	caddr_t			datap = NULL;
3338 	int			ci;
3339 	uint32_t		ncookies;
3340 	size_t			data_sz;
3341 	vgen_t			*vgenp;
3342 
3343 	vgenp = LDC_TO_VGEN(ldcp);
3344 
3345 	bzero(ldcp->tbufp, sizeof (*tbufp) * (ldcp->num_txds));
3346 	bzero(ldcp->txdp, sizeof (*txdp) * (ldcp->num_txds));
3347 
3348 	/*
3349 	 * In order to ensure that the number of ldc cookies per descriptor is
3350 	 * limited to be within the default MAX_COOKIES (2), we take the steps
3351 	 * outlined below:
3352 	 *
3353 	 * Align the entire data buffer area to 8K and carve out per descriptor
3354 	 * data buffers starting from this 8K aligned base address.
3355 	 *
3356 	 * We round up the mtu specified to be a multiple of 2K or 4K.
3357 	 * For sizes up to 12K we round up the size to the next 2K.
3358 	 * For sizes > 12K we round up to the next 4K (otherwise sizes such as
3359 	 * 14K could end up needing 3 cookies, with the buffer spread across
3360 	 * 3 8K pages:  8K+6K, 2K+8K+2K, 6K+8K, ...).
3361 	 */
3362 	data_sz = vgenp->max_frame_size + VNET_IPALIGN + VNET_LDCALIGN;
3363 	if (data_sz <= VNET_12K) {
3364 		data_sz = VNET_ROUNDUP_2K(data_sz);
3365 	} else {
3366 		data_sz = VNET_ROUNDUP_4K(data_sz);
3367 	}
3368 
3369 	/* allocate extra 8K bytes for alignment */
3370 	ldcp->tx_data_sz = (data_sz * ldcp->num_txds) + VNET_8K;
3371 	datap = kmem_zalloc(ldcp->tx_data_sz, KM_SLEEP);
3372 	ldcp->tx_datap = datap;
3373 
3374 
3375 	/* align the starting address of the data area to 8K */
3376 	datap = (caddr_t)VNET_ROUNDUP_8K((uintptr_t)datap);
3377 
3378 	/*
3379 	 * for each private descriptor, allocate a ldc mem_handle which is
3380 	 * required to map the data during transmit, set the flags
3381 	 * to free (available for use by transmit routine).
3382 	 */
3383 
3384 	for (i = 0; i < ldcp->num_txds; i++) {
3385 
3386 		tbufp = &(ldcp->tbufp[i]);
3387 		rv = ldc_mem_alloc_handle(ldcp->ldc_handle,
3388 		    &(tbufp->memhandle));
3389 		if (rv) {
3390 			tbufp->memhandle = 0;
3391 			goto init_tbufs_failed;
3392 		}
3393 
3394 		/*
3395 		 * bind ldc memhandle to the corresponding transmit buffer.
3396 		 */
3397 		ci = ncookies = 0;
3398 		rv = ldc_mem_bind_handle(tbufp->memhandle,
3399 		    (caddr_t)datap, data_sz, LDC_SHADOW_MAP,
3400 		    LDC_MEM_R, &(tbufp->memcookie[ci]), &ncookies);
3401 		if (rv != 0) {
3402 			goto init_tbufs_failed;
3403 		}
3404 
3405 		/*
3406 		 * successful in binding the handle to tx data buffer.
3407 		 * set datap in the private descr to this buffer.
3408 		 */
3409 		tbufp->datap = datap;
3410 
3411 		if ((ncookies == 0) ||
3412 		    (ncookies > MAX_COOKIES)) {
3413 			goto init_tbufs_failed;
3414 		}
3415 
3416 		for (ci = 1; ci < ncookies; ci++) {
3417 			rv = ldc_mem_nextcookie(tbufp->memhandle,
3418 			    &(tbufp->memcookie[ci]));
3419 			if (rv != 0) {
3420 				goto init_tbufs_failed;
3421 			}
3422 		}
3423 
3424 		tbufp->ncookies = ncookies;
3425 		datap += data_sz;
3426 
3427 		tbufp->flags = VGEN_PRIV_DESC_FREE;
3428 		txdp = &(ldcp->txdp[i]);
3429 		hdrp = &txdp->hdr;
3430 		hdrp->dstate = VIO_DESC_FREE;
3431 		hdrp->ack = B_FALSE;
3432 		tbufp->descp = txdp;
3433 
3434 	}
3435 
3436 	/* reset tbuf walking pointers */
3437 	ldcp->next_tbufp = ldcp->tbufp;
3438 	ldcp->cur_tbufp = ldcp->tbufp;
3439 
3440 	/* initialize tx seqnum and index */
3441 	ldcp->next_txseq = VNET_ISS;
3442 	ldcp->next_txi = 0;
3443 
3444 	ldcp->resched_peer = B_TRUE;
3445 	ldcp->resched_peer_txi = 0;
3446 
3447 	return (DDI_SUCCESS);
3448 
3449 init_tbufs_failed:;
3450 	vgen_uninit_tbufs(ldcp);
3451 	return (DDI_FAILURE);
3452 }
3453 
3454 /* Uninitialize transmit buffer ring for the channel */
3455 static void
3456 vgen_uninit_tbufs(vgen_ldc_t *ldcp)
3457 {
3458 	vgen_private_desc_t	*tbufp = ldcp->tbufp;
3459 	int 			i;
3460 
3461 	/* for each tbuf (priv_desc), free ldc mem_handle */
3462 	for (i = 0; i < ldcp->num_txds; i++) {
3463 
3464 		tbufp = &(ldcp->tbufp[i]);
3465 
3466 		if (tbufp->datap) { /* if bound to a ldc memhandle */
3467 			(void) ldc_mem_unbind_handle(tbufp->memhandle);
3468 			tbufp->datap = NULL;
3469 		}
3470 		if (tbufp->memhandle) {
3471 			(void) ldc_mem_free_handle(tbufp->memhandle);
3472 			tbufp->memhandle = 0;
3473 		}
3474 	}
3475 
3476 	if (ldcp->tx_datap) {
3477 		/* prealloc'd tx data buffer */
3478 		kmem_free(ldcp->tx_datap, ldcp->tx_data_sz);
3479 		ldcp->tx_datap = NULL;
3480 		ldcp->tx_data_sz = 0;
3481 	}
3482 
3483 	bzero(ldcp->tbufp, sizeof (vgen_private_desc_t) * (ldcp->num_txds));
3484 	bzero(ldcp->txdp, sizeof (vnet_public_desc_t) * (ldcp->num_txds));
3485 }
3486 
3487 /* clobber tx descriptor ring */
3488 static void
3489 vgen_clobber_tbufs(vgen_ldc_t *ldcp)
3490 {
3491 	vnet_public_desc_t	*txdp;
3492 	vgen_private_desc_t	*tbufp;
3493 	vio_dring_entry_hdr_t	*hdrp;
3494 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
3495 	int i;
3496 #ifdef DEBUG
3497 	int ndone = 0;
3498 #endif
3499 
3500 	for (i = 0; i < ldcp->num_txds; i++) {
3501 
3502 		tbufp = &(ldcp->tbufp[i]);
3503 		txdp = tbufp->descp;
3504 		hdrp = &txdp->hdr;
3505 
3506 		if (tbufp->flags & VGEN_PRIV_DESC_BUSY) {
3507 			tbufp->flags = VGEN_PRIV_DESC_FREE;
3508 #ifdef DEBUG
3509 			if (hdrp->dstate == VIO_DESC_DONE)
3510 				ndone++;
3511 #endif
3512 			hdrp->dstate = VIO_DESC_FREE;
3513 			hdrp->ack = B_FALSE;
3514 		}
3515 	}
3516 	/* reset tbuf walking pointers */
3517 	ldcp->next_tbufp = ldcp->tbufp;
3518 	ldcp->cur_tbufp = ldcp->tbufp;
3519 
3520 	/* reset tx seqnum and index */
3521 	ldcp->next_txseq = VNET_ISS;
3522 	ldcp->next_txi = 0;
3523 
3524 	ldcp->resched_peer = B_TRUE;
3525 	ldcp->resched_peer_txi = 0;
3526 
3527 	DBG2(vgenp, ldcp, "num descrs done (%d)\n", ndone);
3528 }
3529 
3530 /* clobber receive descriptor ring */
3531 static void
3532 vgen_clobber_rxds(vgen_ldc_t *ldcp)
3533 {
3534 	ldcp->rx_dhandle = 0;
3535 	bzero(&ldcp->rx_dcookie, sizeof (ldcp->rx_dcookie));
3536 	ldcp->rxdp = NULL;
3537 	ldcp->next_rxi = 0;
3538 	ldcp->num_rxds = 0;
3539 	ldcp->next_rxseq = VNET_ISS;
3540 }
3541 
3542 /* initialize receive descriptor ring */
3543 static int
3544 vgen_init_rxds(vgen_ldc_t *ldcp, uint32_t num_desc, uint32_t desc_size,
3545 	ldc_mem_cookie_t *dcookie, uint32_t ncookies)
3546 {
3547 	int rv;
3548 	ldc_mem_info_t minfo;
3549 
3550 	rv = ldc_mem_dring_map(ldcp->ldc_handle, dcookie, ncookies, num_desc,
3551 	    desc_size, LDC_DIRECT_MAP, &(ldcp->rx_dhandle));
3552 	if (rv != 0) {
3553 		return (DDI_FAILURE);
3554 	}
3555 
3556 	/*
3557 	 * sucessfully mapped, now try to
3558 	 * get info about the mapped dring
3559 	 */
3560 	rv = ldc_mem_dring_info(ldcp->rx_dhandle, &minfo);
3561 	if (rv != 0) {
3562 		(void) ldc_mem_dring_unmap(ldcp->rx_dhandle);
3563 		return (DDI_FAILURE);
3564 	}
3565 
3566 	/*
3567 	 * save ring address, number of descriptors.
3568 	 */
3569 	ldcp->rxdp = (vnet_public_desc_t *)(minfo.vaddr);
3570 	bcopy(dcookie, &(ldcp->rx_dcookie), sizeof (*dcookie));
3571 	ldcp->num_rxdcookies = ncookies;
3572 	ldcp->num_rxds = num_desc;
3573 	ldcp->next_rxi = 0;
3574 	ldcp->next_rxseq = VNET_ISS;
3575 	ldcp->dring_mtype = minfo.mtype;
3576 
3577 	return (DDI_SUCCESS);
3578 }
3579 
3580 /* get channel statistics */
3581 static uint64_t
3582 vgen_ldc_stat(vgen_ldc_t *ldcp, uint_t stat)
3583 {
3584 	vgen_stats_t *statsp;
3585 	uint64_t val;
3586 
3587 	val = 0;
3588 	statsp = &ldcp->stats;
3589 	switch (stat) {
3590 
3591 	case MAC_STAT_MULTIRCV:
3592 		val = statsp->multircv;
3593 		break;
3594 
3595 	case MAC_STAT_BRDCSTRCV:
3596 		val = statsp->brdcstrcv;
3597 		break;
3598 
3599 	case MAC_STAT_MULTIXMT:
3600 		val = statsp->multixmt;
3601 		break;
3602 
3603 	case MAC_STAT_BRDCSTXMT:
3604 		val = statsp->brdcstxmt;
3605 		break;
3606 
3607 	case MAC_STAT_NORCVBUF:
3608 		val = statsp->norcvbuf;
3609 		break;
3610 
3611 	case MAC_STAT_IERRORS:
3612 		val = statsp->ierrors;
3613 		break;
3614 
3615 	case MAC_STAT_NOXMTBUF:
3616 		val = statsp->noxmtbuf;
3617 		break;
3618 
3619 	case MAC_STAT_OERRORS:
3620 		val = statsp->oerrors;
3621 		break;
3622 
3623 	case MAC_STAT_COLLISIONS:
3624 		break;
3625 
3626 	case MAC_STAT_RBYTES:
3627 		val = statsp->rbytes;
3628 		break;
3629 
3630 	case MAC_STAT_IPACKETS:
3631 		val = statsp->ipackets;
3632 		break;
3633 
3634 	case MAC_STAT_OBYTES:
3635 		val = statsp->obytes;
3636 		break;
3637 
3638 	case MAC_STAT_OPACKETS:
3639 		val = statsp->opackets;
3640 		break;
3641 
3642 	/* stats not relevant to ldc, return 0 */
3643 	case MAC_STAT_IFSPEED:
3644 	case ETHER_STAT_ALIGN_ERRORS:
3645 	case ETHER_STAT_FCS_ERRORS:
3646 	case ETHER_STAT_FIRST_COLLISIONS:
3647 	case ETHER_STAT_MULTI_COLLISIONS:
3648 	case ETHER_STAT_DEFER_XMTS:
3649 	case ETHER_STAT_TX_LATE_COLLISIONS:
3650 	case ETHER_STAT_EX_COLLISIONS:
3651 	case ETHER_STAT_MACXMT_ERRORS:
3652 	case ETHER_STAT_CARRIER_ERRORS:
3653 	case ETHER_STAT_TOOLONG_ERRORS:
3654 	case ETHER_STAT_XCVR_ADDR:
3655 	case ETHER_STAT_XCVR_ID:
3656 	case ETHER_STAT_XCVR_INUSE:
3657 	case ETHER_STAT_CAP_1000FDX:
3658 	case ETHER_STAT_CAP_1000HDX:
3659 	case ETHER_STAT_CAP_100FDX:
3660 	case ETHER_STAT_CAP_100HDX:
3661 	case ETHER_STAT_CAP_10FDX:
3662 	case ETHER_STAT_CAP_10HDX:
3663 	case ETHER_STAT_CAP_ASMPAUSE:
3664 	case ETHER_STAT_CAP_PAUSE:
3665 	case ETHER_STAT_CAP_AUTONEG:
3666 	case ETHER_STAT_ADV_CAP_1000FDX:
3667 	case ETHER_STAT_ADV_CAP_1000HDX:
3668 	case ETHER_STAT_ADV_CAP_100FDX:
3669 	case ETHER_STAT_ADV_CAP_100HDX:
3670 	case ETHER_STAT_ADV_CAP_10FDX:
3671 	case ETHER_STAT_ADV_CAP_10HDX:
3672 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
3673 	case ETHER_STAT_ADV_CAP_PAUSE:
3674 	case ETHER_STAT_ADV_CAP_AUTONEG:
3675 	case ETHER_STAT_LP_CAP_1000FDX:
3676 	case ETHER_STAT_LP_CAP_1000HDX:
3677 	case ETHER_STAT_LP_CAP_100FDX:
3678 	case ETHER_STAT_LP_CAP_100HDX:
3679 	case ETHER_STAT_LP_CAP_10FDX:
3680 	case ETHER_STAT_LP_CAP_10HDX:
3681 	case ETHER_STAT_LP_CAP_ASMPAUSE:
3682 	case ETHER_STAT_LP_CAP_PAUSE:
3683 	case ETHER_STAT_LP_CAP_AUTONEG:
3684 	case ETHER_STAT_LINK_ASMPAUSE:
3685 	case ETHER_STAT_LINK_PAUSE:
3686 	case ETHER_STAT_LINK_AUTONEG:
3687 	case ETHER_STAT_LINK_DUPLEX:
3688 	default:
3689 		val = 0;
3690 		break;
3691 
3692 	}
3693 	return (val);
3694 }
3695 
3696 /*
3697  * LDC channel is UP, start handshake process with peer.
3698  */
3699 static void
3700 vgen_handle_evt_up(vgen_ldc_t *ldcp)
3701 {
3702 	vgen_t	*vgenp = LDC_TO_VGEN(ldcp);
3703 
3704 	DBG1(vgenp, ldcp, "enter\n");
3705 
3706 	ASSERT(MUTEX_HELD(&ldcp->cblock));
3707 
3708 	if (ldcp->portp != vgenp->vsw_portp) {
3709 		/*
3710 		 * As the channel is up, use this port from now on.
3711 		 */
3712 		(void) atomic_swap_32(&ldcp->portp->use_vsw_port, B_FALSE);
3713 	}
3714 
3715 	/* Initialize local session id */
3716 	ldcp->local_sid = ddi_get_lbolt();
3717 
3718 	/* clear peer session id */
3719 	ldcp->peer_sid = 0;
3720 	ldcp->hretries = 0;
3721 
3722 	if (ldcp->hphase != VH_PHASE0) {
3723 		vgen_handshake_reset(ldcp);
3724 	}
3725 
3726 	/* Initiate Handshake process with peer ldc endpoint */
3727 	vgen_handshake(vh_nextphase(ldcp));
3728 
3729 	DBG1(vgenp, ldcp, "exit\n");
3730 }
3731 
3732 /*
3733  * LDC channel is Reset, terminate connection with peer and try to
3734  * bring the channel up again.
3735  */
3736 static void
3737 vgen_handle_evt_reset(vgen_ldc_t *ldcp)
3738 {
3739 	ldc_status_t istatus;
3740 	vgen_t	*vgenp = LDC_TO_VGEN(ldcp);
3741 	int	rv;
3742 
3743 	DBG1(vgenp, ldcp, "enter\n");
3744 
3745 	ASSERT(MUTEX_HELD(&ldcp->cblock));
3746 
3747 	if ((ldcp->portp != vgenp->vsw_portp) &&
3748 	    (vgenp->vsw_portp != NULL)) {
3749 		/*
3750 		 * As the channel is down, use the switch port until
3751 		 * the channel becomes ready to be used.
3752 		 */
3753 		(void) atomic_swap_32(&ldcp->portp->use_vsw_port, B_TRUE);
3754 	}
3755 
3756 	if (vgenp->vsw_portp == ldcp->portp) {
3757 		vio_net_report_err_t rep_err =
3758 		    ldcp->portp->vcb.vio_net_report_err;
3759 
3760 		/* Post a reset message */
3761 		rep_err(ldcp->portp->vhp, VIO_NET_RES_DOWN);
3762 	}
3763 
3764 	if (ldcp->hphase != VH_PHASE0) {
3765 		vgen_handshake_reset(ldcp);
3766 	}
3767 
3768 	/* try to bring the channel up */
3769 	rv = ldc_up(ldcp->ldc_handle);
3770 	if (rv != 0) {
3771 		DWARN(vgenp, ldcp, "ldc_up err rv(%d)\n", rv);
3772 	}
3773 
3774 	if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
3775 		DWARN(vgenp, ldcp, "ldc_status err\n");
3776 	} else {
3777 		ldcp->ldc_status = istatus;
3778 	}
3779 
3780 	/* if channel is already UP - restart handshake */
3781 	if (ldcp->ldc_status == LDC_UP) {
3782 		vgen_handle_evt_up(ldcp);
3783 	}
3784 
3785 	DBG1(vgenp, ldcp, "exit\n");
3786 }
3787 
3788 /* Interrupt handler for the channel */
3789 static uint_t
3790 vgen_ldc_cb(uint64_t event, caddr_t arg)
3791 {
3792 	_NOTE(ARGUNUSED(event))
3793 	vgen_ldc_t	*ldcp;
3794 	vgen_t		*vgenp;
3795 	ldc_status_t 	istatus;
3796 	vgen_stats_t	*statsp;
3797 	timeout_id_t	cancel_htid = 0;
3798 	uint_t		ret = LDC_SUCCESS;
3799 
3800 	ldcp = (vgen_ldc_t *)arg;
3801 	vgenp = LDC_TO_VGEN(ldcp);
3802 	statsp = &ldcp->stats;
3803 
3804 	DBG1(vgenp, ldcp, "enter\n");
3805 
3806 	mutex_enter(&ldcp->cblock);
3807 	statsp->callbacks++;
3808 	if ((ldcp->ldc_status == LDC_INIT) || (ldcp->ldc_handle == NULL)) {
3809 		DWARN(vgenp, ldcp, "status(%d) is LDC_INIT\n",
3810 		    ldcp->ldc_status);
3811 		mutex_exit(&ldcp->cblock);
3812 		return (LDC_SUCCESS);
3813 	}
3814 
3815 	/*
3816 	 * cache cancel_htid before the events specific
3817 	 * code may overwrite it. Do not clear ldcp->cancel_htid
3818 	 * as it is also used to indicate the timer to quit immediately.
3819 	 */
3820 	cancel_htid = ldcp->cancel_htid;
3821 
3822 	/*
3823 	 * NOTE: not using switch() as event could be triggered by
3824 	 * a state change and a read request. Also the ordering	of the
3825 	 * check for the event types is deliberate.
3826 	 */
3827 	if (event & LDC_EVT_UP) {
3828 		if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
3829 			DWARN(vgenp, ldcp, "ldc_status err\n");
3830 			/* status couldn't be determined */
3831 			ret = LDC_FAILURE;
3832 			goto ldc_cb_ret;
3833 		}
3834 		ldcp->ldc_status = istatus;
3835 		if (ldcp->ldc_status != LDC_UP) {
3836 			DWARN(vgenp, ldcp, "LDC_EVT_UP received "
3837 			    " but ldc status is not UP(0x%x)\n",
3838 			    ldcp->ldc_status);
3839 			/* spurious interrupt, return success */
3840 			goto ldc_cb_ret;
3841 		}
3842 		DWARN(vgenp, ldcp, "event(%lx) UP, status(%d)\n",
3843 		    event, ldcp->ldc_status);
3844 
3845 		vgen_handle_evt_up(ldcp);
3846 
3847 		ASSERT((event & (LDC_EVT_RESET | LDC_EVT_DOWN)) == 0);
3848 	}
3849 
3850 	/* Handle RESET/DOWN before READ event */
3851 	if (event & (LDC_EVT_RESET | LDC_EVT_DOWN)) {
3852 		if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
3853 			DWARN(vgenp, ldcp, "ldc_status error\n");
3854 			/* status couldn't be determined */
3855 			ret = LDC_FAILURE;
3856 			goto ldc_cb_ret;
3857 		}
3858 		ldcp->ldc_status = istatus;
3859 		DWARN(vgenp, ldcp, "event(%lx) RESET/DOWN, status(%d)\n",
3860 		    event, ldcp->ldc_status);
3861 
3862 		vgen_handle_evt_reset(ldcp);
3863 
3864 		/*
3865 		 * As the channel is down/reset, ignore READ event
3866 		 * but print a debug warning message.
3867 		 */
3868 		if (event & LDC_EVT_READ) {
3869 			DWARN(vgenp, ldcp,
3870 			    "LDC_EVT_READ set along with RESET/DOWN\n");
3871 			event &= ~LDC_EVT_READ;
3872 		}
3873 	}
3874 
3875 	if (event & LDC_EVT_READ) {
3876 		DBG2(vgenp, ldcp, "event(%lx) READ, status(%d)\n",
3877 		    event, ldcp->ldc_status);
3878 
3879 		ASSERT((event & (LDC_EVT_RESET | LDC_EVT_DOWN)) == 0);
3880 
3881 		if (ldcp->rcv_thread != NULL) {
3882 			/*
3883 			 * If the receive thread is enabled, then
3884 			 * wakeup the receive thread to process the
3885 			 * LDC messages.
3886 			 */
3887 			mutex_exit(&ldcp->cblock);
3888 			mutex_enter(&ldcp->rcv_thr_lock);
3889 			if (!(ldcp->rcv_thr_flags & VGEN_WTHR_DATARCVD)) {
3890 				ldcp->rcv_thr_flags |= VGEN_WTHR_DATARCVD;
3891 				cv_signal(&ldcp->rcv_thr_cv);
3892 			}
3893 			mutex_exit(&ldcp->rcv_thr_lock);
3894 			mutex_enter(&ldcp->cblock);
3895 		} else  {
3896 			vgen_handle_evt_read(ldcp);
3897 		}
3898 	}
3899 
3900 ldc_cb_ret:
3901 	/*
3902 	 * Check to see if the status of cancel_htid has
3903 	 * changed. If another timer needs to be cancelled,
3904 	 * then let the next callback to clear it.
3905 	 */
3906 	if (cancel_htid == 0) {
3907 		cancel_htid = ldcp->cancel_htid;
3908 	}
3909 	mutex_exit(&ldcp->cblock);
3910 
3911 	if (cancel_htid) {
3912 		/*
3913 		 * Cancel handshake timer.
3914 		 * untimeout(9F) will not return until the pending callback is
3915 		 * cancelled or has run. No problems will result from calling
3916 		 * untimeout if the handler has already completed.
3917 		 * If the timeout handler did run, then it would just
3918 		 * return as cancel_htid is set.
3919 		 */
3920 		DBG2(vgenp, ldcp, "calling cance_htid =0x%X \n", cancel_htid);
3921 		(void) untimeout(cancel_htid);
3922 		mutex_enter(&ldcp->cblock);
3923 		/* clear it only if its the same as the one we cancelled */
3924 		if (ldcp->cancel_htid == cancel_htid) {
3925 			ldcp->cancel_htid = 0;
3926 		}
3927 		mutex_exit(&ldcp->cblock);
3928 	}
3929 	DBG1(vgenp, ldcp, "exit\n");
3930 	return (ret);
3931 }
3932 
3933 static void
3934 vgen_handle_evt_read(vgen_ldc_t *ldcp)
3935 {
3936 	int		rv;
3937 	uint64_t	*ldcmsg;
3938 	size_t		msglen;
3939 	vgen_t		*vgenp = LDC_TO_VGEN(ldcp);
3940 	vio_msg_tag_t	*tagp;
3941 	ldc_status_t 	istatus;
3942 	boolean_t 	has_data;
3943 
3944 	DBG1(vgenp, ldcp, "enter\n");
3945 
3946 	ldcmsg = ldcp->ldcmsg;
3947 	/*
3948 	 * If the receive thread is enabled, then the cblock
3949 	 * need to be acquired here. If not, the vgen_ldc_cb()
3950 	 * calls this function with cblock held already.
3951 	 */
3952 	if (ldcp->rcv_thread != NULL) {
3953 		mutex_enter(&ldcp->cblock);
3954 	} else {
3955 		ASSERT(MUTEX_HELD(&ldcp->cblock));
3956 	}
3957 
3958 vgen_evt_read:
3959 	do {
3960 		msglen = ldcp->msglen;
3961 		rv = ldc_read(ldcp->ldc_handle, (caddr_t)ldcmsg, &msglen);
3962 
3963 		if (rv != 0) {
3964 			DWARN(vgenp, ldcp, "err rv(%d) len(%d)\n",
3965 			    rv, msglen);
3966 			if (rv == ECONNRESET)
3967 				goto vgen_evtread_error;
3968 			break;
3969 		}
3970 		if (msglen == 0) {
3971 			DBG2(vgenp, ldcp, "ldc_read NODATA");
3972 			break;
3973 		}
3974 		DBG2(vgenp, ldcp, "ldc_read msglen(%d)", msglen);
3975 
3976 		tagp = (vio_msg_tag_t *)ldcmsg;
3977 
3978 		if (ldcp->peer_sid) {
3979 			/*
3980 			 * check sid only after we have received peer's sid
3981 			 * in the version negotiate msg.
3982 			 */
3983 #ifdef DEBUG
3984 			if (vgen_hdbg & HDBG_BAD_SID) {
3985 				/* simulate bad sid condition */
3986 				tagp->vio_sid = 0;
3987 				vgen_hdbg &= ~(HDBG_BAD_SID);
3988 			}
3989 #endif
3990 			rv = vgen_check_sid(ldcp, tagp);
3991 			if (rv != VGEN_SUCCESS) {
3992 				/*
3993 				 * If sid mismatch is detected,
3994 				 * reset the channel.
3995 				 */
3996 				ldcp->need_ldc_reset = B_TRUE;
3997 				goto vgen_evtread_error;
3998 			}
3999 		}
4000 
4001 		switch (tagp->vio_msgtype) {
4002 		case VIO_TYPE_CTRL:
4003 			rv = vgen_handle_ctrlmsg(ldcp, tagp);
4004 			break;
4005 
4006 		case VIO_TYPE_DATA:
4007 			rv = vgen_handle_datamsg(ldcp, tagp, msglen);
4008 			break;
4009 
4010 		case VIO_TYPE_ERR:
4011 			vgen_handle_errmsg(ldcp, tagp);
4012 			break;
4013 
4014 		default:
4015 			DWARN(vgenp, ldcp, "Unknown VIO_TYPE(%x)\n",
4016 			    tagp->vio_msgtype);
4017 			break;
4018 		}
4019 
4020 		/*
4021 		 * If an error is encountered, stop processing and
4022 		 * handle the error.
4023 		 */
4024 		if (rv != 0) {
4025 			goto vgen_evtread_error;
4026 		}
4027 
4028 	} while (msglen);
4029 
4030 	/* check once more before exiting */
4031 	rv = ldc_chkq(ldcp->ldc_handle, &has_data);
4032 	if ((rv == 0) && (has_data == B_TRUE)) {
4033 		DTRACE_PROBE(vgen_chkq);
4034 		goto vgen_evt_read;
4035 	}
4036 
4037 vgen_evtread_error:
4038 	if (rv == ECONNRESET) {
4039 		if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
4040 			DWARN(vgenp, ldcp, "ldc_status err\n");
4041 		} else {
4042 			ldcp->ldc_status = istatus;
4043 		}
4044 		vgen_handle_evt_reset(ldcp);
4045 	} else if (rv) {
4046 		vgen_handshake_retry(ldcp);
4047 	}
4048 
4049 	/*
4050 	 * If the receive thread is enabled, then cancel the
4051 	 * handshake timeout here.
4052 	 */
4053 	if (ldcp->rcv_thread != NULL) {
4054 		timeout_id_t cancel_htid = ldcp->cancel_htid;
4055 
4056 		mutex_exit(&ldcp->cblock);
4057 		if (cancel_htid) {
4058 			/*
4059 			 * Cancel handshake timer. untimeout(9F) will
4060 			 * not return until the pending callback is cancelled
4061 			 * or has run. No problems will result from calling
4062 			 * untimeout if the handler has already completed.
4063 			 * If the timeout handler did run, then it would just
4064 			 * return as cancel_htid is set.
4065 			 */
4066 			DBG2(vgenp, ldcp, "calling cance_htid =0x%X \n",
4067 			    cancel_htid);
4068 			(void) untimeout(cancel_htid);
4069 
4070 			/*
4071 			 * clear it only if its the same as the one we
4072 			 * cancelled
4073 			 */
4074 			mutex_enter(&ldcp->cblock);
4075 			if (ldcp->cancel_htid == cancel_htid) {
4076 				ldcp->cancel_htid = 0;
4077 			}
4078 			mutex_exit(&ldcp->cblock);
4079 		}
4080 	}
4081 
4082 	DBG1(vgenp, ldcp, "exit\n");
4083 }
4084 
4085 /* vgen handshake functions */
4086 
4087 /* change the hphase for the channel to the next phase */
4088 static vgen_ldc_t *
4089 vh_nextphase(vgen_ldc_t *ldcp)
4090 {
4091 	if (ldcp->hphase == VH_PHASE3) {
4092 		ldcp->hphase = VH_DONE;
4093 	} else {
4094 		ldcp->hphase++;
4095 	}
4096 	return (ldcp);
4097 }
4098 
4099 /*
4100  * wrapper routine to send the given message over ldc using ldc_write().
4101  */
4102 static int
4103 vgen_sendmsg(vgen_ldc_t *ldcp, caddr_t msg,  size_t msglen,
4104     boolean_t caller_holds_lock)
4105 {
4106 	int			rv;
4107 	size_t			len;
4108 	uint32_t		retries = 0;
4109 	vgen_t			*vgenp = LDC_TO_VGEN(ldcp);
4110 	vio_msg_tag_t		*tagp = (vio_msg_tag_t *)msg;
4111 	vio_dring_msg_t		*dmsg;
4112 	vio_raw_data_msg_t	*rmsg;
4113 	boolean_t		data_msg = B_FALSE;
4114 
4115 	len = msglen;
4116 	if ((len == 0) || (msg == NULL))
4117 		return (VGEN_FAILURE);
4118 
4119 	if (!caller_holds_lock) {
4120 		mutex_enter(&ldcp->wrlock);
4121 	}
4122 
4123 	if (tagp->vio_subtype == VIO_SUBTYPE_INFO) {
4124 		if (tagp->vio_subtype_env == VIO_DRING_DATA) {
4125 			dmsg = (vio_dring_msg_t *)tagp;
4126 			dmsg->seq_num = ldcp->next_txseq;
4127 			data_msg = B_TRUE;
4128 		} else if (tagp->vio_subtype_env == VIO_PKT_DATA) {
4129 			rmsg = (vio_raw_data_msg_t *)tagp;
4130 			rmsg->seq_num = ldcp->next_txseq;
4131 			data_msg = B_TRUE;
4132 		}
4133 	}
4134 
4135 	do {
4136 		len = msglen;
4137 		rv = ldc_write(ldcp->ldc_handle, (caddr_t)msg, &len);
4138 		if (retries++ >= vgen_ldcwr_retries)
4139 			break;
4140 	} while (rv == EWOULDBLOCK);
4141 
4142 	if (rv == 0 && data_msg == B_TRUE) {
4143 		ldcp->next_txseq++;
4144 	}
4145 
4146 	if (!caller_holds_lock) {
4147 		mutex_exit(&ldcp->wrlock);
4148 	}
4149 
4150 	if (rv != 0) {
4151 		DWARN(vgenp, ldcp, "ldc_write failed: rv(%d)\n",
4152 		    rv, msglen);
4153 		return (rv);
4154 	}
4155 
4156 	if (len != msglen) {
4157 		DWARN(vgenp, ldcp, "ldc_write failed: rv(%d) msglen (%d)\n",
4158 		    rv, msglen);
4159 		return (VGEN_FAILURE);
4160 	}
4161 
4162 	return (VGEN_SUCCESS);
4163 }
4164 
4165 /* send version negotiate message to the peer over ldc */
4166 static int
4167 vgen_send_version_negotiate(vgen_ldc_t *ldcp)
4168 {
4169 	vgen_t		*vgenp = LDC_TO_VGEN(ldcp);
4170 	vio_ver_msg_t	vermsg;
4171 	vio_msg_tag_t	*tagp = &vermsg.tag;
4172 	int		rv;
4173 
4174 	bzero(&vermsg, sizeof (vermsg));
4175 
4176 	tagp->vio_msgtype = VIO_TYPE_CTRL;
4177 	tagp->vio_subtype = VIO_SUBTYPE_INFO;
4178 	tagp->vio_subtype_env = VIO_VER_INFO;
4179 	tagp->vio_sid = ldcp->local_sid;
4180 
4181 	/* get version msg payload from ldcp->local */
4182 	vermsg.ver_major = ldcp->local_hparams.ver_major;
4183 	vermsg.ver_minor = ldcp->local_hparams.ver_minor;
4184 	vermsg.dev_class = ldcp->local_hparams.dev_class;
4185 
4186 	rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (vermsg), B_FALSE);
4187 	if (rv != VGEN_SUCCESS) {
4188 		DWARN(vgenp, ldcp, "vgen_sendmsg failed\n");
4189 		return (rv);
4190 	}
4191 
4192 	ldcp->hstate |= VER_INFO_SENT;
4193 	DBG2(vgenp, ldcp, "VER_INFO_SENT ver(%d,%d)\n",
4194 	    vermsg.ver_major, vermsg.ver_minor);
4195 
4196 	return (VGEN_SUCCESS);
4197 }
4198 
4199 /* send attr info message to the peer over ldc */
4200 static int
4201 vgen_send_attr_info(vgen_ldc_t *ldcp)
4202 {
4203 	vgen_t		*vgenp = LDC_TO_VGEN(ldcp);
4204 	vnet_attr_msg_t	attrmsg;
4205 	vio_msg_tag_t	*tagp = &attrmsg.tag;
4206 	int		rv;
4207 
4208 	bzero(&attrmsg, sizeof (attrmsg));
4209 
4210 	tagp->vio_msgtype = VIO_TYPE_CTRL;
4211 	tagp->vio_subtype = VIO_SUBTYPE_INFO;
4212 	tagp->vio_subtype_env = VIO_ATTR_INFO;
4213 	tagp->vio_sid = ldcp->local_sid;
4214 
4215 	/* get attr msg payload from ldcp->local */
4216 	attrmsg.mtu = ldcp->local_hparams.mtu;
4217 	attrmsg.addr = ldcp->local_hparams.addr;
4218 	attrmsg.addr_type = ldcp->local_hparams.addr_type;
4219 	attrmsg.xfer_mode = ldcp->local_hparams.xfer_mode;
4220 	attrmsg.ack_freq = ldcp->local_hparams.ack_freq;
4221 
4222 	rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (attrmsg), B_FALSE);
4223 	if (rv != VGEN_SUCCESS) {
4224 		DWARN(vgenp, ldcp, "vgen_sendmsg failed\n");
4225 		return (rv);
4226 	}
4227 
4228 	ldcp->hstate |= ATTR_INFO_SENT;
4229 	DBG2(vgenp, ldcp, "ATTR_INFO_SENT\n");
4230 
4231 	return (VGEN_SUCCESS);
4232 }
4233 
4234 /* send descriptor ring register message to the peer over ldc */
4235 static int
4236 vgen_send_dring_reg(vgen_ldc_t *ldcp)
4237 {
4238 	vgen_t			*vgenp = LDC_TO_VGEN(ldcp);
4239 	vio_dring_reg_msg_t	msg;
4240 	vio_msg_tag_t		*tagp = &msg.tag;
4241 	int		rv;
4242 
4243 	bzero(&msg, sizeof (msg));
4244 
4245 	tagp->vio_msgtype = VIO_TYPE_CTRL;
4246 	tagp->vio_subtype = VIO_SUBTYPE_INFO;
4247 	tagp->vio_subtype_env = VIO_DRING_REG;
4248 	tagp->vio_sid = ldcp->local_sid;
4249 
4250 	/* get dring info msg payload from ldcp->local */
4251 	bcopy(&(ldcp->local_hparams.dring_cookie), (msg.cookie),
4252 	    sizeof (ldc_mem_cookie_t));
4253 	msg.ncookies = ldcp->local_hparams.num_dcookies;
4254 	msg.num_descriptors = ldcp->local_hparams.num_desc;
4255 	msg.descriptor_size = ldcp->local_hparams.desc_size;
4256 
4257 	/*
4258 	 * dring_ident is set to 0. After mapping the dring, peer sets this
4259 	 * value and sends it in the ack, which is saved in
4260 	 * vgen_handle_dring_reg().
4261 	 */
4262 	msg.dring_ident = 0;
4263 
4264 	rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (msg), B_FALSE);
4265 	if (rv != VGEN_SUCCESS) {
4266 		DWARN(vgenp, ldcp, "vgen_sendmsg failed\n");
4267 		return (rv);
4268 	}
4269 
4270 	ldcp->hstate |= DRING_INFO_SENT;
4271 	DBG2(vgenp, ldcp, "DRING_INFO_SENT \n");
4272 
4273 	return (VGEN_SUCCESS);
4274 }
4275 
4276 static int
4277 vgen_send_rdx_info(vgen_ldc_t *ldcp)
4278 {
4279 	vgen_t		*vgenp = LDC_TO_VGEN(ldcp);
4280 	vio_rdx_msg_t	rdxmsg;
4281 	vio_msg_tag_t	*tagp = &rdxmsg.tag;
4282 	int		rv;
4283 
4284 	bzero(&rdxmsg, sizeof (rdxmsg));
4285 
4286 	tagp->vio_msgtype = VIO_TYPE_CTRL;
4287 	tagp->vio_subtype = VIO_SUBTYPE_INFO;
4288 	tagp->vio_subtype_env = VIO_RDX;
4289 	tagp->vio_sid = ldcp->local_sid;
4290 
4291 	rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (rdxmsg), B_FALSE);
4292 	if (rv != VGEN_SUCCESS) {
4293 		DWARN(vgenp, ldcp, "vgen_sendmsg failed\n");
4294 		return (rv);
4295 	}
4296 
4297 	ldcp->hstate |= RDX_INFO_SENT;
4298 	DBG2(vgenp, ldcp, "RDX_INFO_SENT\n");
4299 
4300 	return (VGEN_SUCCESS);
4301 }
4302 
4303 /* send descriptor ring data message to the peer over ldc */
4304 static int
4305 vgen_send_dring_data(vgen_ldc_t *ldcp, uint32_t start, int32_t end)
4306 {
4307 	vgen_t		*vgenp = LDC_TO_VGEN(ldcp);
4308 	vio_dring_msg_t	dringmsg, *msgp = &dringmsg;
4309 	vio_msg_tag_t	*tagp = &msgp->tag;
4310 	vgen_stats_t	*statsp = &ldcp->stats;
4311 	int		rv;
4312 
4313 	bzero(msgp, sizeof (*msgp));
4314 
4315 	tagp->vio_msgtype = VIO_TYPE_DATA;
4316 	tagp->vio_subtype = VIO_SUBTYPE_INFO;
4317 	tagp->vio_subtype_env = VIO_DRING_DATA;
4318 	tagp->vio_sid = ldcp->local_sid;
4319 
4320 	msgp->dring_ident = ldcp->local_hparams.dring_ident;
4321 	msgp->start_idx = start;
4322 	msgp->end_idx = end;
4323 
4324 	rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (dringmsg), B_TRUE);
4325 	if (rv != VGEN_SUCCESS) {
4326 		DWARN(vgenp, ldcp, "vgen_sendmsg failed\n");
4327 		return (rv);
4328 	}
4329 
4330 	statsp->dring_data_msgs++;
4331 
4332 	DBG2(vgenp, ldcp, "DRING_DATA_SENT \n");
4333 
4334 	return (VGEN_SUCCESS);
4335 }
4336 
4337 /* send multicast addr info message to vsw */
4338 static int
4339 vgen_send_mcast_info(vgen_ldc_t *ldcp)
4340 {
4341 	vnet_mcast_msg_t	mcastmsg;
4342 	vnet_mcast_msg_t	*msgp;
4343 	vio_msg_tag_t		*tagp;
4344 	vgen_t			*vgenp;
4345 	struct ether_addr	*mca;
4346 	int			rv;
4347 	int			i;
4348 	uint32_t		size;
4349 	uint32_t		mccount;
4350 	uint32_t		n;
4351 
4352 	msgp = &mcastmsg;
4353 	tagp = &msgp->tag;
4354 	vgenp = LDC_TO_VGEN(ldcp);
4355 
4356 	mccount = vgenp->mccount;
4357 	i = 0;
4358 
4359 	do {
4360 		tagp->vio_msgtype = VIO_TYPE_CTRL;
4361 		tagp->vio_subtype = VIO_SUBTYPE_INFO;
4362 		tagp->vio_subtype_env = VNET_MCAST_INFO;
4363 		tagp->vio_sid = ldcp->local_sid;
4364 
4365 		n = ((mccount >= VNET_NUM_MCAST) ? VNET_NUM_MCAST : mccount);
4366 		size = n * sizeof (struct ether_addr);
4367 
4368 		mca = &(vgenp->mctab[i]);
4369 		bcopy(mca, (msgp->mca), size);
4370 		msgp->set = B_TRUE;
4371 		msgp->count = n;
4372 
4373 		rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*msgp),
4374 		    B_FALSE);
4375 		if (rv != VGEN_SUCCESS) {
4376 			DWARN(vgenp, ldcp, "vgen_sendmsg err(%d)\n", rv);
4377 			return (rv);
4378 		}
4379 
4380 		mccount -= n;
4381 		i += n;
4382 
4383 	} while (mccount);
4384 
4385 	return (VGEN_SUCCESS);
4386 }
4387 
4388 /* Initiate Phase 2 of handshake */
4389 static int
4390 vgen_handshake_phase2(vgen_ldc_t *ldcp)
4391 {
4392 	int rv;
4393 	uint32_t ncookies = 0;
4394 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
4395 
4396 #ifdef DEBUG
4397 	if (vgen_hdbg & HDBG_OUT_STATE) {
4398 		/* simulate out of state condition */
4399 		vgen_hdbg &= ~(HDBG_OUT_STATE);
4400 		rv = vgen_send_rdx_info(ldcp);
4401 		return (rv);
4402 	}
4403 	if (vgen_hdbg & HDBG_TIMEOUT) {
4404 		/* simulate timeout condition */
4405 		vgen_hdbg &= ~(HDBG_TIMEOUT);
4406 		return (VGEN_SUCCESS);
4407 	}
4408 #endif
4409 	rv = vgen_send_attr_info(ldcp);
4410 	if (rv != VGEN_SUCCESS) {
4411 		return (rv);
4412 	}
4413 
4414 	/* Bind descriptor ring to the channel */
4415 	if (ldcp->num_txdcookies == 0) {
4416 		rv = ldc_mem_dring_bind(ldcp->ldc_handle, ldcp->tx_dhandle,
4417 		    LDC_DIRECT_MAP | LDC_SHADOW_MAP, LDC_MEM_RW,
4418 		    &ldcp->tx_dcookie, &ncookies);
4419 		if (rv != 0) {
4420 			DWARN(vgenp, ldcp, "ldc_mem_dring_bind failed "
4421 			    "rv(%x)\n", rv);
4422 			return (rv);
4423 		}
4424 		ASSERT(ncookies == 1);
4425 		ldcp->num_txdcookies = ncookies;
4426 	}
4427 
4428 	/* update local dring_info params */
4429 	bcopy(&(ldcp->tx_dcookie), &(ldcp->local_hparams.dring_cookie),
4430 	    sizeof (ldc_mem_cookie_t));
4431 	ldcp->local_hparams.num_dcookies = ldcp->num_txdcookies;
4432 	ldcp->local_hparams.num_desc = ldcp->num_txds;
4433 	ldcp->local_hparams.desc_size = sizeof (vnet_public_desc_t);
4434 
4435 	rv = vgen_send_dring_reg(ldcp);
4436 	if (rv != VGEN_SUCCESS) {
4437 		return (rv);
4438 	}
4439 
4440 	return (VGEN_SUCCESS);
4441 }
4442 
4443 /*
4444  * Set vnet-protocol-version dependent functions based on version.
4445  */
4446 static void
4447 vgen_set_vnet_proto_ops(vgen_ldc_t *ldcp)
4448 {
4449 	vgen_hparams_t	*lp = &ldcp->local_hparams;
4450 	vgen_t		*vgenp = LDC_TO_VGEN(ldcp);
4451 
4452 	if (VGEN_VER_GTEQ(ldcp, 1, 4)) {
4453 		/*
4454 		 * If the version negotiated with peer is >= 1.4(Jumbo Frame
4455 		 * Support), set the mtu in our attributes to max_frame_size.
4456 		 */
4457 		lp->mtu = vgenp->max_frame_size;
4458 	} else  if (VGEN_VER_EQ(ldcp, 1, 3)) {
4459 		/*
4460 		 * If the version negotiated with peer is == 1.3 (Vlan Tag
4461 		 * Support) set the attr.mtu to ETHERMAX + VLAN_TAGSZ.
4462 		 */
4463 		lp->mtu = ETHERMAX + VLAN_TAGSZ;
4464 	} else {
4465 		vgen_port_t	*portp = ldcp->portp;
4466 		vnet_t		*vnetp = vgenp->vnetp;
4467 		/*
4468 		 * Pre-1.3 peers expect max frame size of ETHERMAX.
4469 		 * We can negotiate that size with those peers provided the
4470 		 * following conditions are true:
4471 		 * - Only pvid is defined for our peer and there are no vids.
4472 		 * - pvids are equal.
4473 		 * If the above conditions are true, then we can send/recv only
4474 		 * untagged frames of max size ETHERMAX.
4475 		 */
4476 		if (portp->nvids == 0 && portp->pvid == vnetp->pvid) {
4477 			lp->mtu = ETHERMAX;
4478 		}
4479 	}
4480 
4481 	if (VGEN_VER_GTEQ(ldcp, 1, 2)) {
4482 		/* Versions >= 1.2 */
4483 
4484 		if (VGEN_PRI_ETH_DEFINED(vgenp)) {
4485 			/*
4486 			 * enable priority routines and pkt mode only if
4487 			 * at least one pri-eth-type is specified in MD.
4488 			 */
4489 
4490 			ldcp->tx = vgen_ldcsend;
4491 			ldcp->rx_pktdata = vgen_handle_pkt_data;
4492 
4493 			/* set xfer mode for vgen_send_attr_info() */
4494 			lp->xfer_mode = VIO_PKT_MODE | VIO_DRING_MODE_V1_2;
4495 
4496 		} else {
4497 			/* no priority eth types defined in MD */
4498 
4499 			ldcp->tx = vgen_ldcsend_dring;
4500 			ldcp->rx_pktdata = vgen_handle_pkt_data_nop;
4501 
4502 			/* set xfer mode for vgen_send_attr_info() */
4503 			lp->xfer_mode = VIO_DRING_MODE_V1_2;
4504 
4505 		}
4506 	} else {
4507 		/* Versions prior to 1.2  */
4508 
4509 		vgen_reset_vnet_proto_ops(ldcp);
4510 	}
4511 }
4512 
4513 /*
4514  * Reset vnet-protocol-version dependent functions to pre-v1.2.
4515  */
4516 static void
4517 vgen_reset_vnet_proto_ops(vgen_ldc_t *ldcp)
4518 {
4519 	vgen_hparams_t	*lp = &ldcp->local_hparams;
4520 
4521 	ldcp->tx = vgen_ldcsend_dring;
4522 	ldcp->rx_pktdata = vgen_handle_pkt_data_nop;
4523 
4524 	/* set xfer mode for vgen_send_attr_info() */
4525 	lp->xfer_mode = VIO_DRING_MODE_V1_0;
4526 }
4527 
4528 static void
4529 vgen_vlan_unaware_port_reset(vgen_port_t *portp)
4530 {
4531 	vgen_ldclist_t	*ldclp;
4532 	vgen_ldc_t	*ldcp;
4533 	vgen_t		*vgenp = portp->vgenp;
4534 	vnet_t		*vnetp = vgenp->vnetp;
4535 
4536 	ldclp = &portp->ldclist;
4537 
4538 	READ_ENTER(&ldclp->rwlock);
4539 
4540 	/*
4541 	 * NOTE: for now, we will assume we have a single channel.
4542 	 */
4543 	if (ldclp->headp == NULL) {
4544 		RW_EXIT(&ldclp->rwlock);
4545 		return;
4546 	}
4547 	ldcp = ldclp->headp;
4548 
4549 	mutex_enter(&ldcp->cblock);
4550 
4551 	/*
4552 	 * If the peer is vlan_unaware(ver < 1.3), reset channel and terminate
4553 	 * the connection. See comments in vgen_set_vnet_proto_ops().
4554 	 */
4555 	if (ldcp->hphase == VH_DONE && VGEN_VER_LT(ldcp, 1, 3) &&
4556 	    (portp->nvids != 0 || portp->pvid != vnetp->pvid)) {
4557 		ldcp->need_ldc_reset = B_TRUE;
4558 		vgen_handshake_retry(ldcp);
4559 	}
4560 
4561 	mutex_exit(&ldcp->cblock);
4562 
4563 	RW_EXIT(&ldclp->rwlock);
4564 }
4565 
4566 static void
4567 vgen_reset_vlan_unaware_ports(vgen_t *vgenp)
4568 {
4569 	vgen_port_t	*portp;
4570 	vgen_portlist_t	*plistp;
4571 
4572 	plistp = &(vgenp->vgenports);
4573 	READ_ENTER(&plistp->rwlock);
4574 
4575 	for (portp = plistp->headp; portp != NULL; portp = portp->nextp) {
4576 
4577 		vgen_vlan_unaware_port_reset(portp);
4578 
4579 	}
4580 
4581 	RW_EXIT(&plistp->rwlock);
4582 }
4583 
4584 /*
4585  * This function resets the handshake phase to VH_PHASE0(pre-handshake phase).
4586  * This can happen after a channel comes up (status: LDC_UP) or
4587  * when handshake gets terminated due to various conditions.
4588  */
4589 static void
4590 vgen_reset_hphase(vgen_ldc_t *ldcp)
4591 {
4592 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
4593 	ldc_status_t istatus;
4594 	int rv;
4595 
4596 	DBG1(vgenp, ldcp, "enter\n");
4597 	/* reset hstate and hphase */
4598 	ldcp->hstate = 0;
4599 	ldcp->hphase = VH_PHASE0;
4600 
4601 	vgen_reset_vnet_proto_ops(ldcp);
4602 
4603 	/*
4604 	 * Save the id of pending handshake timer in cancel_htid.
4605 	 * This will be checked in vgen_ldc_cb() and the handshake timer will
4606 	 * be cancelled after releasing cblock.
4607 	 */
4608 	if (ldcp->htid) {
4609 		ldcp->cancel_htid = ldcp->htid;
4610 		ldcp->htid = 0;
4611 	}
4612 
4613 	if (ldcp->local_hparams.dring_ready) {
4614 		ldcp->local_hparams.dring_ready = B_FALSE;
4615 	}
4616 
4617 	/* Unbind tx descriptor ring from the channel */
4618 	if (ldcp->num_txdcookies) {
4619 		rv = ldc_mem_dring_unbind(ldcp->tx_dhandle);
4620 		if (rv != 0) {
4621 			DWARN(vgenp, ldcp, "ldc_mem_dring_unbind failed\n");
4622 		}
4623 		ldcp->num_txdcookies = 0;
4624 	}
4625 
4626 	if (ldcp->peer_hparams.dring_ready) {
4627 		ldcp->peer_hparams.dring_ready = B_FALSE;
4628 		/* Unmap peer's dring */
4629 		(void) ldc_mem_dring_unmap(ldcp->rx_dhandle);
4630 		vgen_clobber_rxds(ldcp);
4631 	}
4632 
4633 	vgen_clobber_tbufs(ldcp);
4634 
4635 	/*
4636 	 * clear local handshake params and initialize.
4637 	 */
4638 	bzero(&(ldcp->local_hparams), sizeof (ldcp->local_hparams));
4639 
4640 	/* set version to the highest version supported */
4641 	ldcp->local_hparams.ver_major =
4642 	    ldcp->vgen_versions[0].ver_major;
4643 	ldcp->local_hparams.ver_minor =
4644 	    ldcp->vgen_versions[0].ver_minor;
4645 	ldcp->local_hparams.dev_class = VDEV_NETWORK;
4646 
4647 	/* set attr_info params */
4648 	ldcp->local_hparams.mtu = vgenp->max_frame_size;
4649 	ldcp->local_hparams.addr =
4650 	    vnet_macaddr_strtoul(vgenp->macaddr);
4651 	ldcp->local_hparams.addr_type = ADDR_TYPE_MAC;
4652 	ldcp->local_hparams.xfer_mode = VIO_DRING_MODE_V1_0;
4653 	ldcp->local_hparams.ack_freq = 0;	/* don't need acks */
4654 
4655 	/*
4656 	 * Note: dring is created, but not bound yet.
4657 	 * local dring_info params will be updated when we bind the dring in
4658 	 * vgen_handshake_phase2().
4659 	 * dring_ident is set to 0. After mapping the dring, peer sets this
4660 	 * value and sends it in the ack, which is saved in
4661 	 * vgen_handle_dring_reg().
4662 	 */
4663 	ldcp->local_hparams.dring_ident = 0;
4664 
4665 	/* clear peer_hparams */
4666 	bzero(&(ldcp->peer_hparams), sizeof (ldcp->peer_hparams));
4667 
4668 	/* reset the channel if required */
4669 	if (ldcp->need_ldc_reset) {
4670 		DWARN(vgenp, ldcp, "Doing Channel Reset...\n");
4671 		ldcp->need_ldc_reset = B_FALSE;
4672 		(void) ldc_down(ldcp->ldc_handle);
4673 		(void) ldc_status(ldcp->ldc_handle, &istatus);
4674 		DBG2(vgenp, ldcp, "Reset Done,ldc_status(%x)\n", istatus);
4675 		ldcp->ldc_status = istatus;
4676 
4677 		/* clear sids */
4678 		ldcp->local_sid = 0;
4679 		ldcp->peer_sid = 0;
4680 
4681 		/* try to bring the channel up */
4682 		rv = ldc_up(ldcp->ldc_handle);
4683 		if (rv != 0) {
4684 			DWARN(vgenp, ldcp, "ldc_up err rv(%d)\n", rv);
4685 		}
4686 
4687 		if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
4688 			DWARN(vgenp, ldcp, "ldc_status err\n");
4689 		} else {
4690 			ldcp->ldc_status = istatus;
4691 		}
4692 	}
4693 }
4694 
4695 /* wrapper function for vgen_reset_hphase */
4696 static void
4697 vgen_handshake_reset(vgen_ldc_t *ldcp)
4698 {
4699 	ASSERT(MUTEX_HELD(&ldcp->cblock));
4700 	mutex_enter(&ldcp->rxlock);
4701 	mutex_enter(&ldcp->wrlock);
4702 	mutex_enter(&ldcp->txlock);
4703 	mutex_enter(&ldcp->tclock);
4704 
4705 	vgen_reset_hphase(ldcp);
4706 
4707 	mutex_exit(&ldcp->tclock);
4708 	mutex_exit(&ldcp->txlock);
4709 	mutex_exit(&ldcp->wrlock);
4710 	mutex_exit(&ldcp->rxlock);
4711 }
4712 
4713 /*
4714  * Initiate handshake with the peer by sending various messages
4715  * based on the handshake-phase that the channel is currently in.
4716  */
4717 static void
4718 vgen_handshake(vgen_ldc_t *ldcp)
4719 {
4720 	uint32_t hphase = ldcp->hphase;
4721 	vgen_t	*vgenp = LDC_TO_VGEN(ldcp);
4722 	ldc_status_t	istatus;
4723 	int	rv = 0;
4724 
4725 	switch (hphase) {
4726 
4727 	case VH_PHASE1:
4728 
4729 		/*
4730 		 * start timer, for entire handshake process, turn this timer
4731 		 * off if all phases of handshake complete successfully and
4732 		 * hphase goes to VH_DONE(below) or
4733 		 * vgen_reset_hphase() gets called or
4734 		 * channel is reset due to errors or
4735 		 * vgen_ldc_uninit() is invoked(vgen_stop).
4736 		 */
4737 		ASSERT(ldcp->htid == 0);
4738 		ldcp->htid = timeout(vgen_hwatchdog, (caddr_t)ldcp,
4739 		    drv_usectohz(vgen_hwd_interval * MICROSEC));
4740 
4741 		/* Phase 1 involves negotiating the version */
4742 		rv = vgen_send_version_negotiate(ldcp);
4743 		break;
4744 
4745 	case VH_PHASE2:
4746 		rv = vgen_handshake_phase2(ldcp);
4747 		break;
4748 
4749 	case VH_PHASE3:
4750 		rv = vgen_send_rdx_info(ldcp);
4751 		break;
4752 
4753 	case VH_DONE:
4754 		/*
4755 		 * Save the id of pending handshake timer in cancel_htid.
4756 		 * This will be checked in vgen_ldc_cb() and the handshake
4757 		 * timer will be cancelled after releasing cblock.
4758 		 */
4759 		if (ldcp->htid) {
4760 			ldcp->cancel_htid = ldcp->htid;
4761 			ldcp->htid = 0;
4762 		}
4763 		ldcp->hretries = 0;
4764 		DBG1(vgenp, ldcp, "Handshake Done\n");
4765 
4766 		if (ldcp->portp == vgenp->vsw_portp) {
4767 			/*
4768 			 * If this channel(port) is connected to vsw,
4769 			 * need to sync multicast table with vsw.
4770 			 */
4771 			mutex_exit(&ldcp->cblock);
4772 
4773 			mutex_enter(&vgenp->lock);
4774 			rv = vgen_send_mcast_info(ldcp);
4775 			mutex_exit(&vgenp->lock);
4776 
4777 			mutex_enter(&ldcp->cblock);
4778 			if (rv != VGEN_SUCCESS)
4779 				break;
4780 		}
4781 
4782 		/*
4783 		 * Check if mac layer should be notified to restart
4784 		 * transmissions. This can happen if the channel got
4785 		 * reset and vgen_clobber_tbufs() is called, while
4786 		 * need_resched is set.
4787 		 */
4788 		mutex_enter(&ldcp->tclock);
4789 		if (ldcp->need_resched) {
4790 			vio_net_tx_update_t vtx_update =
4791 			    ldcp->portp->vcb.vio_net_tx_update;
4792 
4793 			ldcp->need_resched = B_FALSE;
4794 			vtx_update(ldcp->portp->vhp);
4795 		}
4796 		mutex_exit(&ldcp->tclock);
4797 
4798 		break;
4799 
4800 	default:
4801 		break;
4802 	}
4803 
4804 	if (rv == ECONNRESET) {
4805 		if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
4806 			DWARN(vgenp, ldcp, "ldc_status err\n");
4807 		} else {
4808 			ldcp->ldc_status = istatus;
4809 		}
4810 		vgen_handle_evt_reset(ldcp);
4811 	} else if (rv) {
4812 		vgen_handshake_reset(ldcp);
4813 	}
4814 }
4815 
4816 /*
4817  * Check if the current handshake phase has completed successfully and
4818  * return the status.
4819  */
4820 static int
4821 vgen_handshake_done(vgen_ldc_t *ldcp)
4822 {
4823 	vgen_t		*vgenp = LDC_TO_VGEN(ldcp);
4824 	uint32_t	hphase = ldcp->hphase;
4825 	int 		status = 0;
4826 
4827 	switch (hphase) {
4828 
4829 	case VH_PHASE1:
4830 		/*
4831 		 * Phase1 is done, if version negotiation
4832 		 * completed successfully.
4833 		 */
4834 		status = ((ldcp->hstate & VER_NEGOTIATED) ==
4835 		    VER_NEGOTIATED);
4836 		break;
4837 
4838 	case VH_PHASE2:
4839 		/*
4840 		 * Phase 2 is done, if attr info and dring info
4841 		 * have been exchanged successfully.
4842 		 */
4843 		status = (((ldcp->hstate & ATTR_INFO_EXCHANGED) ==
4844 		    ATTR_INFO_EXCHANGED) &&
4845 		    ((ldcp->hstate & DRING_INFO_EXCHANGED) ==
4846 		    DRING_INFO_EXCHANGED));
4847 		break;
4848 
4849 	case VH_PHASE3:
4850 		/* Phase 3 is done, if rdx msg has been exchanged */
4851 		status = ((ldcp->hstate & RDX_EXCHANGED) ==
4852 		    RDX_EXCHANGED);
4853 		break;
4854 
4855 	default:
4856 		break;
4857 	}
4858 
4859 	if (status == 0) {
4860 		return (VGEN_FAILURE);
4861 	}
4862 	DBG2(vgenp, ldcp, "PHASE(%d)\n", hphase);
4863 	return (VGEN_SUCCESS);
4864 }
4865 
4866 /* retry handshake on failure */
4867 static void
4868 vgen_handshake_retry(vgen_ldc_t *ldcp)
4869 {
4870 	/* reset handshake phase */
4871 	vgen_handshake_reset(ldcp);
4872 
4873 	/* handshake retry is specified and the channel is UP */
4874 	if (vgen_max_hretries && (ldcp->ldc_status == LDC_UP)) {
4875 		if (ldcp->hretries++ < vgen_max_hretries) {
4876 			ldcp->local_sid = ddi_get_lbolt();
4877 			vgen_handshake(vh_nextphase(ldcp));
4878 		}
4879 	}
4880 }
4881 
4882 /*
4883  * Handle a version info msg from the peer or an ACK/NACK from the peer
4884  * to a version info msg that we sent.
4885  */
4886 static int
4887 vgen_handle_version_negotiate(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
4888 {
4889 	vgen_t		*vgenp;
4890 	vio_ver_msg_t	*vermsg = (vio_ver_msg_t *)tagp;
4891 	int		ack = 0;
4892 	int		failed = 0;
4893 	int		idx;
4894 	vgen_ver_t	*versions = ldcp->vgen_versions;
4895 	int		rv = 0;
4896 
4897 	vgenp = LDC_TO_VGEN(ldcp);
4898 	DBG1(vgenp, ldcp, "enter\n");
4899 	switch (tagp->vio_subtype) {
4900 	case VIO_SUBTYPE_INFO:
4901 
4902 		/*  Cache sid of peer if this is the first time */
4903 		if (ldcp->peer_sid == 0) {
4904 			DBG2(vgenp, ldcp, "Caching peer_sid(%x)\n",
4905 			    tagp->vio_sid);
4906 			ldcp->peer_sid = tagp->vio_sid;
4907 		}
4908 
4909 		if (ldcp->hphase != VH_PHASE1) {
4910 			/*
4911 			 * If we are not already in VH_PHASE1, reset to
4912 			 * pre-handshake state, and initiate handshake
4913 			 * to the peer too.
4914 			 */
4915 			vgen_handshake_reset(ldcp);
4916 			vgen_handshake(vh_nextphase(ldcp));
4917 		}
4918 		ldcp->hstate |= VER_INFO_RCVD;
4919 
4920 		/* save peer's requested values */
4921 		ldcp->peer_hparams.ver_major = vermsg->ver_major;
4922 		ldcp->peer_hparams.ver_minor = vermsg->ver_minor;
4923 		ldcp->peer_hparams.dev_class = vermsg->dev_class;
4924 
4925 		if ((vermsg->dev_class != VDEV_NETWORK) &&
4926 		    (vermsg->dev_class != VDEV_NETWORK_SWITCH)) {
4927 			/* unsupported dev_class, send NACK */
4928 
4929 			DWARN(vgenp, ldcp, "Version Negotiation Failed\n");
4930 
4931 			tagp->vio_subtype = VIO_SUBTYPE_NACK;
4932 			tagp->vio_sid = ldcp->local_sid;
4933 			/* send reply msg back to peer */
4934 			rv = vgen_sendmsg(ldcp, (caddr_t)tagp,
4935 			    sizeof (*vermsg), B_FALSE);
4936 			if (rv != VGEN_SUCCESS) {
4937 				return (rv);
4938 			}
4939 			return (VGEN_FAILURE);
4940 		}
4941 
4942 		DBG2(vgenp, ldcp, "VER_INFO_RCVD, ver(%d,%d)\n",
4943 		    vermsg->ver_major,  vermsg->ver_minor);
4944 
4945 		idx = 0;
4946 
4947 		for (;;) {
4948 
4949 			if (vermsg->ver_major > versions[idx].ver_major) {
4950 
4951 				/* nack with next lower version */
4952 				tagp->vio_subtype = VIO_SUBTYPE_NACK;
4953 				vermsg->ver_major = versions[idx].ver_major;
4954 				vermsg->ver_minor = versions[idx].ver_minor;
4955 				break;
4956 			}
4957 
4958 			if (vermsg->ver_major == versions[idx].ver_major) {
4959 
4960 				/* major version match - ACK version */
4961 				tagp->vio_subtype = VIO_SUBTYPE_ACK;
4962 				ack = 1;
4963 
4964 				/*
4965 				 * lower minor version to the one this endpt
4966 				 * supports, if necessary
4967 				 */
4968 				if (vermsg->ver_minor >
4969 				    versions[idx].ver_minor) {
4970 					vermsg->ver_minor =
4971 					    versions[idx].ver_minor;
4972 					ldcp->peer_hparams.ver_minor =
4973 					    versions[idx].ver_minor;
4974 				}
4975 				break;
4976 			}
4977 
4978 			idx++;
4979 
4980 			if (idx == VGEN_NUM_VER) {
4981 
4982 				/* no version match - send NACK */
4983 				tagp->vio_subtype = VIO_SUBTYPE_NACK;
4984 				vermsg->ver_major = 0;
4985 				vermsg->ver_minor = 0;
4986 				failed = 1;
4987 				break;
4988 			}
4989 
4990 		}
4991 
4992 		tagp->vio_sid = ldcp->local_sid;
4993 
4994 		/* send reply msg back to peer */
4995 		rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*vermsg),
4996 		    B_FALSE);
4997 		if (rv != VGEN_SUCCESS) {
4998 			return (rv);
4999 		}
5000 
5001 		if (ack) {
5002 			ldcp->hstate |= VER_ACK_SENT;
5003 			DBG2(vgenp, ldcp, "VER_ACK_SENT, ver(%d,%d) \n",
5004 			    vermsg->ver_major, vermsg->ver_minor);
5005 		}
5006 		if (failed) {
5007 			DWARN(vgenp, ldcp, "Negotiation Failed\n");
5008 			return (VGEN_FAILURE);
5009 		}
5010 		if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) {
5011 
5012 			/*  VER_ACK_SENT and VER_ACK_RCVD */
5013 
5014 			/* local and peer versions match? */
5015 			ASSERT((ldcp->local_hparams.ver_major ==
5016 			    ldcp->peer_hparams.ver_major) &&
5017 			    (ldcp->local_hparams.ver_minor ==
5018 			    ldcp->peer_hparams.ver_minor));
5019 
5020 			vgen_set_vnet_proto_ops(ldcp);
5021 
5022 			/* move to the next phase */
5023 			vgen_handshake(vh_nextphase(ldcp));
5024 		}
5025 
5026 		break;
5027 
5028 	case VIO_SUBTYPE_ACK:
5029 
5030 		if (ldcp->hphase != VH_PHASE1) {
5031 			/*  This should not happen. */
5032 			DWARN(vgenp, ldcp, "Invalid Phase(%u)\n", ldcp->hphase);
5033 			return (VGEN_FAILURE);
5034 		}
5035 
5036 		/* SUCCESS - we have agreed on a version */
5037 		ldcp->local_hparams.ver_major = vermsg->ver_major;
5038 		ldcp->local_hparams.ver_minor = vermsg->ver_minor;
5039 		ldcp->hstate |= VER_ACK_RCVD;
5040 
5041 		DBG2(vgenp, ldcp, "VER_ACK_RCVD, ver(%d,%d) \n",
5042 		    vermsg->ver_major,  vermsg->ver_minor);
5043 
5044 		if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) {
5045 
5046 			/*  VER_ACK_SENT and VER_ACK_RCVD */
5047 
5048 			/* local and peer versions match? */
5049 			ASSERT((ldcp->local_hparams.ver_major ==
5050 			    ldcp->peer_hparams.ver_major) &&
5051 			    (ldcp->local_hparams.ver_minor ==
5052 			    ldcp->peer_hparams.ver_minor));
5053 
5054 			vgen_set_vnet_proto_ops(ldcp);
5055 
5056 			/* move to the next phase */
5057 			vgen_handshake(vh_nextphase(ldcp));
5058 		}
5059 		break;
5060 
5061 	case VIO_SUBTYPE_NACK:
5062 
5063 		if (ldcp->hphase != VH_PHASE1) {
5064 			/*  This should not happen.  */
5065 			DWARN(vgenp, ldcp, "VER_NACK_RCVD Invalid "
5066 			"Phase(%u)\n", ldcp->hphase);
5067 			return (VGEN_FAILURE);
5068 		}
5069 
5070 		DBG2(vgenp, ldcp, "VER_NACK_RCVD next ver(%d,%d)\n",
5071 		    vermsg->ver_major, vermsg->ver_minor);
5072 
5073 		/* check if version in NACK is zero */
5074 		if (vermsg->ver_major == 0 && vermsg->ver_minor == 0) {
5075 			/*
5076 			 * Version Negotiation has failed.
5077 			 */
5078 			DWARN(vgenp, ldcp, "Version Negotiation Failed\n");
5079 			return (VGEN_FAILURE);
5080 		}
5081 
5082 		idx = 0;
5083 
5084 		for (;;) {
5085 
5086 			if (vermsg->ver_major > versions[idx].ver_major) {
5087 				/* select next lower version */
5088 
5089 				ldcp->local_hparams.ver_major =
5090 				    versions[idx].ver_major;
5091 				ldcp->local_hparams.ver_minor =
5092 				    versions[idx].ver_minor;
5093 				break;
5094 			}
5095 
5096 			if (vermsg->ver_major == versions[idx].ver_major) {
5097 				/* major version match */
5098 
5099 				ldcp->local_hparams.ver_major =
5100 				    versions[idx].ver_major;
5101 
5102 				ldcp->local_hparams.ver_minor =
5103 				    versions[idx].ver_minor;
5104 				break;
5105 			}
5106 
5107 			idx++;
5108 
5109 			if (idx == VGEN_NUM_VER) {
5110 				/*
5111 				 * no version match.
5112 				 * Version Negotiation has failed.
5113 				 */
5114 				DWARN(vgenp, ldcp,
5115 				    "Version Negotiation Failed\n");
5116 				return (VGEN_FAILURE);
5117 			}
5118 
5119 		}
5120 
5121 		rv = vgen_send_version_negotiate(ldcp);
5122 		if (rv != VGEN_SUCCESS) {
5123 			return (rv);
5124 		}
5125 
5126 		break;
5127 	}
5128 
5129 	DBG1(vgenp, ldcp, "exit\n");
5130 	return (VGEN_SUCCESS);
5131 }
5132 
5133 /* Check if the attributes are supported */
5134 static int
5135 vgen_check_attr_info(vgen_ldc_t *ldcp, vnet_attr_msg_t *msg)
5136 {
5137 	vgen_hparams_t	*lp = &ldcp->local_hparams;
5138 
5139 	if ((msg->addr_type != ADDR_TYPE_MAC) ||
5140 	    (msg->ack_freq > 64) ||
5141 	    (msg->xfer_mode != lp->xfer_mode)) {
5142 		return (VGEN_FAILURE);
5143 	}
5144 
5145 	if (VGEN_VER_LT(ldcp, 1, 4)) {
5146 		/* versions < 1.4, mtu must match */
5147 		if (msg->mtu != lp->mtu) {
5148 			return (VGEN_FAILURE);
5149 		}
5150 	} else {
5151 		/* Ver >= 1.4, validate mtu of the peer is at least ETHERMAX */
5152 		if (msg->mtu < ETHERMAX) {
5153 			return (VGEN_FAILURE);
5154 		}
5155 	}
5156 
5157 	return (VGEN_SUCCESS);
5158 }
5159 
5160 /*
5161  * Handle an attribute info msg from the peer or an ACK/NACK from the peer
5162  * to an attr info msg that we sent.
5163  */
5164 static int
5165 vgen_handle_attr_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
5166 {
5167 	vgen_t		*vgenp = LDC_TO_VGEN(ldcp);
5168 	vnet_attr_msg_t	*msg = (vnet_attr_msg_t *)tagp;
5169 	vgen_hparams_t	*lp = &ldcp->local_hparams;
5170 	vgen_hparams_t	*rp = &ldcp->peer_hparams;
5171 	int		ack = 1;
5172 	int		rv = 0;
5173 	uint32_t	mtu;
5174 
5175 	DBG1(vgenp, ldcp, "enter\n");
5176 	if (ldcp->hphase != VH_PHASE2) {
5177 		DWARN(vgenp, ldcp, "Rcvd ATTR_INFO subtype(%d),"
5178 		" Invalid Phase(%u)\n",
5179 		    tagp->vio_subtype, ldcp->hphase);
5180 		return (VGEN_FAILURE);
5181 	}
5182 	switch (tagp->vio_subtype) {
5183 	case VIO_SUBTYPE_INFO:
5184 
5185 		DBG2(vgenp, ldcp, "ATTR_INFO_RCVD \n");
5186 		ldcp->hstate |= ATTR_INFO_RCVD;
5187 
5188 		/* save peer's values */
5189 		rp->mtu = msg->mtu;
5190 		rp->addr = msg->addr;
5191 		rp->addr_type = msg->addr_type;
5192 		rp->xfer_mode = msg->xfer_mode;
5193 		rp->ack_freq = msg->ack_freq;
5194 
5195 		rv = vgen_check_attr_info(ldcp, msg);
5196 		if (rv == VGEN_FAILURE) {
5197 			/* unsupported attr, send NACK */
5198 			ack = 0;
5199 		} else {
5200 
5201 			if (VGEN_VER_GTEQ(ldcp, 1, 4)) {
5202 
5203 				/*
5204 				 * Versions >= 1.4:
5205 				 * The mtu is negotiated down to the
5206 				 * minimum of our mtu and peer's mtu.
5207 				 */
5208 				mtu = MIN(msg->mtu, vgenp->max_frame_size);
5209 
5210 				/*
5211 				 * If we have received an ack for the attr info
5212 				 * that we sent, then check if the mtu computed
5213 				 * above matches the mtu that the peer had ack'd
5214 				 * (saved in local hparams). If they don't
5215 				 * match, we fail the handshake.
5216 				 */
5217 				if (ldcp->hstate & ATTR_ACK_RCVD) {
5218 					if (mtu != lp->mtu) {
5219 						/* send NACK */
5220 						ack = 0;
5221 					}
5222 				} else {
5223 					/*
5224 					 * Save the mtu computed above in our
5225 					 * attr parameters, so it gets sent in
5226 					 * the attr info from us to the peer.
5227 					 */
5228 					lp->mtu = mtu;
5229 				}
5230 
5231 				/* save the MIN mtu in the msg to be replied */
5232 				msg->mtu = mtu;
5233 
5234 			}
5235 		}
5236 
5237 
5238 		if (ack) {
5239 			tagp->vio_subtype = VIO_SUBTYPE_ACK;
5240 		} else {
5241 			tagp->vio_subtype = VIO_SUBTYPE_NACK;
5242 		}
5243 		tagp->vio_sid = ldcp->local_sid;
5244 
5245 		/* send reply msg back to peer */
5246 		rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*msg),
5247 		    B_FALSE);
5248 		if (rv != VGEN_SUCCESS) {
5249 			return (rv);
5250 		}
5251 
5252 		if (ack) {
5253 			ldcp->hstate |= ATTR_ACK_SENT;
5254 			DBG2(vgenp, ldcp, "ATTR_ACK_SENT \n");
5255 		} else {
5256 			/* failed */
5257 			DWARN(vgenp, ldcp, "ATTR_NACK_SENT \n");
5258 			return (VGEN_FAILURE);
5259 		}
5260 
5261 		if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) {
5262 			vgen_handshake(vh_nextphase(ldcp));
5263 		}
5264 
5265 		break;
5266 
5267 	case VIO_SUBTYPE_ACK:
5268 
5269 		if (VGEN_VER_GTEQ(ldcp, 1, 4)) {
5270 			/*
5271 			 * Versions >= 1.4:
5272 			 * The ack msg sent by the peer contains the minimum of
5273 			 * our mtu (that we had sent in our attr info) and the
5274 			 * peer's mtu.
5275 			 *
5276 			 * If we have sent an ack for the attr info msg from
5277 			 * the peer, check if the mtu that was computed then
5278 			 * (saved in local hparams) matches the mtu that the
5279 			 * peer has ack'd. If they don't match, we fail the
5280 			 * handshake.
5281 			 */
5282 			if (ldcp->hstate & ATTR_ACK_SENT) {
5283 				if (lp->mtu != msg->mtu) {
5284 					return (VGEN_FAILURE);
5285 				}
5286 			} else {
5287 				/*
5288 				 * If the mtu ack'd by the peer is > our mtu
5289 				 * fail handshake. Otherwise, save the mtu, so
5290 				 * we can validate it when we receive attr info
5291 				 * from our peer.
5292 				 */
5293 				if (msg->mtu > lp->mtu) {
5294 					return (VGEN_FAILURE);
5295 				}
5296 				if (msg->mtu <= lp->mtu) {
5297 					lp->mtu = msg->mtu;
5298 				}
5299 			}
5300 		}
5301 
5302 		ldcp->hstate |= ATTR_ACK_RCVD;
5303 
5304 		DBG2(vgenp, ldcp, "ATTR_ACK_RCVD \n");
5305 
5306 		if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) {
5307 			vgen_handshake(vh_nextphase(ldcp));
5308 		}
5309 		break;
5310 
5311 	case VIO_SUBTYPE_NACK:
5312 
5313 		DBG2(vgenp, ldcp, "ATTR_NACK_RCVD \n");
5314 		return (VGEN_FAILURE);
5315 	}
5316 	DBG1(vgenp, ldcp, "exit\n");
5317 	return (VGEN_SUCCESS);
5318 }
5319 
5320 /* Check if the dring info msg is ok */
5321 static int
5322 vgen_check_dring_reg(vio_dring_reg_msg_t *msg)
5323 {
5324 	/* check if msg contents are ok */
5325 	if ((msg->num_descriptors < 128) || (msg->descriptor_size <
5326 	    sizeof (vnet_public_desc_t))) {
5327 		return (VGEN_FAILURE);
5328 	}
5329 	return (VGEN_SUCCESS);
5330 }
5331 
5332 /*
5333  * Handle a descriptor ring register msg from the peer or an ACK/NACK from
5334  * the peer to a dring register msg that we sent.
5335  */
5336 static int
5337 vgen_handle_dring_reg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
5338 {
5339 	vio_dring_reg_msg_t *msg = (vio_dring_reg_msg_t *)tagp;
5340 	ldc_mem_cookie_t dcookie;
5341 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
5342 	int ack = 0;
5343 	int rv = 0;
5344 
5345 	DBG1(vgenp, ldcp, "enter\n");
5346 	if (ldcp->hphase < VH_PHASE2) {
5347 		/* dring_info can be rcvd in any of the phases after Phase1 */
5348 		DWARN(vgenp, ldcp,
5349 		    "Rcvd DRING_INFO Subtype (%d), Invalid Phase(%u)\n",
5350 		    tagp->vio_subtype, ldcp->hphase);
5351 		return (VGEN_FAILURE);
5352 	}
5353 	switch (tagp->vio_subtype) {
5354 	case VIO_SUBTYPE_INFO:
5355 
5356 		DBG2(vgenp, ldcp, "DRING_INFO_RCVD \n");
5357 		ldcp->hstate |= DRING_INFO_RCVD;
5358 		bcopy((msg->cookie), &dcookie, sizeof (dcookie));
5359 
5360 		ASSERT(msg->ncookies == 1);
5361 
5362 		if (vgen_check_dring_reg(msg) == VGEN_SUCCESS) {
5363 			/*
5364 			 * verified dring info msg to be ok,
5365 			 * now try to map the remote dring.
5366 			 */
5367 			rv = vgen_init_rxds(ldcp, msg->num_descriptors,
5368 			    msg->descriptor_size, &dcookie,
5369 			    msg->ncookies);
5370 			if (rv == DDI_SUCCESS) {
5371 				/* now we can ack the peer */
5372 				ack = 1;
5373 			}
5374 		}
5375 		if (ack == 0) {
5376 			/* failed, send NACK */
5377 			tagp->vio_subtype = VIO_SUBTYPE_NACK;
5378 		} else {
5379 			if (!(ldcp->peer_hparams.dring_ready)) {
5380 
5381 				/* save peer's dring_info values */
5382 				bcopy(&dcookie,
5383 				    &(ldcp->peer_hparams.dring_cookie),
5384 				    sizeof (dcookie));
5385 				ldcp->peer_hparams.num_desc =
5386 				    msg->num_descriptors;
5387 				ldcp->peer_hparams.desc_size =
5388 				    msg->descriptor_size;
5389 				ldcp->peer_hparams.num_dcookies =
5390 				    msg->ncookies;
5391 
5392 				/* set dring_ident for the peer */
5393 				ldcp->peer_hparams.dring_ident =
5394 				    (uint64_t)ldcp->rxdp;
5395 				/* return the dring_ident in ack msg */
5396 				msg->dring_ident =
5397 				    (uint64_t)ldcp->rxdp;
5398 
5399 				ldcp->peer_hparams.dring_ready = B_TRUE;
5400 			}
5401 			tagp->vio_subtype = VIO_SUBTYPE_ACK;
5402 		}
5403 		tagp->vio_sid = ldcp->local_sid;
5404 		/* send reply msg back to peer */
5405 		rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*msg),
5406 		    B_FALSE);
5407 		if (rv != VGEN_SUCCESS) {
5408 			return (rv);
5409 		}
5410 
5411 		if (ack) {
5412 			ldcp->hstate |= DRING_ACK_SENT;
5413 			DBG2(vgenp, ldcp, "DRING_ACK_SENT");
5414 		} else {
5415 			DWARN(vgenp, ldcp, "DRING_NACK_SENT");
5416 			return (VGEN_FAILURE);
5417 		}
5418 
5419 		if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) {
5420 			vgen_handshake(vh_nextphase(ldcp));
5421 		}
5422 
5423 		break;
5424 
5425 	case VIO_SUBTYPE_ACK:
5426 
5427 		ldcp->hstate |= DRING_ACK_RCVD;
5428 
5429 		DBG2(vgenp, ldcp, "DRING_ACK_RCVD");
5430 
5431 		if (!(ldcp->local_hparams.dring_ready)) {
5432 			/* local dring is now ready */
5433 			ldcp->local_hparams.dring_ready = B_TRUE;
5434 
5435 			/* save dring_ident acked by peer */
5436 			ldcp->local_hparams.dring_ident =
5437 			    msg->dring_ident;
5438 		}
5439 
5440 		if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) {
5441 			vgen_handshake(vh_nextphase(ldcp));
5442 		}
5443 
5444 		break;
5445 
5446 	case VIO_SUBTYPE_NACK:
5447 
5448 		DBG2(vgenp, ldcp, "DRING_NACK_RCVD");
5449 		return (VGEN_FAILURE);
5450 	}
5451 	DBG1(vgenp, ldcp, "exit\n");
5452 	return (VGEN_SUCCESS);
5453 }
5454 
5455 /*
5456  * Handle a rdx info msg from the peer or an ACK/NACK
5457  * from the peer to a rdx info msg that we sent.
5458  */
5459 static int
5460 vgen_handle_rdx_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
5461 {
5462 	int rv = 0;
5463 	vgen_t	*vgenp = LDC_TO_VGEN(ldcp);
5464 
5465 	DBG1(vgenp, ldcp, "enter\n");
5466 	if (ldcp->hphase != VH_PHASE3) {
5467 		DWARN(vgenp, ldcp,
5468 		    "Rcvd RDX_INFO Subtype (%d), Invalid Phase(%u)\n",
5469 		    tagp->vio_subtype, ldcp->hphase);
5470 		return (VGEN_FAILURE);
5471 	}
5472 	switch (tagp->vio_subtype) {
5473 	case VIO_SUBTYPE_INFO:
5474 
5475 		DBG2(vgenp, ldcp, "RDX_INFO_RCVD \n");
5476 		ldcp->hstate |= RDX_INFO_RCVD;
5477 
5478 		tagp->vio_subtype = VIO_SUBTYPE_ACK;
5479 		tagp->vio_sid = ldcp->local_sid;
5480 		/* send reply msg back to peer */
5481 		rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (vio_rdx_msg_t),
5482 		    B_FALSE);
5483 		if (rv != VGEN_SUCCESS) {
5484 			return (rv);
5485 		}
5486 
5487 		ldcp->hstate |= RDX_ACK_SENT;
5488 		DBG2(vgenp, ldcp, "RDX_ACK_SENT \n");
5489 
5490 		if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) {
5491 			vgen_handshake(vh_nextphase(ldcp));
5492 		}
5493 
5494 		break;
5495 
5496 	case VIO_SUBTYPE_ACK:
5497 
5498 		ldcp->hstate |= RDX_ACK_RCVD;
5499 
5500 		DBG2(vgenp, ldcp, "RDX_ACK_RCVD \n");
5501 
5502 		if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) {
5503 			vgen_handshake(vh_nextphase(ldcp));
5504 		}
5505 		break;
5506 
5507 	case VIO_SUBTYPE_NACK:
5508 
5509 		DBG2(vgenp, ldcp, "RDX_NACK_RCVD \n");
5510 		return (VGEN_FAILURE);
5511 	}
5512 	DBG1(vgenp, ldcp, "exit\n");
5513 	return (VGEN_SUCCESS);
5514 }
5515 
5516 /* Handle ACK/NACK from vsw to a set multicast msg that we sent */
5517 static int
5518 vgen_handle_mcast_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
5519 {
5520 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
5521 	vnet_mcast_msg_t *msgp = (vnet_mcast_msg_t *)tagp;
5522 	struct ether_addr *addrp;
5523 	int count;
5524 	int i;
5525 
5526 	DBG1(vgenp, ldcp, "enter\n");
5527 	switch (tagp->vio_subtype) {
5528 
5529 	case VIO_SUBTYPE_INFO:
5530 
5531 		/* vnet shouldn't recv set mcast msg, only vsw handles it */
5532 		DWARN(vgenp, ldcp, "rcvd SET_MCAST_INFO \n");
5533 		break;
5534 
5535 	case VIO_SUBTYPE_ACK:
5536 
5537 		/* success adding/removing multicast addr */
5538 		DBG1(vgenp, ldcp, "rcvd SET_MCAST_ACK \n");
5539 		break;
5540 
5541 	case VIO_SUBTYPE_NACK:
5542 
5543 		DWARN(vgenp, ldcp, "rcvd SET_MCAST_NACK \n");
5544 		if (!(msgp->set)) {
5545 			/* multicast remove request failed */
5546 			break;
5547 		}
5548 
5549 		/* multicast add request failed */
5550 		for (count = 0; count < msgp->count; count++) {
5551 			addrp = &(msgp->mca[count]);
5552 
5553 			/* delete address from the table */
5554 			for (i = 0; i < vgenp->mccount; i++) {
5555 				if (ether_cmp(addrp,
5556 				    &(vgenp->mctab[i])) == 0) {
5557 					if (vgenp->mccount > 1) {
5558 						int t = vgenp->mccount - 1;
5559 						vgenp->mctab[i] =
5560 						    vgenp->mctab[t];
5561 					}
5562 					vgenp->mccount--;
5563 					break;
5564 				}
5565 			}
5566 		}
5567 		break;
5568 
5569 	}
5570 	DBG1(vgenp, ldcp, "exit\n");
5571 
5572 	return (VGEN_SUCCESS);
5573 }
5574 
5575 /* handler for control messages received from the peer ldc end-point */
5576 static int
5577 vgen_handle_ctrlmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
5578 {
5579 	int rv = 0;
5580 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
5581 
5582 	DBG1(vgenp, ldcp, "enter\n");
5583 	switch (tagp->vio_subtype_env) {
5584 
5585 	case VIO_VER_INFO:
5586 		rv = vgen_handle_version_negotiate(ldcp, tagp);
5587 		break;
5588 
5589 	case VIO_ATTR_INFO:
5590 		rv = vgen_handle_attr_info(ldcp, tagp);
5591 		break;
5592 
5593 	case VIO_DRING_REG:
5594 		rv = vgen_handle_dring_reg(ldcp, tagp);
5595 		break;
5596 
5597 	case VIO_RDX:
5598 		rv = vgen_handle_rdx_info(ldcp, tagp);
5599 		break;
5600 
5601 	case VNET_MCAST_INFO:
5602 		rv = vgen_handle_mcast_info(ldcp, tagp);
5603 		break;
5604 
5605 	case VIO_DDS_INFO:
5606 		rv = vgen_dds_rx(ldcp, tagp);
5607 		break;
5608 	}
5609 
5610 	DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
5611 	return (rv);
5612 }
5613 
5614 /* handler for data messages received from the peer ldc end-point */
5615 static int
5616 vgen_handle_datamsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp, uint32_t msglen)
5617 {
5618 	int rv = 0;
5619 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
5620 
5621 	DBG1(vgenp, ldcp, "enter\n");
5622 
5623 	if (ldcp->hphase != VH_DONE)
5624 		return (rv);
5625 
5626 	if (tagp->vio_subtype == VIO_SUBTYPE_INFO) {
5627 		rv = vgen_check_datamsg_seq(ldcp, tagp);
5628 		if (rv != 0) {
5629 			return (rv);
5630 		}
5631 	}
5632 
5633 	switch (tagp->vio_subtype_env) {
5634 	case VIO_DRING_DATA:
5635 		rv = vgen_handle_dring_data(ldcp, tagp);
5636 		break;
5637 
5638 	case VIO_PKT_DATA:
5639 		ldcp->rx_pktdata((void *)ldcp, (void *)tagp, msglen);
5640 		break;
5641 	default:
5642 		break;
5643 	}
5644 
5645 	DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
5646 	return (rv);
5647 }
5648 
5649 /*
5650  * dummy pkt data handler function for vnet protocol version 1.0
5651  */
5652 static void
5653 vgen_handle_pkt_data_nop(void *arg1, void *arg2, uint32_t msglen)
5654 {
5655 	_NOTE(ARGUNUSED(arg1, arg2, msglen))
5656 }
5657 
5658 /*
5659  * This function handles raw pkt data messages received over the channel.
5660  * Currently, only priority-eth-type frames are received through this mechanism.
5661  * In this case, the frame(data) is present within the message itself which
5662  * is copied into an mblk before sending it up the stack.
5663  */
5664 static void
5665 vgen_handle_pkt_data(void *arg1, void *arg2, uint32_t msglen)
5666 {
5667 	vgen_ldc_t		*ldcp = (vgen_ldc_t *)arg1;
5668 	vio_raw_data_msg_t	*pkt	= (vio_raw_data_msg_t *)arg2;
5669 	uint32_t		size;
5670 	mblk_t			*mp;
5671 	vgen_t			*vgenp = LDC_TO_VGEN(ldcp);
5672 	vgen_stats_t		*statsp = &ldcp->stats;
5673 	vgen_hparams_t		*lp = &ldcp->local_hparams;
5674 	vio_net_rx_cb_t		vrx_cb;
5675 
5676 	ASSERT(MUTEX_HELD(&ldcp->cblock));
5677 
5678 	mutex_exit(&ldcp->cblock);
5679 
5680 	size = msglen - VIO_PKT_DATA_HDRSIZE;
5681 	if (size < ETHERMIN || size > lp->mtu) {
5682 		(void) atomic_inc_32(&statsp->rx_pri_fail);
5683 		goto exit;
5684 	}
5685 
5686 	mp = vio_multipool_allocb(&ldcp->vmp, size);
5687 	if (mp == NULL) {
5688 		mp = allocb(size, BPRI_MED);
5689 		if (mp == NULL) {
5690 			(void) atomic_inc_32(&statsp->rx_pri_fail);
5691 			DWARN(vgenp, ldcp, "allocb failure, "
5692 			    "unable to process priority frame\n");
5693 			goto exit;
5694 		}
5695 	}
5696 
5697 	/* copy the frame from the payload of raw data msg into the mblk */
5698 	bcopy(pkt->data, mp->b_rptr, size);
5699 	mp->b_wptr = mp->b_rptr + size;
5700 
5701 	/* update stats */
5702 	(void) atomic_inc_64(&statsp->rx_pri_packets);
5703 	(void) atomic_add_64(&statsp->rx_pri_bytes, size);
5704 
5705 	/* send up; call vrx_cb() as cblock is already released */
5706 	vrx_cb = ldcp->portp->vcb.vio_net_rx_cb;
5707 	vrx_cb(ldcp->portp->vhp, mp);
5708 
5709 exit:
5710 	mutex_enter(&ldcp->cblock);
5711 }
5712 
5713 static int
5714 vgen_send_dring_ack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp, uint32_t start,
5715     int32_t end, uint8_t pstate)
5716 {
5717 	int rv = 0;
5718 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
5719 	vio_dring_msg_t *msgp = (vio_dring_msg_t *)tagp;
5720 
5721 	tagp->vio_subtype = VIO_SUBTYPE_ACK;
5722 	tagp->vio_sid = ldcp->local_sid;
5723 	msgp->start_idx = start;
5724 	msgp->end_idx = end;
5725 	msgp->dring_process_state = pstate;
5726 	rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*msgp), B_FALSE);
5727 	if (rv != VGEN_SUCCESS) {
5728 		DWARN(vgenp, ldcp, "vgen_sendmsg failed\n");
5729 	}
5730 	return (rv);
5731 }
5732 
5733 static int
5734 vgen_handle_dring_data(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
5735 {
5736 	int rv = 0;
5737 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
5738 
5739 
5740 	DBG1(vgenp, ldcp, "enter\n");
5741 	switch (tagp->vio_subtype) {
5742 
5743 	case VIO_SUBTYPE_INFO:
5744 		/*
5745 		 * To reduce the locking contention, release the
5746 		 * cblock here and re-acquire it once we are done
5747 		 * receiving packets.
5748 		 */
5749 		mutex_exit(&ldcp->cblock);
5750 		mutex_enter(&ldcp->rxlock);
5751 		rv = vgen_handle_dring_data_info(ldcp, tagp);
5752 		mutex_exit(&ldcp->rxlock);
5753 		mutex_enter(&ldcp->cblock);
5754 		break;
5755 
5756 	case VIO_SUBTYPE_ACK:
5757 		rv = vgen_handle_dring_data_ack(ldcp, tagp);
5758 		break;
5759 
5760 	case VIO_SUBTYPE_NACK:
5761 		rv = vgen_handle_dring_data_nack(ldcp, tagp);
5762 		break;
5763 	}
5764 	DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
5765 	return (rv);
5766 }
5767 
5768 static int
5769 vgen_handle_dring_data_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
5770 {
5771 	uint32_t start;
5772 	int32_t end;
5773 	int rv = 0;
5774 	vio_dring_msg_t *dringmsg = (vio_dring_msg_t *)tagp;
5775 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
5776 #ifdef VGEN_HANDLE_LOST_PKTS
5777 	vgen_stats_t *statsp = &ldcp->stats;
5778 	uint32_t rxi;
5779 	int n;
5780 #endif
5781 
5782 	DBG1(vgenp, ldcp, "enter\n");
5783 
5784 	start = dringmsg->start_idx;
5785 	end = dringmsg->end_idx;
5786 	/*
5787 	 * received a data msg, which contains the start and end
5788 	 * indices of the descriptors within the rx ring holding data,
5789 	 * the seq_num of data packet corresponding to the start index,
5790 	 * and the dring_ident.
5791 	 * We can now read the contents of each of these descriptors
5792 	 * and gather data from it.
5793 	 */
5794 	DBG1(vgenp, ldcp, "INFO: start(%d), end(%d)\n",
5795 	    start, end);
5796 
5797 	/* validate rx start and end indeces */
5798 	if (!(CHECK_RXI(start, ldcp)) || ((end != -1) &&
5799 	    !(CHECK_RXI(end, ldcp)))) {
5800 		DWARN(vgenp, ldcp, "Invalid Rx start(%d) or end(%d)\n",
5801 		    start, end);
5802 		/* drop the message if invalid index */
5803 		return (rv);
5804 	}
5805 
5806 	/* validate dring_ident */
5807 	if (dringmsg->dring_ident != ldcp->peer_hparams.dring_ident) {
5808 		DWARN(vgenp, ldcp, "Invalid dring ident 0x%x\n",
5809 		    dringmsg->dring_ident);
5810 		/* invalid dring_ident, drop the msg */
5811 		return (rv);
5812 	}
5813 #ifdef DEBUG
5814 	if (vgen_trigger_rxlost) {
5815 		/* drop this msg to simulate lost pkts for debugging */
5816 		vgen_trigger_rxlost = 0;
5817 		return (rv);
5818 	}
5819 #endif
5820 
5821 #ifdef	VGEN_HANDLE_LOST_PKTS
5822 
5823 	/* receive start index doesn't match expected index */
5824 	if (ldcp->next_rxi != start) {
5825 		DWARN(vgenp, ldcp, "next_rxi(%d) != start(%d)\n",
5826 		    ldcp->next_rxi, start);
5827 
5828 		/* calculate the number of pkts lost */
5829 		if (start >= ldcp->next_rxi) {
5830 			n = start - ldcp->next_rxi;
5831 		} else  {
5832 			n = ldcp->num_rxds - (ldcp->next_rxi - start);
5833 		}
5834 
5835 		statsp->rx_lost_pkts += n;
5836 		tagp->vio_subtype = VIO_SUBTYPE_NACK;
5837 		tagp->vio_sid = ldcp->local_sid;
5838 		/* indicate the range of lost descriptors */
5839 		dringmsg->start_idx = ldcp->next_rxi;
5840 		rxi = start;
5841 		DECR_RXI(rxi, ldcp);
5842 		dringmsg->end_idx = rxi;
5843 		/* dring ident is left unchanged */
5844 		rv = vgen_sendmsg(ldcp, (caddr_t)tagp,
5845 		    sizeof (*dringmsg), B_FALSE);
5846 		if (rv != VGEN_SUCCESS) {
5847 			DWARN(vgenp, ldcp,
5848 			    "vgen_sendmsg failed, stype:NACK\n");
5849 			return (rv);
5850 		}
5851 		/*
5852 		 * treat this range of descrs/pkts as dropped
5853 		 * and set the new expected value of next_rxi
5854 		 * and continue(below) to process from the new
5855 		 * start index.
5856 		 */
5857 		ldcp->next_rxi = start;
5858 	}
5859 
5860 #endif	/* VGEN_HANDLE_LOST_PKTS */
5861 
5862 	/* Now receive messages */
5863 	rv = vgen_process_dring_data(ldcp, tagp);
5864 
5865 	DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
5866 	return (rv);
5867 }
5868 
5869 static int
5870 vgen_process_dring_data(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
5871 {
5872 	boolean_t set_ack_start = B_FALSE;
5873 	uint32_t start;
5874 	uint32_t ack_end;
5875 	uint32_t next_rxi;
5876 	uint32_t rxi;
5877 	int count = 0;
5878 	int rv = 0;
5879 	uint32_t retries = 0;
5880 	vgen_stats_t *statsp;
5881 	vnet_public_desc_t rxd;
5882 	vio_dring_entry_hdr_t *hdrp;
5883 	mblk_t *bp = NULL;
5884 	mblk_t *bpt = NULL;
5885 	uint32_t ack_start;
5886 	boolean_t rxd_err = B_FALSE;
5887 	mblk_t *mp = NULL;
5888 	size_t nbytes;
5889 	boolean_t ack_needed = B_FALSE;
5890 	size_t nread;
5891 	uint64_t off = 0;
5892 	struct ether_header *ehp;
5893 	vio_dring_msg_t *dringmsg = (vio_dring_msg_t *)tagp;
5894 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
5895 	vgen_hparams_t	*lp = &ldcp->local_hparams;
5896 
5897 	DBG1(vgenp, ldcp, "enter\n");
5898 
5899 	statsp = &ldcp->stats;
5900 	start = dringmsg->start_idx;
5901 
5902 	/*
5903 	 * start processing the descriptors from the specified
5904 	 * start index, up to the index a descriptor is not ready
5905 	 * to be processed or we process the entire descriptor ring
5906 	 * and wrap around upto the start index.
5907 	 */
5908 
5909 	/* need to set the start index of descriptors to be ack'd */
5910 	set_ack_start = B_TRUE;
5911 
5912 	/* index upto which we have ack'd */
5913 	ack_end = start;
5914 	DECR_RXI(ack_end, ldcp);
5915 
5916 	next_rxi = rxi =  start;
5917 	do {
5918 vgen_recv_retry:
5919 		rv = vnet_dring_entry_copy(&(ldcp->rxdp[rxi]), &rxd,
5920 		    ldcp->dring_mtype, ldcp->rx_dhandle, rxi, rxi);
5921 		if (rv != 0) {
5922 			DWARN(vgenp, ldcp, "ldc_mem_dring_acquire() failed"
5923 			    " rv(%d)\n", rv);
5924 			statsp->ierrors++;
5925 			return (rv);
5926 		}
5927 
5928 		hdrp = &rxd.hdr;
5929 
5930 		if (hdrp->dstate != VIO_DESC_READY) {
5931 			/*
5932 			 * Before waiting and retry here, send up
5933 			 * the packets that are received already
5934 			 */
5935 			if (bp != NULL) {
5936 				DTRACE_PROBE1(vgen_rcv_msgs, int, count);
5937 				vgen_rx(ldcp, bp);
5938 				count = 0;
5939 				bp = bpt = NULL;
5940 			}
5941 			/*
5942 			 * descriptor is not ready.
5943 			 * retry descriptor acquire, stop processing
5944 			 * after max # retries.
5945 			 */
5946 			if (retries == vgen_recv_retries)
5947 				break;
5948 			retries++;
5949 			drv_usecwait(vgen_recv_delay);
5950 			goto vgen_recv_retry;
5951 		}
5952 		retries = 0;
5953 
5954 		if (set_ack_start) {
5955 			/*
5956 			 * initialize the start index of the range
5957 			 * of descriptors to be ack'd.
5958 			 */
5959 			ack_start = rxi;
5960 			set_ack_start = B_FALSE;
5961 		}
5962 
5963 		if ((rxd.nbytes < ETHERMIN) ||
5964 		    (rxd.nbytes > lp->mtu) ||
5965 		    (rxd.ncookies == 0) ||
5966 		    (rxd.ncookies > MAX_COOKIES)) {
5967 			rxd_err = B_TRUE;
5968 		} else {
5969 			/*
5970 			 * Try to allocate an mblk from the free pool
5971 			 * of recv mblks for the channel.
5972 			 * If this fails, use allocb().
5973 			 */
5974 			nbytes = (VNET_IPALIGN + rxd.nbytes + 7) & ~7;
5975 			if (nbytes > ldcp->max_rxpool_size) {
5976 				mp = allocb(VNET_IPALIGN + rxd.nbytes + 8,
5977 				    BPRI_MED);
5978 			} else {
5979 				mp = vio_multipool_allocb(&ldcp->vmp, nbytes);
5980 				if (mp == NULL) {
5981 					statsp->rx_vio_allocb_fail++;
5982 					/*
5983 					 * Data buffer returned by allocb(9F)
5984 					 * is 8byte aligned. We allocate extra
5985 					 * 8 bytes to ensure size is multiple
5986 					 * of 8 bytes for ldc_mem_copy().
5987 					 */
5988 					mp = allocb(VNET_IPALIGN +
5989 					    rxd.nbytes + 8, BPRI_MED);
5990 				}
5991 			}
5992 		}
5993 		if ((rxd_err) || (mp == NULL)) {
5994 			/*
5995 			 * rxd_err or allocb() failure,
5996 			 * drop this packet, get next.
5997 			 */
5998 			if (rxd_err) {
5999 				statsp->ierrors++;
6000 				rxd_err = B_FALSE;
6001 			} else {
6002 				statsp->rx_allocb_fail++;
6003 			}
6004 
6005 			ack_needed = hdrp->ack;
6006 
6007 			/* set descriptor done bit */
6008 			rv = vnet_dring_entry_set_dstate(&(ldcp->rxdp[rxi]),
6009 			    ldcp->dring_mtype, ldcp->rx_dhandle, rxi, rxi,
6010 			    VIO_DESC_DONE);
6011 			if (rv != 0) {
6012 				DWARN(vgenp, ldcp,
6013 				    "vnet_dring_entry_set_dstate err rv(%d)\n",
6014 				    rv);
6015 				return (rv);
6016 			}
6017 
6018 			if (ack_needed) {
6019 				ack_needed = B_FALSE;
6020 				/*
6021 				 * sender needs ack for this packet,
6022 				 * ack pkts upto this index.
6023 				 */
6024 				ack_end = rxi;
6025 
6026 				rv = vgen_send_dring_ack(ldcp, tagp,
6027 				    ack_start, ack_end,
6028 				    VIO_DP_ACTIVE);
6029 				if (rv != VGEN_SUCCESS) {
6030 					goto error_ret;
6031 				}
6032 
6033 				/* need to set new ack start index */
6034 				set_ack_start = B_TRUE;
6035 			}
6036 			goto vgen_next_rxi;
6037 		}
6038 
6039 		nread = nbytes;
6040 		rv = ldc_mem_copy(ldcp->ldc_handle,
6041 		    (caddr_t)mp->b_rptr, off, &nread,
6042 		    rxd.memcookie, rxd.ncookies, LDC_COPY_IN);
6043 
6044 		/* if ldc_mem_copy() failed */
6045 		if (rv) {
6046 			DWARN(vgenp, ldcp, "ldc_mem_copy err rv(%d)\n", rv);
6047 			statsp->ierrors++;
6048 			freemsg(mp);
6049 			goto error_ret;
6050 		}
6051 
6052 		ack_needed = hdrp->ack;
6053 
6054 		rv = vnet_dring_entry_set_dstate(&(ldcp->rxdp[rxi]),
6055 		    ldcp->dring_mtype, ldcp->rx_dhandle, rxi, rxi,
6056 		    VIO_DESC_DONE);
6057 		if (rv != 0) {
6058 			DWARN(vgenp, ldcp,
6059 			    "vnet_dring_entry_set_dstate err rv(%d)\n", rv);
6060 			goto error_ret;
6061 		}
6062 
6063 		mp->b_rptr += VNET_IPALIGN;
6064 
6065 		if (ack_needed) {
6066 			ack_needed = B_FALSE;
6067 			/*
6068 			 * sender needs ack for this packet,
6069 			 * ack pkts upto this index.
6070 			 */
6071 			ack_end = rxi;
6072 
6073 			rv = vgen_send_dring_ack(ldcp, tagp,
6074 			    ack_start, ack_end, VIO_DP_ACTIVE);
6075 			if (rv != VGEN_SUCCESS) {
6076 				goto error_ret;
6077 			}
6078 
6079 			/* need to set new ack start index */
6080 			set_ack_start = B_TRUE;
6081 		}
6082 
6083 		if (nread != nbytes) {
6084 			DWARN(vgenp, ldcp,
6085 			    "ldc_mem_copy nread(%lx), nbytes(%lx)\n",
6086 			    nread, nbytes);
6087 			statsp->ierrors++;
6088 			freemsg(mp);
6089 			goto vgen_next_rxi;
6090 		}
6091 
6092 		/* point to the actual end of data */
6093 		mp->b_wptr = mp->b_rptr + rxd.nbytes;
6094 
6095 		/* update stats */
6096 		statsp->ipackets++;
6097 		statsp->rbytes += rxd.nbytes;
6098 		ehp = (struct ether_header *)mp->b_rptr;
6099 		if (IS_BROADCAST(ehp))
6100 			statsp->brdcstrcv++;
6101 		else if (IS_MULTICAST(ehp))
6102 			statsp->multircv++;
6103 
6104 		/* build a chain of received packets */
6105 		if (bp == NULL) {
6106 			/* first pkt */
6107 			bp = mp;
6108 			bpt = bp;
6109 			bpt->b_next = NULL;
6110 		} else {
6111 			mp->b_next = NULL;
6112 			bpt->b_next = mp;
6113 			bpt = mp;
6114 		}
6115 
6116 		if (count++ > vgen_chain_len) {
6117 			DTRACE_PROBE1(vgen_rcv_msgs, int, count);
6118 			vgen_rx(ldcp, bp);
6119 			count = 0;
6120 			bp = bpt = NULL;
6121 		}
6122 
6123 vgen_next_rxi:
6124 		/* update end index of range of descrs to be ack'd */
6125 		ack_end = rxi;
6126 
6127 		/* update the next index to be processed */
6128 		INCR_RXI(next_rxi, ldcp);
6129 		if (next_rxi == start) {
6130 			/*
6131 			 * processed the entire descriptor ring upto
6132 			 * the index at which we started.
6133 			 */
6134 			break;
6135 		}
6136 
6137 		rxi = next_rxi;
6138 
6139 	_NOTE(CONSTCOND)
6140 	} while (1);
6141 
6142 	/*
6143 	 * send an ack message to peer indicating that we have stopped
6144 	 * processing descriptors.
6145 	 */
6146 	if (set_ack_start) {
6147 		/*
6148 		 * We have ack'd upto some index and we have not
6149 		 * processed any descriptors beyond that index.
6150 		 * Use the last ack'd index as both the start and
6151 		 * end of range of descrs being ack'd.
6152 		 * Note: This results in acking the last index twice
6153 		 * and should be harmless.
6154 		 */
6155 		ack_start = ack_end;
6156 	}
6157 
6158 	rv = vgen_send_dring_ack(ldcp, tagp, ack_start, ack_end,
6159 	    VIO_DP_STOPPED);
6160 	if (rv != VGEN_SUCCESS) {
6161 		goto error_ret;
6162 	}
6163 
6164 	/* save new recv index of next dring msg */
6165 	ldcp->next_rxi = next_rxi;
6166 
6167 error_ret:
6168 	/* send up packets received so far */
6169 	if (bp != NULL) {
6170 		DTRACE_PROBE1(vgen_rcv_msgs, int, count);
6171 		vgen_rx(ldcp, bp);
6172 		bp = bpt = NULL;
6173 	}
6174 	DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
6175 	return (rv);
6176 
6177 }
6178 
6179 static int
6180 vgen_handle_dring_data_ack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
6181 {
6182 	int rv = 0;
6183 	uint32_t start;
6184 	int32_t end;
6185 	uint32_t txi;
6186 	boolean_t ready_txd = B_FALSE;
6187 	vgen_stats_t *statsp;
6188 	vgen_private_desc_t *tbufp;
6189 	vnet_public_desc_t *txdp;
6190 	vio_dring_entry_hdr_t *hdrp;
6191 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
6192 	vio_dring_msg_t *dringmsg = (vio_dring_msg_t *)tagp;
6193 
6194 	DBG1(vgenp, ldcp, "enter\n");
6195 	start = dringmsg->start_idx;
6196 	end = dringmsg->end_idx;
6197 	statsp = &ldcp->stats;
6198 
6199 	/*
6200 	 * received an ack corresponding to a specific descriptor for
6201 	 * which we had set the ACK bit in the descriptor (during
6202 	 * transmit). This enables us to reclaim descriptors.
6203 	 */
6204 
6205 	DBG2(vgenp, ldcp, "ACK:  start(%d), end(%d)\n", start, end);
6206 
6207 	/* validate start and end indeces in the tx ack msg */
6208 	if (!(CHECK_TXI(start, ldcp)) || !(CHECK_TXI(end, ldcp))) {
6209 		/* drop the message if invalid index */
6210 		DWARN(vgenp, ldcp, "Invalid Tx ack start(%d) or end(%d)\n",
6211 		    start, end);
6212 		return (rv);
6213 	}
6214 	/* validate dring_ident */
6215 	if (dringmsg->dring_ident != ldcp->local_hparams.dring_ident) {
6216 		/* invalid dring_ident, drop the msg */
6217 		DWARN(vgenp, ldcp, "Invalid dring ident 0x%x\n",
6218 		    dringmsg->dring_ident);
6219 		return (rv);
6220 	}
6221 	statsp->dring_data_acks++;
6222 
6223 	/* reclaim descriptors that are done */
6224 	vgen_reclaim(ldcp);
6225 
6226 	if (dringmsg->dring_process_state != VIO_DP_STOPPED) {
6227 		/*
6228 		 * receiver continued processing descriptors after
6229 		 * sending us the ack.
6230 		 */
6231 		return (rv);
6232 	}
6233 
6234 	statsp->dring_stopped_acks++;
6235 
6236 	/* receiver stopped processing descriptors */
6237 	mutex_enter(&ldcp->wrlock);
6238 	mutex_enter(&ldcp->tclock);
6239 
6240 	/*
6241 	 * determine if there are any pending tx descriptors
6242 	 * ready to be processed by the receiver(peer) and if so,
6243 	 * send a message to the peer to restart receiving.
6244 	 */
6245 	ready_txd = B_FALSE;
6246 
6247 	/*
6248 	 * using the end index of the descriptor range for which
6249 	 * we received the ack, check if the next descriptor is
6250 	 * ready.
6251 	 */
6252 	txi = end;
6253 	INCR_TXI(txi, ldcp);
6254 	tbufp = &ldcp->tbufp[txi];
6255 	txdp = tbufp->descp;
6256 	hdrp = &txdp->hdr;
6257 	if (hdrp->dstate == VIO_DESC_READY) {
6258 		ready_txd = B_TRUE;
6259 	} else {
6260 		/*
6261 		 * descr next to the end of ack'd descr range is not
6262 		 * ready.
6263 		 * starting from the current reclaim index, check
6264 		 * if any descriptor is ready.
6265 		 */
6266 
6267 		txi = ldcp->cur_tbufp - ldcp->tbufp;
6268 		tbufp = &ldcp->tbufp[txi];
6269 
6270 		txdp = tbufp->descp;
6271 		hdrp = &txdp->hdr;
6272 		if (hdrp->dstate == VIO_DESC_READY) {
6273 			ready_txd = B_TRUE;
6274 		}
6275 
6276 	}
6277 
6278 	if (ready_txd) {
6279 		/*
6280 		 * we have tx descriptor(s) ready to be
6281 		 * processed by the receiver.
6282 		 * send a message to the peer with the start index
6283 		 * of ready descriptors.
6284 		 */
6285 		rv = vgen_send_dring_data(ldcp, txi, -1);
6286 		if (rv != VGEN_SUCCESS) {
6287 			ldcp->resched_peer = B_TRUE;
6288 			ldcp->resched_peer_txi = txi;
6289 			mutex_exit(&ldcp->tclock);
6290 			mutex_exit(&ldcp->wrlock);
6291 			return (rv);
6292 		}
6293 	} else {
6294 		/*
6295 		 * no ready tx descriptors. set the flag to send a
6296 		 * message to peer when tx descriptors are ready in
6297 		 * transmit routine.
6298 		 */
6299 		ldcp->resched_peer = B_TRUE;
6300 		ldcp->resched_peer_txi = ldcp->cur_tbufp - ldcp->tbufp;
6301 	}
6302 
6303 	mutex_exit(&ldcp->tclock);
6304 	mutex_exit(&ldcp->wrlock);
6305 	DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
6306 	return (rv);
6307 }
6308 
6309 static int
6310 vgen_handle_dring_data_nack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
6311 {
6312 	int rv = 0;
6313 	uint32_t start;
6314 	int32_t end;
6315 	uint32_t txi;
6316 	vnet_public_desc_t *txdp;
6317 	vio_dring_entry_hdr_t *hdrp;
6318 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
6319 	vio_dring_msg_t *dringmsg = (vio_dring_msg_t *)tagp;
6320 
6321 	DBG1(vgenp, ldcp, "enter\n");
6322 	start = dringmsg->start_idx;
6323 	end = dringmsg->end_idx;
6324 
6325 	/*
6326 	 * peer sent a NACK msg to indicate lost packets.
6327 	 * The start and end correspond to the range of descriptors
6328 	 * for which the peer didn't receive a dring data msg and so
6329 	 * didn't receive the corresponding data.
6330 	 */
6331 	DWARN(vgenp, ldcp, "NACK: start(%d), end(%d)\n", start, end);
6332 
6333 	/* validate start and end indeces in the tx nack msg */
6334 	if (!(CHECK_TXI(start, ldcp)) || !(CHECK_TXI(end, ldcp))) {
6335 		/* drop the message if invalid index */
6336 		DWARN(vgenp, ldcp, "Invalid Tx nack start(%d) or end(%d)\n",
6337 		    start, end);
6338 		return (rv);
6339 	}
6340 	/* validate dring_ident */
6341 	if (dringmsg->dring_ident != ldcp->local_hparams.dring_ident) {
6342 		/* invalid dring_ident, drop the msg */
6343 		DWARN(vgenp, ldcp, "Invalid dring ident 0x%x\n",
6344 		    dringmsg->dring_ident);
6345 		return (rv);
6346 	}
6347 	mutex_enter(&ldcp->txlock);
6348 	mutex_enter(&ldcp->tclock);
6349 
6350 	if (ldcp->next_tbufp == ldcp->cur_tbufp) {
6351 		/* no busy descriptors, bogus nack ? */
6352 		mutex_exit(&ldcp->tclock);
6353 		mutex_exit(&ldcp->txlock);
6354 		return (rv);
6355 	}
6356 
6357 	/* we just mark the descrs as done so they can be reclaimed */
6358 	for (txi = start; txi <= end; ) {
6359 		txdp = &(ldcp->txdp[txi]);
6360 		hdrp = &txdp->hdr;
6361 		if (hdrp->dstate == VIO_DESC_READY)
6362 			hdrp->dstate = VIO_DESC_DONE;
6363 		INCR_TXI(txi, ldcp);
6364 	}
6365 	mutex_exit(&ldcp->tclock);
6366 	mutex_exit(&ldcp->txlock);
6367 	DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
6368 	return (rv);
6369 }
6370 
6371 static void
6372 vgen_reclaim(vgen_ldc_t *ldcp)
6373 {
6374 	mutex_enter(&ldcp->tclock);
6375 
6376 	vgen_reclaim_dring(ldcp);
6377 	ldcp->reclaim_lbolt = ddi_get_lbolt();
6378 
6379 	mutex_exit(&ldcp->tclock);
6380 }
6381 
6382 /*
6383  * transmit reclaim function. starting from the current reclaim index
6384  * look for descriptors marked DONE and reclaim the descriptor and the
6385  * corresponding buffers (tbuf).
6386  */
6387 static void
6388 vgen_reclaim_dring(vgen_ldc_t *ldcp)
6389 {
6390 	int count = 0;
6391 	vnet_public_desc_t *txdp;
6392 	vgen_private_desc_t *tbufp;
6393 	vio_dring_entry_hdr_t	*hdrp;
6394 
6395 #ifdef DEBUG
6396 	if (vgen_trigger_txtimeout)
6397 		return;
6398 #endif
6399 
6400 	tbufp = ldcp->cur_tbufp;
6401 	txdp = tbufp->descp;
6402 	hdrp = &txdp->hdr;
6403 
6404 	while ((hdrp->dstate == VIO_DESC_DONE) &&
6405 	    (tbufp != ldcp->next_tbufp)) {
6406 		tbufp->flags = VGEN_PRIV_DESC_FREE;
6407 		hdrp->dstate = VIO_DESC_FREE;
6408 		hdrp->ack = B_FALSE;
6409 
6410 		tbufp = NEXTTBUF(ldcp, tbufp);
6411 		txdp = tbufp->descp;
6412 		hdrp = &txdp->hdr;
6413 		count++;
6414 	}
6415 
6416 	ldcp->cur_tbufp = tbufp;
6417 
6418 	/*
6419 	 * Check if mac layer should be notified to restart transmissions
6420 	 */
6421 	if ((ldcp->need_resched) && (count > 0)) {
6422 		vio_net_tx_update_t vtx_update =
6423 		    ldcp->portp->vcb.vio_net_tx_update;
6424 
6425 		ldcp->need_resched = B_FALSE;
6426 		vtx_update(ldcp->portp->vhp);
6427 	}
6428 }
6429 
6430 /* return the number of pending transmits for the channel */
6431 static int
6432 vgen_num_txpending(vgen_ldc_t *ldcp)
6433 {
6434 	int n;
6435 
6436 	if (ldcp->next_tbufp >= ldcp->cur_tbufp) {
6437 		n = ldcp->next_tbufp - ldcp->cur_tbufp;
6438 	} else  {
6439 		/* cur_tbufp > next_tbufp */
6440 		n = ldcp->num_txds - (ldcp->cur_tbufp - ldcp->next_tbufp);
6441 	}
6442 
6443 	return (n);
6444 }
6445 
6446 /* determine if the transmit descriptor ring is full */
6447 static int
6448 vgen_tx_dring_full(vgen_ldc_t *ldcp)
6449 {
6450 	vgen_private_desc_t	*tbufp;
6451 	vgen_private_desc_t	*ntbufp;
6452 
6453 	tbufp = ldcp->next_tbufp;
6454 	ntbufp = NEXTTBUF(ldcp, tbufp);
6455 	if (ntbufp == ldcp->cur_tbufp) { /* out of tbufs/txds */
6456 		return (VGEN_SUCCESS);
6457 	}
6458 	return (VGEN_FAILURE);
6459 }
6460 
6461 /* determine if timeout condition has occured */
6462 static int
6463 vgen_ldc_txtimeout(vgen_ldc_t *ldcp)
6464 {
6465 	if (((ddi_get_lbolt() - ldcp->reclaim_lbolt) >
6466 	    drv_usectohz(vnet_ldcwd_txtimeout * 1000)) &&
6467 	    (vnet_ldcwd_txtimeout) &&
6468 	    (vgen_tx_dring_full(ldcp) == VGEN_SUCCESS)) {
6469 		return (VGEN_SUCCESS);
6470 	} else {
6471 		return (VGEN_FAILURE);
6472 	}
6473 }
6474 
6475 /* transmit watchdog timeout handler */
6476 static void
6477 vgen_ldc_watchdog(void *arg)
6478 {
6479 	vgen_ldc_t *ldcp;
6480 	vgen_t *vgenp;
6481 	int rv;
6482 
6483 	ldcp = (vgen_ldc_t *)arg;
6484 	vgenp = LDC_TO_VGEN(ldcp);
6485 
6486 	rv = vgen_ldc_txtimeout(ldcp);
6487 	if (rv == VGEN_SUCCESS) {
6488 		DWARN(vgenp, ldcp, "transmit timeout\n");
6489 #ifdef DEBUG
6490 		if (vgen_trigger_txtimeout) {
6491 			/* tx timeout triggered for debugging */
6492 			vgen_trigger_txtimeout = 0;
6493 		}
6494 #endif
6495 		mutex_enter(&ldcp->cblock);
6496 		ldcp->need_ldc_reset = B_TRUE;
6497 		vgen_handshake_retry(ldcp);
6498 		mutex_exit(&ldcp->cblock);
6499 		if (ldcp->need_resched) {
6500 			vio_net_tx_update_t vtx_update =
6501 			    ldcp->portp->vcb.vio_net_tx_update;
6502 
6503 			ldcp->need_resched = B_FALSE;
6504 			vtx_update(ldcp->portp->vhp);
6505 		}
6506 	}
6507 
6508 	ldcp->wd_tid = timeout(vgen_ldc_watchdog, (caddr_t)ldcp,
6509 	    drv_usectohz(vnet_ldcwd_interval * 1000));
6510 }
6511 
6512 /* handler for error messages received from the peer ldc end-point */
6513 static void
6514 vgen_handle_errmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
6515 {
6516 	_NOTE(ARGUNUSED(ldcp, tagp))
6517 }
6518 
6519 static int
6520 vgen_check_datamsg_seq(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
6521 {
6522 	vio_raw_data_msg_t	*rmsg;
6523 	vio_dring_msg_t		*dmsg;
6524 	uint64_t		seq_num;
6525 	vgen_t			*vgenp = LDC_TO_VGEN(ldcp);
6526 
6527 	if (tagp->vio_subtype_env == VIO_DRING_DATA) {
6528 		dmsg = (vio_dring_msg_t *)tagp;
6529 		seq_num = dmsg->seq_num;
6530 	} else if (tagp->vio_subtype_env == VIO_PKT_DATA) {
6531 		rmsg = (vio_raw_data_msg_t *)tagp;
6532 		seq_num = rmsg->seq_num;
6533 	} else {
6534 		return (EINVAL);
6535 	}
6536 
6537 	if (seq_num != ldcp->next_rxseq) {
6538 
6539 		/* seqnums don't match */
6540 		DWARN(vgenp, ldcp,
6541 		    "next_rxseq(0x%lx) != seq_num(0x%lx)\n",
6542 		    ldcp->next_rxseq, seq_num);
6543 
6544 		ldcp->need_ldc_reset = B_TRUE;
6545 		return (EINVAL);
6546 
6547 	}
6548 
6549 	ldcp->next_rxseq++;
6550 
6551 	return (0);
6552 }
6553 
6554 /* Check if the session id in the received message is valid */
6555 static int
6556 vgen_check_sid(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
6557 {
6558 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
6559 
6560 	if (tagp->vio_sid != ldcp->peer_sid) {
6561 		DWARN(vgenp, ldcp, "sid mismatch: expected(%x), rcvd(%x)\n",
6562 		    ldcp->peer_sid, tagp->vio_sid);
6563 		return (VGEN_FAILURE);
6564 	}
6565 	else
6566 		return (VGEN_SUCCESS);
6567 }
6568 
6569 static caddr_t
6570 vgen_print_ethaddr(uint8_t *a, char *ebuf)
6571 {
6572 	(void) sprintf(ebuf,
6573 	    "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]);
6574 	return (ebuf);
6575 }
6576 
6577 /* Handshake watchdog timeout handler */
6578 static void
6579 vgen_hwatchdog(void *arg)
6580 {
6581 	vgen_ldc_t *ldcp = (vgen_ldc_t *)arg;
6582 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
6583 
6584 	DWARN(vgenp, ldcp,
6585 	    "handshake timeout ldc(%lx) phase(%x) state(%x)\n",
6586 	    ldcp->hphase, ldcp->hstate);
6587 
6588 	mutex_enter(&ldcp->cblock);
6589 	if (ldcp->cancel_htid) {
6590 		ldcp->cancel_htid = 0;
6591 		mutex_exit(&ldcp->cblock);
6592 		return;
6593 	}
6594 	ldcp->htid = 0;
6595 	ldcp->need_ldc_reset = B_TRUE;
6596 	vgen_handshake_retry(ldcp);
6597 	mutex_exit(&ldcp->cblock);
6598 }
6599 
6600 static void
6601 vgen_print_hparams(vgen_hparams_t *hp)
6602 {
6603 	uint8_t	addr[6];
6604 	char	ea[6];
6605 	ldc_mem_cookie_t *dc;
6606 
6607 	cmn_err(CE_CONT, "version_info:\n");
6608 	cmn_err(CE_CONT,
6609 	    "\tver_major: %d, ver_minor: %d, dev_class: %d\n",
6610 	    hp->ver_major, hp->ver_minor, hp->dev_class);
6611 
6612 	vnet_macaddr_ultostr(hp->addr, addr);
6613 	cmn_err(CE_CONT, "attr_info:\n");
6614 	cmn_err(CE_CONT, "\tMTU: %lx, addr: %s\n", hp->mtu,
6615 	    vgen_print_ethaddr(addr, ea));
6616 	cmn_err(CE_CONT,
6617 	    "\taddr_type: %x, xfer_mode: %x, ack_freq: %x\n",
6618 	    hp->addr_type, hp->xfer_mode, hp->ack_freq);
6619 
6620 	dc = &hp->dring_cookie;
6621 	cmn_err(CE_CONT, "dring_info:\n");
6622 	cmn_err(CE_CONT,
6623 	    "\tlength: %d, dsize: %d\n", hp->num_desc, hp->desc_size);
6624 	cmn_err(CE_CONT,
6625 	    "\tldc_addr: 0x%lx, ldc_size: %ld\n",
6626 	    dc->addr, dc->size);
6627 	cmn_err(CE_CONT, "\tdring_ident: 0x%lx\n", hp->dring_ident);
6628 }
6629 
6630 static void
6631 vgen_print_ldcinfo(vgen_ldc_t *ldcp)
6632 {
6633 	vgen_hparams_t *hp;
6634 
6635 	cmn_err(CE_CONT, "Channel Information:\n");
6636 	cmn_err(CE_CONT,
6637 	    "\tldc_id: 0x%lx, ldc_status: 0x%x\n",
6638 	    ldcp->ldc_id, ldcp->ldc_status);
6639 	cmn_err(CE_CONT,
6640 	    "\tlocal_sid: 0x%x, peer_sid: 0x%x\n",
6641 	    ldcp->local_sid, ldcp->peer_sid);
6642 	cmn_err(CE_CONT,
6643 	    "\thphase: 0x%x, hstate: 0x%x\n",
6644 	    ldcp->hphase, ldcp->hstate);
6645 
6646 	cmn_err(CE_CONT, "Local handshake params:\n");
6647 	hp = &ldcp->local_hparams;
6648 	vgen_print_hparams(hp);
6649 
6650 	cmn_err(CE_CONT, "Peer handshake params:\n");
6651 	hp = &ldcp->peer_hparams;
6652 	vgen_print_hparams(hp);
6653 }
6654 
6655 /*
6656  * Send received packets up the stack.
6657  */
6658 static void
6659 vgen_rx(vgen_ldc_t *ldcp, mblk_t *bp)
6660 {
6661 	vio_net_rx_cb_t vrx_cb = ldcp->portp->vcb.vio_net_rx_cb;
6662 
6663 	if (ldcp->rcv_thread != NULL) {
6664 		ASSERT(MUTEX_HELD(&ldcp->rxlock));
6665 		mutex_exit(&ldcp->rxlock);
6666 	} else {
6667 		ASSERT(MUTEX_HELD(&ldcp->cblock));
6668 		mutex_exit(&ldcp->cblock);
6669 	}
6670 
6671 	vrx_cb(ldcp->portp->vhp, bp);
6672 
6673 	if (ldcp->rcv_thread != NULL) {
6674 		mutex_enter(&ldcp->rxlock);
6675 	} else {
6676 		mutex_enter(&ldcp->cblock);
6677 	}
6678 }
6679 
6680 /*
6681  * vgen_ldc_rcv_worker -- A per LDC worker thread to receive data.
6682  * This thread is woken up by the LDC interrupt handler to process
6683  * LDC packets and receive data.
6684  */
6685 static void
6686 vgen_ldc_rcv_worker(void *arg)
6687 {
6688 	callb_cpr_t	cprinfo;
6689 	vgen_ldc_t *ldcp = (vgen_ldc_t *)arg;
6690 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
6691 
6692 	DBG1(vgenp, ldcp, "enter\n");
6693 	CALLB_CPR_INIT(&cprinfo, &ldcp->rcv_thr_lock, callb_generic_cpr,
6694 	    "vnet_rcv_thread");
6695 	mutex_enter(&ldcp->rcv_thr_lock);
6696 	while (!(ldcp->rcv_thr_flags & VGEN_WTHR_STOP)) {
6697 
6698 		CALLB_CPR_SAFE_BEGIN(&cprinfo);
6699 		/*
6700 		 * Wait until the data is received or a stop
6701 		 * request is received.
6702 		 */
6703 		while (!(ldcp->rcv_thr_flags &
6704 		    (VGEN_WTHR_DATARCVD | VGEN_WTHR_STOP))) {
6705 			cv_wait(&ldcp->rcv_thr_cv, &ldcp->rcv_thr_lock);
6706 		}
6707 		CALLB_CPR_SAFE_END(&cprinfo, &ldcp->rcv_thr_lock)
6708 
6709 		/*
6710 		 * First process the stop request.
6711 		 */
6712 		if (ldcp->rcv_thr_flags & VGEN_WTHR_STOP) {
6713 			DBG2(vgenp, ldcp, "stopped\n");
6714 			break;
6715 		}
6716 		ldcp->rcv_thr_flags &= ~VGEN_WTHR_DATARCVD;
6717 		ldcp->rcv_thr_flags |= VGEN_WTHR_PROCESSING;
6718 		mutex_exit(&ldcp->rcv_thr_lock);
6719 		DBG2(vgenp, ldcp, "calling vgen_handle_evt_read\n");
6720 		vgen_handle_evt_read(ldcp);
6721 		mutex_enter(&ldcp->rcv_thr_lock);
6722 		ldcp->rcv_thr_flags &= ~VGEN_WTHR_PROCESSING;
6723 	}
6724 
6725 	/*
6726 	 * Update the run status and wakeup the thread that
6727 	 * has sent the stop request.
6728 	 */
6729 	ldcp->rcv_thr_flags &= ~VGEN_WTHR_STOP;
6730 	ldcp->rcv_thread = NULL;
6731 	CALLB_CPR_EXIT(&cprinfo);
6732 
6733 	thread_exit();
6734 	DBG1(vgenp, ldcp, "exit\n");
6735 }
6736 
6737 /* vgen_stop_rcv_thread -- Co-ordinate with receive thread to stop it */
6738 static void
6739 vgen_stop_rcv_thread(vgen_ldc_t *ldcp)
6740 {
6741 	kt_did_t	tid = 0;
6742 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
6743 
6744 	DBG1(vgenp, ldcp, "enter\n");
6745 	/*
6746 	 * Send a stop request by setting the stop flag and
6747 	 * wait until the receive thread stops.
6748 	 */
6749 	mutex_enter(&ldcp->rcv_thr_lock);
6750 	if (ldcp->rcv_thread != NULL) {
6751 		tid = ldcp->rcv_thread->t_did;
6752 		ldcp->rcv_thr_flags |= VGEN_WTHR_STOP;
6753 		cv_signal(&ldcp->rcv_thr_cv);
6754 	}
6755 	mutex_exit(&ldcp->rcv_thr_lock);
6756 
6757 	if (tid != 0) {
6758 		thread_join(tid);
6759 	}
6760 	DBG1(vgenp, ldcp, "exit\n");
6761 }
6762 
6763 /*
6764  * Wait for the channel rx-queue to be drained by allowing the receive
6765  * worker thread to read all messages from the rx-queue of the channel.
6766  * Assumption: further callbacks are disabled at this time.
6767  */
6768 static void
6769 vgen_drain_rcv_thread(vgen_ldc_t *ldcp)
6770 {
6771 	clock_t	tm;
6772 	clock_t	wt;
6773 	clock_t	rv;
6774 
6775 	/*
6776 	 * If there is data in ldc rx queue, wait until the rx
6777 	 * worker thread runs and drains all msgs in the queue.
6778 	 */
6779 	wt = drv_usectohz(MILLISEC);
6780 
6781 	mutex_enter(&ldcp->rcv_thr_lock);
6782 
6783 	tm = ddi_get_lbolt() + wt;
6784 
6785 	/*
6786 	 * We need to check both bits - DATARCVD and PROCESSING, to be cleared.
6787 	 * If DATARCVD is set, that means the callback has signalled the worker
6788 	 * thread, but the worker hasn't started processing yet. If PROCESSING
6789 	 * is set, that means the thread is awake and processing. Note that the
6790 	 * DATARCVD state can only be seen once, as the assumption is that
6791 	 * further callbacks have been disabled at this point.
6792 	 */
6793 	while (ldcp->rcv_thr_flags &
6794 	    (VGEN_WTHR_DATARCVD | VGEN_WTHR_PROCESSING)) {
6795 		rv = cv_timedwait(&ldcp->rcv_thr_cv, &ldcp->rcv_thr_lock, tm);
6796 		if (rv == -1) {	/* timeout */
6797 			/*
6798 			 * Note that the only way we return is due to a timeout;
6799 			 * we set the new time to wait, before we go back and
6800 			 * check the condition. The other(unlikely) possibility
6801 			 * is a premature wakeup(see cv_timedwait(9F)) in which
6802 			 * case we just continue to use the same time to wait.
6803 			 */
6804 			tm = ddi_get_lbolt() + wt;
6805 		}
6806 	}
6807 
6808 	mutex_exit(&ldcp->rcv_thr_lock);
6809 }
6810 
6811 /*
6812  * vgen_dds_rx -- post DDS messages to vnet.
6813  */
6814 static int
6815 vgen_dds_rx(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
6816 {
6817 	vio_dds_msg_t *dmsg = (vio_dds_msg_t *)tagp;
6818 	vgen_t *vgenp = LDC_TO_VGEN(ldcp);
6819 
6820 	if (dmsg->dds_class != DDS_VNET_NIU) {
6821 		DWARN(vgenp, ldcp, "Unknown DDS class, dropping");
6822 		return (EBADMSG);
6823 	}
6824 	vnet_dds_rx(vgenp->vnetp, dmsg);
6825 	return (0);
6826 }
6827 
6828 /*
6829  * vgen_dds_tx -- an interface called by vnet to send DDS messages.
6830  */
6831 int
6832 vgen_dds_tx(void *arg, void *msg)
6833 {
6834 	vgen_t *vgenp = arg;
6835 	vio_dds_msg_t *dmsg = msg;
6836 	vgen_portlist_t *plistp = &vgenp->vgenports;
6837 	vgen_ldc_t *ldcp;
6838 	vgen_ldclist_t *ldclp;
6839 	int rv = EIO;
6840 
6841 
6842 	READ_ENTER(&plistp->rwlock);
6843 	ldclp = &(vgenp->vsw_portp->ldclist);
6844 	READ_ENTER(&ldclp->rwlock);
6845 	ldcp = ldclp->headp;
6846 	if ((ldcp == NULL) || (ldcp->hphase != VH_DONE)) {
6847 		goto vgen_dsend_exit;
6848 	}
6849 
6850 	dmsg->tag.vio_sid = ldcp->local_sid;
6851 	rv = vgen_sendmsg(ldcp, (caddr_t)dmsg, sizeof (vio_dds_msg_t), B_FALSE);
6852 	if (rv != VGEN_SUCCESS) {
6853 		rv = EIO;
6854 	} else {
6855 		rv = 0;
6856 	}
6857 
6858 vgen_dsend_exit:
6859 	RW_EXIT(&ldclp->rwlock);
6860 	RW_EXIT(&plistp->rwlock);
6861 	return (rv);
6862 
6863 }
6864 
6865 #if DEBUG
6866 
6867 /*
6868  * Print debug messages - set to 0xf to enable all msgs
6869  */
6870 static void
6871 debug_printf(const char *fname, vgen_t *vgenp,
6872     vgen_ldc_t *ldcp, const char *fmt, ...)
6873 {
6874 	char    buf[256];
6875 	char    *bufp = buf;
6876 	va_list ap;
6877 
6878 	if ((vgenp != NULL) && (vgenp->vnetp != NULL)) {
6879 		(void) sprintf(bufp, "vnet%d:",
6880 		    ((vnet_t *)(vgenp->vnetp))->instance);
6881 		bufp += strlen(bufp);
6882 	}
6883 	if (ldcp != NULL) {
6884 		(void) sprintf(bufp, "ldc(%ld):", ldcp->ldc_id);
6885 		bufp += strlen(bufp);
6886 	}
6887 	(void) sprintf(bufp, "%s: ", fname);
6888 	bufp += strlen(bufp);
6889 
6890 	va_start(ap, fmt);
6891 	(void) vsprintf(bufp, fmt, ap);
6892 	va_end(ap);
6893 
6894 	if ((ldcp == NULL) ||(vgendbg_ldcid == -1) ||
6895 	    (vgendbg_ldcid == ldcp->ldc_id)) {
6896 		cmn_err(CE_CONT, "%s\n", buf);
6897 	}
6898 }
6899 #endif
6900