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