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