xref: /onnv-gate/usr/src/uts/common/io/ib/clients/eoib/eib_vnic.c (revision 13101:da7b13ec3a28)
1*13101SVenki.Rajagopalan@Sun.COM /*
2*13101SVenki.Rajagopalan@Sun.COM  * CDDL HEADER START
3*13101SVenki.Rajagopalan@Sun.COM  *
4*13101SVenki.Rajagopalan@Sun.COM  * The contents of this file are subject to the terms of the
5*13101SVenki.Rajagopalan@Sun.COM  * Common Development and Distribution License (the "License").
6*13101SVenki.Rajagopalan@Sun.COM  * You may not use this file except in compliance with the License.
7*13101SVenki.Rajagopalan@Sun.COM  *
8*13101SVenki.Rajagopalan@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*13101SVenki.Rajagopalan@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*13101SVenki.Rajagopalan@Sun.COM  * See the License for the specific language governing permissions
11*13101SVenki.Rajagopalan@Sun.COM  * and limitations under the License.
12*13101SVenki.Rajagopalan@Sun.COM  *
13*13101SVenki.Rajagopalan@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*13101SVenki.Rajagopalan@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*13101SVenki.Rajagopalan@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*13101SVenki.Rajagopalan@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*13101SVenki.Rajagopalan@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*13101SVenki.Rajagopalan@Sun.COM  *
19*13101SVenki.Rajagopalan@Sun.COM  * CDDL HEADER END
20*13101SVenki.Rajagopalan@Sun.COM  */
21*13101SVenki.Rajagopalan@Sun.COM 
22*13101SVenki.Rajagopalan@Sun.COM /*
23*13101SVenki.Rajagopalan@Sun.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*13101SVenki.Rajagopalan@Sun.COM  */
25*13101SVenki.Rajagopalan@Sun.COM 
26*13101SVenki.Rajagopalan@Sun.COM #include <sys/types.h>
27*13101SVenki.Rajagopalan@Sun.COM #include <sys/kmem.h>
28*13101SVenki.Rajagopalan@Sun.COM #include <sys/conf.h>
29*13101SVenki.Rajagopalan@Sun.COM #include <sys/ddi.h>
30*13101SVenki.Rajagopalan@Sun.COM #include <sys/sunddi.h>
31*13101SVenki.Rajagopalan@Sun.COM #include <sys/ksynch.h>
32*13101SVenki.Rajagopalan@Sun.COM 
33*13101SVenki.Rajagopalan@Sun.COM #include <sys/ib/clients/eoib/eib_impl.h>
34*13101SVenki.Rajagopalan@Sun.COM 
35*13101SVenki.Rajagopalan@Sun.COM /*
36*13101SVenki.Rajagopalan@Sun.COM  * Declarations private to this file
37*13101SVenki.Rajagopalan@Sun.COM  */
38*13101SVenki.Rajagopalan@Sun.COM static int eib_vnic_get_instance(eib_t *, int *);
39*13101SVenki.Rajagopalan@Sun.COM static void eib_vnic_ret_instance(eib_t *, int);
40*13101SVenki.Rajagopalan@Sun.COM static void eib_vnic_modify_enter(eib_t *, uint_t);
41*13101SVenki.Rajagopalan@Sun.COM static void eib_vnic_modify_exit(eib_t *, uint_t);
42*13101SVenki.Rajagopalan@Sun.COM static int eib_vnic_create_common(eib_t *, eib_vnic_t *, int *);
43*13101SVenki.Rajagopalan@Sun.COM static int eib_vnic_set_partition(eib_t *, eib_vnic_t *, int *);
44*13101SVenki.Rajagopalan@Sun.COM static void eib_vnic_make_vhub_mgid(uint8_t *, uint8_t, uint8_t *, uint8_t,
45*13101SVenki.Rajagopalan@Sun.COM     uint8_t, uint32_t, ib_gid_t *);
46*13101SVenki.Rajagopalan@Sun.COM static int eib_vnic_attach_ctl_mcgs(eib_t *, eib_vnic_t *, int *);
47*13101SVenki.Rajagopalan@Sun.COM static int eib_vnic_attach_vhub_table(eib_t *, eib_vnic_t *);
48*13101SVenki.Rajagopalan@Sun.COM static int eib_vnic_attach_vhub_update(eib_t *, eib_vnic_t *);
49*13101SVenki.Rajagopalan@Sun.COM static void eib_vnic_start_keepalives(eib_t *, eib_vnic_t *);
50*13101SVenki.Rajagopalan@Sun.COM static int eib_vnic_lookup_dest(eib_vnic_t *, uint8_t *, uint16_t,
51*13101SVenki.Rajagopalan@Sun.COM     eib_vhub_map_t *, ibt_mcg_info_t *, int *);
52*13101SVenki.Rajagopalan@Sun.COM static void eib_vnic_leave_all_data_mcgs(eib_t *, eib_vnic_t *);
53*13101SVenki.Rajagopalan@Sun.COM static void eib_vnic_rejoin_data_mcgs(eib_t *, eib_vnic_t *);
54*13101SVenki.Rajagopalan@Sun.COM static void eib_vnic_reattach_ctl_mcgs(eib_t *, eib_vnic_t *);
55*13101SVenki.Rajagopalan@Sun.COM static void eib_rb_vnic_create_common(eib_t *, eib_vnic_t *, uint_t);
56*13101SVenki.Rajagopalan@Sun.COM static void eib_rb_vnic_attach_ctl_mcgs(eib_t *, eib_vnic_t *);
57*13101SVenki.Rajagopalan@Sun.COM static void eib_rb_vnic_attach_vhub_table(eib_t *, eib_vnic_t *);
58*13101SVenki.Rajagopalan@Sun.COM static void eib_rb_vnic_attach_vhub_update(eib_t *, eib_vnic_t *);
59*13101SVenki.Rajagopalan@Sun.COM static void eib_rb_vnic_start_keepalives(eib_t *, eib_vnic_t *);
60*13101SVenki.Rajagopalan@Sun.COM static void eib_rb_vnic_join_data_mcg(eib_t *, eib_vnic_t *, uint8_t *);
61*13101SVenki.Rajagopalan@Sun.COM 
62*13101SVenki.Rajagopalan@Sun.COM /*
63*13101SVenki.Rajagopalan@Sun.COM  * Definitions private to this file
64*13101SVenki.Rajagopalan@Sun.COM  */
65*13101SVenki.Rajagopalan@Sun.COM #define	EIB_VNIC_STRUCT_ALLOCD		0x0001
66*13101SVenki.Rajagopalan@Sun.COM #define	EIB_VNIC_GOT_INSTANCE		0x0002
67*13101SVenki.Rajagopalan@Sun.COM #define	EIB_VNIC_CREATE_COMMON_DONE	0x0004
68*13101SVenki.Rajagopalan@Sun.COM #define	EIB_VNIC_CTLQP_CREATED		0x0008
69*13101SVenki.Rajagopalan@Sun.COM #define	EIB_VNIC_DATAQP_CREATED		0x0010
70*13101SVenki.Rajagopalan@Sun.COM #define	EIB_VNIC_LOGIN_DONE		0x0020
71*13101SVenki.Rajagopalan@Sun.COM #define	EIB_VNIC_PARTITION_SET		0x0040
72*13101SVenki.Rajagopalan@Sun.COM #define	EIB_VNIC_RX_POSTED_TO_CTLQP	0x0080
73*13101SVenki.Rajagopalan@Sun.COM #define	EIB_VNIC_RX_POSTED_TO_DATAQP	0x0100
74*13101SVenki.Rajagopalan@Sun.COM #define	EIB_VNIC_ATTACHED_TO_CTL_MCGS	0x0200
75*13101SVenki.Rajagopalan@Sun.COM #define	EIB_VNIC_GOT_VHUB_TABLE		0x0400
76*13101SVenki.Rajagopalan@Sun.COM #define	EIB_VNIC_KEEPALIVES_STARTED	0x0800
77*13101SVenki.Rajagopalan@Sun.COM #define	EIB_VNIC_BROADCAST_JOINED	0x1000
78*13101SVenki.Rajagopalan@Sun.COM 
79*13101SVenki.Rajagopalan@Sun.COM /*
80*13101SVenki.Rajagopalan@Sun.COM  * Destination type
81*13101SVenki.Rajagopalan@Sun.COM  */
82*13101SVenki.Rajagopalan@Sun.COM #define	EIB_TX_UNICAST			1
83*13101SVenki.Rajagopalan@Sun.COM #define	EIB_TX_MULTICAST		2
84*13101SVenki.Rajagopalan@Sun.COM #define	EIB_TX_BROADCAST		3
85*13101SVenki.Rajagopalan@Sun.COM 
86*13101SVenki.Rajagopalan@Sun.COM int
eib_vnic_create(eib_t * ss,uint8_t * macaddr,uint16_t vlan,eib_vnic_t ** vnicp,int * err)87*13101SVenki.Rajagopalan@Sun.COM eib_vnic_create(eib_t *ss, uint8_t *macaddr, uint16_t vlan, eib_vnic_t **vnicp,
88*13101SVenki.Rajagopalan@Sun.COM     int *err)
89*13101SVenki.Rajagopalan@Sun.COM {
90*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_t *vnic = NULL;
91*13101SVenki.Rajagopalan@Sun.COM 	boolean_t failed_vnic = B_FALSE;
92*13101SVenki.Rajagopalan@Sun.COM 	uint_t progress = 0;
93*13101SVenki.Rajagopalan@Sun.COM 
94*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_modify_enter(ss, EIB_VN_BEING_CREATED);
95*13101SVenki.Rajagopalan@Sun.COM 
96*13101SVenki.Rajagopalan@Sun.COM 	/*
97*13101SVenki.Rajagopalan@Sun.COM 	 * When a previously created vnic is being resurrected due to a
98*13101SVenki.Rajagopalan@Sun.COM 	 * gateway reboot, there's a race possible where a creation request
99*13101SVenki.Rajagopalan@Sun.COM 	 * for the existing vnic could get filed with the vnic creator
100*13101SVenki.Rajagopalan@Sun.COM 	 * thread. So, before we go ahead with the creation of this vnic,
101*13101SVenki.Rajagopalan@Sun.COM 	 * make sure we already don't have the vnic.
102*13101SVenki.Rajagopalan@Sun.COM 	 */
103*13101SVenki.Rajagopalan@Sun.COM 	if (macaddr) {
104*13101SVenki.Rajagopalan@Sun.COM 		if (eib_data_lookup_vnic(ss, macaddr, vlan, vnicp,
105*13101SVenki.Rajagopalan@Sun.COM 		    &failed_vnic) == EIB_E_SUCCESS) {
106*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance, "eib_vnic_create: "
107*13101SVenki.Rajagopalan@Sun.COM 			    "vnic for mac=%x:%x:%x:%x:%x:%x, vlan=0x%x "
108*13101SVenki.Rajagopalan@Sun.COM 			    "already there, no duplicate creation", macaddr[0],
109*13101SVenki.Rajagopalan@Sun.COM 			    macaddr[1], macaddr[2], macaddr[3], macaddr[4],
110*13101SVenki.Rajagopalan@Sun.COM 			    macaddr[5], vlan);
111*13101SVenki.Rajagopalan@Sun.COM 
112*13101SVenki.Rajagopalan@Sun.COM 			eib_vnic_modify_exit(ss, EIB_VN_BEING_CREATED);
113*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_SUCCESS);
114*13101SVenki.Rajagopalan@Sun.COM 		} else if (failed_vnic) {
115*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance, "eib_vnic_create: "
116*13101SVenki.Rajagopalan@Sun.COM 			    "vnic for mac=%x:%x:%x:%x:%x:%x, vlan=0x%x "
117*13101SVenki.Rajagopalan@Sun.COM 			    "failed earlier, shouldn't be here at all",
118*13101SVenki.Rajagopalan@Sun.COM 			    macaddr[0], macaddr[1], macaddr[2], macaddr[3],
119*13101SVenki.Rajagopalan@Sun.COM 			    macaddr[4], macaddr[5], vlan);
120*13101SVenki.Rajagopalan@Sun.COM 
121*13101SVenki.Rajagopalan@Sun.COM 			*err = EEXIST;
122*13101SVenki.Rajagopalan@Sun.COM 
123*13101SVenki.Rajagopalan@Sun.COM 			eib_vnic_modify_exit(ss, EIB_VN_BEING_CREATED);
124*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_FAILURE);
125*13101SVenki.Rajagopalan@Sun.COM 		}
126*13101SVenki.Rajagopalan@Sun.COM 	}
127*13101SVenki.Rajagopalan@Sun.COM 
128*13101SVenki.Rajagopalan@Sun.COM 	/*
129*13101SVenki.Rajagopalan@Sun.COM 	 * Allocate a vnic structure for this instance
130*13101SVenki.Rajagopalan@Sun.COM 	 */
131*13101SVenki.Rajagopalan@Sun.COM 	vnic = kmem_zalloc(sizeof (eib_vnic_t), KM_SLEEP);
132*13101SVenki.Rajagopalan@Sun.COM 	vnic->vn_ss = ss;
133*13101SVenki.Rajagopalan@Sun.COM 	vnic->vn_instance = -1;
134*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&vnic->vn_lock, NULL, MUTEX_DRIVER, NULL);
135*13101SVenki.Rajagopalan@Sun.COM 	cv_init(&vnic->vn_cv, NULL, CV_DEFAULT, NULL);
136*13101SVenki.Rajagopalan@Sun.COM 
137*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_VNIC_STRUCT_ALLOCD;
138*13101SVenki.Rajagopalan@Sun.COM 
139*13101SVenki.Rajagopalan@Sun.COM 	/*
140*13101SVenki.Rajagopalan@Sun.COM 	 * Get a vnic instance
141*13101SVenki.Rajagopalan@Sun.COM 	 */
142*13101SVenki.Rajagopalan@Sun.COM 	if (eib_vnic_get_instance(ss, &vnic->vn_instance) != EIB_E_SUCCESS) {
143*13101SVenki.Rajagopalan@Sun.COM 		*err = EMFILE;
144*13101SVenki.Rajagopalan@Sun.COM 		goto vnic_create_fail;
145*13101SVenki.Rajagopalan@Sun.COM 	}
146*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_VNIC_GOT_INSTANCE;
147*13101SVenki.Rajagopalan@Sun.COM 
148*13101SVenki.Rajagopalan@Sun.COM 	/*
149*13101SVenki.Rajagopalan@Sun.COM 	 * Initialize vnic's basic parameters.  Note that we set the 15-bit
150*13101SVenki.Rajagopalan@Sun.COM 	 * vnic id to send to gw during a login to be a 2-tuple of
151*13101SVenki.Rajagopalan@Sun.COM 	 * {devi_instance#, eoib_vnic_instance#}.
152*13101SVenki.Rajagopalan@Sun.COM 	 */
153*13101SVenki.Rajagopalan@Sun.COM 	vnic->vn_vlan = vlan;
154*13101SVenki.Rajagopalan@Sun.COM 	if (macaddr) {
155*13101SVenki.Rajagopalan@Sun.COM 		bcopy(macaddr, vnic->vn_macaddr, sizeof (vnic->vn_macaddr));
156*13101SVenki.Rajagopalan@Sun.COM 	}
157*13101SVenki.Rajagopalan@Sun.COM 	vnic->vn_id = (uint16_t)EIB_VNIC_ID(ss->ei_instance, vnic->vn_instance);
158*13101SVenki.Rajagopalan@Sun.COM 
159*13101SVenki.Rajagopalan@Sun.COM 	/*
160*13101SVenki.Rajagopalan@Sun.COM 	 * Start up this vnic instance
161*13101SVenki.Rajagopalan@Sun.COM 	 */
162*13101SVenki.Rajagopalan@Sun.COM 	if (eib_vnic_create_common(ss, vnic, err) != EIB_E_SUCCESS)
163*13101SVenki.Rajagopalan@Sun.COM 		goto vnic_create_fail;
164*13101SVenki.Rajagopalan@Sun.COM 
165*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_VNIC_CREATE_COMMON_DONE;
166*13101SVenki.Rajagopalan@Sun.COM 
167*13101SVenki.Rajagopalan@Sun.COM 	/*
168*13101SVenki.Rajagopalan@Sun.COM 	 * Return the created vnic
169*13101SVenki.Rajagopalan@Sun.COM 	 */
170*13101SVenki.Rajagopalan@Sun.COM 	if (vnicp) {
171*13101SVenki.Rajagopalan@Sun.COM 		*vnicp = vnic;
172*13101SVenki.Rajagopalan@Sun.COM 	}
173*13101SVenki.Rajagopalan@Sun.COM 
174*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_modify_exit(ss, EIB_VN_BEING_CREATED);
175*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
176*13101SVenki.Rajagopalan@Sun.COM 
177*13101SVenki.Rajagopalan@Sun.COM vnic_create_fail:
178*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_vnic_create(ss, vnic, progress);
179*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_modify_exit(ss, EIB_VN_BEING_CREATED);
180*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_FAILURE);
181*13101SVenki.Rajagopalan@Sun.COM }
182*13101SVenki.Rajagopalan@Sun.COM 
183*13101SVenki.Rajagopalan@Sun.COM void
eib_vnic_delete(eib_t * ss,eib_vnic_t * vnic)184*13101SVenki.Rajagopalan@Sun.COM eib_vnic_delete(eib_t *ss, eib_vnic_t *vnic)
185*13101SVenki.Rajagopalan@Sun.COM {
186*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_modify_enter(ss, EIB_VN_BEING_DELETED);
187*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_vnic_create(ss, vnic, ~0);
188*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_modify_exit(ss, EIB_VN_BEING_DELETED);
189*13101SVenki.Rajagopalan@Sun.COM }
190*13101SVenki.Rajagopalan@Sun.COM 
191*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
192*13101SVenki.Rajagopalan@Sun.COM int
eib_vnic_wait_for_login_ack(eib_t * ss,eib_vnic_t * vnic,int * err)193*13101SVenki.Rajagopalan@Sun.COM eib_vnic_wait_for_login_ack(eib_t *ss, eib_vnic_t *vnic, int *err)
194*13101SVenki.Rajagopalan@Sun.COM {
195*13101SVenki.Rajagopalan@Sun.COM 	clock_t deadline;
196*13101SVenki.Rajagopalan@Sun.COM 	int ret = EIB_E_SUCCESS;
197*13101SVenki.Rajagopalan@Sun.COM 
198*13101SVenki.Rajagopalan@Sun.COM 	deadline = ddi_get_lbolt() + drv_usectohz(EIB_LOGIN_TIMEOUT_USEC);
199*13101SVenki.Rajagopalan@Sun.COM 
200*13101SVenki.Rajagopalan@Sun.COM 	/*
201*13101SVenki.Rajagopalan@Sun.COM 	 * Wait for login ack/nack or wait time to get over. If we wake up
202*13101SVenki.Rajagopalan@Sun.COM 	 * with a login failure, record the reason.
203*13101SVenki.Rajagopalan@Sun.COM 	 */
204*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&vnic->vn_lock);
205*13101SVenki.Rajagopalan@Sun.COM 	while (vnic->vn_state == EIB_LOGIN_ACK_WAIT) {
206*13101SVenki.Rajagopalan@Sun.COM 		if (cv_timedwait(&vnic->vn_cv, &vnic->vn_lock,
207*13101SVenki.Rajagopalan@Sun.COM 		    deadline) == -1) {
208*13101SVenki.Rajagopalan@Sun.COM 			if (vnic->vn_state == EIB_LOGIN_ACK_WAIT)
209*13101SVenki.Rajagopalan@Sun.COM 				vnic->vn_state = EIB_LOGIN_TIMED_OUT;
210*13101SVenki.Rajagopalan@Sun.COM 		}
211*13101SVenki.Rajagopalan@Sun.COM 	}
212*13101SVenki.Rajagopalan@Sun.COM 
213*13101SVenki.Rajagopalan@Sun.COM 	if (vnic->vn_state != EIB_LOGIN_ACK_RCVD) {
214*13101SVenki.Rajagopalan@Sun.COM 		ret = EIB_E_FAILURE;
215*13101SVenki.Rajagopalan@Sun.COM 		*err =  (vnic->vn_state == EIB_LOGIN_TIMED_OUT) ?
216*13101SVenki.Rajagopalan@Sun.COM 		    ETIME : ECANCELED;
217*13101SVenki.Rajagopalan@Sun.COM 	}
218*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&vnic->vn_lock);
219*13101SVenki.Rajagopalan@Sun.COM 
220*13101SVenki.Rajagopalan@Sun.COM 	return (ret);
221*13101SVenki.Rajagopalan@Sun.COM }
222*13101SVenki.Rajagopalan@Sun.COM 
223*13101SVenki.Rajagopalan@Sun.COM void
eib_vnic_login_ack(eib_t * ss,eib_login_data_t * ld)224*13101SVenki.Rajagopalan@Sun.COM eib_vnic_login_ack(eib_t *ss, eib_login_data_t *ld)
225*13101SVenki.Rajagopalan@Sun.COM {
226*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_t *vnic;
227*13101SVenki.Rajagopalan@Sun.COM 	uint_t vnic_instance;
228*13101SVenki.Rajagopalan@Sun.COM 	uint_t hdrs_sz;
229*13101SVenki.Rajagopalan@Sun.COM 	uint16_t vnic_id;
230*13101SVenki.Rajagopalan@Sun.COM 	int nack = 1;
231*13101SVenki.Rajagopalan@Sun.COM 
232*13101SVenki.Rajagopalan@Sun.COM 	/*
233*13101SVenki.Rajagopalan@Sun.COM 	 * The msb in the vnic id in login ack message is not
234*13101SVenki.Rajagopalan@Sun.COM 	 * part of our vNIC id.
235*13101SVenki.Rajagopalan@Sun.COM 	 */
236*13101SVenki.Rajagopalan@Sun.COM 	vnic_id = ld->ld_vnic_id & (~FIP_VL_VNIC_ID_MSBIT);
237*13101SVenki.Rajagopalan@Sun.COM 
238*13101SVenki.Rajagopalan@Sun.COM 	/*
239*13101SVenki.Rajagopalan@Sun.COM 	 * Now, we deconstruct the vnic id and determine the vnic
240*13101SVenki.Rajagopalan@Sun.COM 	 * instance number. If this vnic_instance number isn't
241*13101SVenki.Rajagopalan@Sun.COM 	 * valid or the vnic_id of the vnic for this instance
242*13101SVenki.Rajagopalan@Sun.COM 	 * number doesn't match in our records, we quit.
243*13101SVenki.Rajagopalan@Sun.COM 	 */
244*13101SVenki.Rajagopalan@Sun.COM 	vnic_instance = EIB_VNIC_INSTANCE(vnic_id);
245*13101SVenki.Rajagopalan@Sun.COM 	if (vnic_instance >= EIB_MAX_VNICS)
246*13101SVenki.Rajagopalan@Sun.COM 		return;
247*13101SVenki.Rajagopalan@Sun.COM 
248*13101SVenki.Rajagopalan@Sun.COM 	/*
249*13101SVenki.Rajagopalan@Sun.COM 	 * At this point, we haven't fully created the vnic, so
250*13101SVenki.Rajagopalan@Sun.COM 	 * this vnic should be present as ei_vnic_pending.
251*13101SVenki.Rajagopalan@Sun.COM 	 */
252*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_vnic_lock);
253*13101SVenki.Rajagopalan@Sun.COM 	if ((vnic = ss->ei_vnic_pending) == NULL) {
254*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ss->ei_vnic_lock);
255*13101SVenki.Rajagopalan@Sun.COM 		return;
256*13101SVenki.Rajagopalan@Sun.COM 	} else if (vnic->vn_id != vnic_id) {
257*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ss->ei_vnic_lock);
258*13101SVenki.Rajagopalan@Sun.COM 		return;
259*13101SVenki.Rajagopalan@Sun.COM 	}
260*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_vnic_lock);
261*13101SVenki.Rajagopalan@Sun.COM 
262*13101SVenki.Rajagopalan@Sun.COM 	/*
263*13101SVenki.Rajagopalan@Sun.COM 	 * First check if the vnic is still sleeping, waiting
264*13101SVenki.Rajagopalan@Sun.COM 	 * for login ack.  If not, we might as well quit now.
265*13101SVenki.Rajagopalan@Sun.COM 	 */
266*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&vnic->vn_lock);
267*13101SVenki.Rajagopalan@Sun.COM 	if (vnic->vn_state != EIB_LOGIN_ACK_WAIT) {
268*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&vnic->vn_lock);
269*13101SVenki.Rajagopalan@Sun.COM 		return;
270*13101SVenki.Rajagopalan@Sun.COM 	}
271*13101SVenki.Rajagopalan@Sun.COM 
272*13101SVenki.Rajagopalan@Sun.COM 	/*
273*13101SVenki.Rajagopalan@Sun.COM 	 * We NACK the waiter under these conditions:
274*13101SVenki.Rajagopalan@Sun.COM 	 *
275*13101SVenki.Rajagopalan@Sun.COM 	 * . syndrome was set
276*13101SVenki.Rajagopalan@Sun.COM 	 * . vhub mtu is bigger than our max mtu (minus eoib/eth hdrs sz)
277*13101SVenki.Rajagopalan@Sun.COM 	 * . assigned vlan is different from requested vlan (except
278*13101SVenki.Rajagopalan@Sun.COM 	 *   when we didn't request a specific vlan)
279*13101SVenki.Rajagopalan@Sun.COM 	 * . when the assigned mac is different from the requested mac
280*13101SVenki.Rajagopalan@Sun.COM 	 *   (except when we didn't request a specific mac)
281*13101SVenki.Rajagopalan@Sun.COM 	 * . when the VP bit indicates that vlan tag should be used
282*13101SVenki.Rajagopalan@Sun.COM 	 *   but we had not specified a vlan tag in our request
283*13101SVenki.Rajagopalan@Sun.COM 	 * . when the VP bit indicates that vlan tag should not be
284*13101SVenki.Rajagopalan@Sun.COM 	 *   present and we'd specified a vlan tag in our request
285*13101SVenki.Rajagopalan@Sun.COM 	 *
286*13101SVenki.Rajagopalan@Sun.COM 	 * The last case is interesting: if we had not specified any vlan id
287*13101SVenki.Rajagopalan@Sun.COM 	 * in our request, but the gateway has assigned a vlan and asks us
288*13101SVenki.Rajagopalan@Sun.COM 	 * to use/expect that tag on every packet dealt by this vnic, it
289*13101SVenki.Rajagopalan@Sun.COM 	 * means effectively the EoIB driver has to insert/remove vlan
290*13101SVenki.Rajagopalan@Sun.COM 	 * tagging on this vnic traffic, since the nw layer on Solaris
291*13101SVenki.Rajagopalan@Sun.COM 	 * won't be using/expecting any tag on traffic for this vnic. This
292*13101SVenki.Rajagopalan@Sun.COM 	 * feature is not supported currently.
293*13101SVenki.Rajagopalan@Sun.COM 	 */
294*13101SVenki.Rajagopalan@Sun.COM 	hdrs_sz = EIB_ENCAP_HDR_SZ + sizeof (struct ether_header) + VLAN_TAGSZ;
295*13101SVenki.Rajagopalan@Sun.COM 	if (ld->ld_syndrome) {
296*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_vnic_login_ack: "
297*13101SVenki.Rajagopalan@Sun.COM 		    "non-zero syndrome 0x%lx, NACK", ld->ld_syndrome);
298*13101SVenki.Rajagopalan@Sun.COM 
299*13101SVenki.Rajagopalan@Sun.COM 	} else if (ld->ld_vhub_mtu > (ss->ei_props->ep_mtu - hdrs_sz)) {
300*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_vnic_login_ack: "
301*13101SVenki.Rajagopalan@Sun.COM 		    "vhub mtu (0x%x) bigger than port mtu (0x%x), NACK",
302*13101SVenki.Rajagopalan@Sun.COM 		    ld->ld_vhub_mtu, ss->ei_props->ep_mtu);
303*13101SVenki.Rajagopalan@Sun.COM 
304*13101SVenki.Rajagopalan@Sun.COM 	} else if ((vnic->vn_vlan) && (vnic->vn_vlan != ld->ld_assigned_vlan)) {
305*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_vnic_login_ack: "
306*13101SVenki.Rajagopalan@Sun.COM 		    "assigned vlan (0x%x) different from asked (0x%x), "
307*13101SVenki.Rajagopalan@Sun.COM 		    "for vnic id 0x%x, NACK", ld->ld_assigned_vlan,
308*13101SVenki.Rajagopalan@Sun.COM 		    vnic->vn_vlan, vnic->vn_id);
309*13101SVenki.Rajagopalan@Sun.COM 
310*13101SVenki.Rajagopalan@Sun.COM 	} else if (bcmp(vnic->vn_macaddr, eib_zero_mac, ETHERADDRL) &&
311*13101SVenki.Rajagopalan@Sun.COM 	    bcmp(vnic->vn_macaddr, ld->ld_assigned_mac, ETHERADDRL)) {
312*13101SVenki.Rajagopalan@Sun.COM 		uint8_t *asked, *got;
313*13101SVenki.Rajagopalan@Sun.COM 
314*13101SVenki.Rajagopalan@Sun.COM 		asked = vnic->vn_macaddr;
315*13101SVenki.Rajagopalan@Sun.COM 		got = ld->ld_assigned_mac;
316*13101SVenki.Rajagopalan@Sun.COM 
317*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_vnic_login_ack: "
318*13101SVenki.Rajagopalan@Sun.COM 		    "assigned mac (%x:%x:%x:%x:%x:%x) different from "
319*13101SVenki.Rajagopalan@Sun.COM 		    "asked (%x:%x:%x:%x:%x:%x) for vnic id 0x%x, NACK",
320*13101SVenki.Rajagopalan@Sun.COM 		    got[0], got[1], got[2], got[3], got[4], got[5], asked[0],
321*13101SVenki.Rajagopalan@Sun.COM 		    asked[1], asked[2], asked[3], asked[4], asked[5]);
322*13101SVenki.Rajagopalan@Sun.COM 
323*13101SVenki.Rajagopalan@Sun.COM 	} else if ((vnic->vn_vlan == 0) && (ld->ld_vlan_in_packets)) {
324*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_vnic_login_ack: "
325*13101SVenki.Rajagopalan@Sun.COM 		    "asked for tagless vlan, but VP flag is set "
326*13101SVenki.Rajagopalan@Sun.COM 		    "for vnic id 0x%x, NACK", vnic->vn_id);
327*13101SVenki.Rajagopalan@Sun.COM 
328*13101SVenki.Rajagopalan@Sun.COM 	} else if ((vnic->vn_vlan) && (!ld->ld_vlan_in_packets)) {
329*13101SVenki.Rajagopalan@Sun.COM 		if (eib_wa_no_good_vp_flag) {
330*13101SVenki.Rajagopalan@Sun.COM 			ld->ld_vlan_in_packets = 1;
331*13101SVenki.Rajagopalan@Sun.COM 			ld->ld_vhub_id = EIB_VHUB_ID(ld->ld_gw_port_id,
332*13101SVenki.Rajagopalan@Sun.COM 			    ld->ld_assigned_vlan);
333*13101SVenki.Rajagopalan@Sun.COM 			nack = 0;
334*13101SVenki.Rajagopalan@Sun.COM 		} else {
335*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance, "eib_vnic_login_ack: "
336*13101SVenki.Rajagopalan@Sun.COM 			    "vlan was assigned correctly, but VP flag is not "
337*13101SVenki.Rajagopalan@Sun.COM 			    "set for vnic id 0x%x, NACK", vnic->vn_id);
338*13101SVenki.Rajagopalan@Sun.COM 		}
339*13101SVenki.Rajagopalan@Sun.COM 	} else {
340*13101SVenki.Rajagopalan@Sun.COM 		ld->ld_vhub_id = EIB_VHUB_ID(ld->ld_gw_port_id,
341*13101SVenki.Rajagopalan@Sun.COM 		    ld->ld_assigned_vlan);
342*13101SVenki.Rajagopalan@Sun.COM 		nack = 0;
343*13101SVenki.Rajagopalan@Sun.COM 	}
344*13101SVenki.Rajagopalan@Sun.COM 
345*13101SVenki.Rajagopalan@Sun.COM 	/*
346*13101SVenki.Rajagopalan@Sun.COM 	 * ACK/NACK the waiter
347*13101SVenki.Rajagopalan@Sun.COM 	 */
348*13101SVenki.Rajagopalan@Sun.COM 	if (nack) {
349*13101SVenki.Rajagopalan@Sun.COM 		vnic->vn_state = EIB_LOGIN_NACK_RCVD;
350*13101SVenki.Rajagopalan@Sun.COM 	} else {
351*13101SVenki.Rajagopalan@Sun.COM 		bcopy(ld, &vnic->vn_login_data, sizeof (eib_login_data_t));
352*13101SVenki.Rajagopalan@Sun.COM 		vnic->vn_state = EIB_LOGIN_ACK_RCVD;
353*13101SVenki.Rajagopalan@Sun.COM 	}
354*13101SVenki.Rajagopalan@Sun.COM 
355*13101SVenki.Rajagopalan@Sun.COM 	cv_signal(&vnic->vn_cv);
356*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&vnic->vn_lock);
357*13101SVenki.Rajagopalan@Sun.COM }
358*13101SVenki.Rajagopalan@Sun.COM 
359*13101SVenki.Rajagopalan@Sun.COM int
eib_vnic_wait_for_table(eib_t * ss,eib_vnic_t * vnic,int * err)360*13101SVenki.Rajagopalan@Sun.COM eib_vnic_wait_for_table(eib_t *ss, eib_vnic_t *vnic, int *err)
361*13101SVenki.Rajagopalan@Sun.COM {
362*13101SVenki.Rajagopalan@Sun.COM 	clock_t deadline;
363*13101SVenki.Rajagopalan@Sun.COM 	int ret = EIB_E_SUCCESS;
364*13101SVenki.Rajagopalan@Sun.COM 
365*13101SVenki.Rajagopalan@Sun.COM 	/*
366*13101SVenki.Rajagopalan@Sun.COM 	 * The EoIB spec does not detail exactly within what time a vhub table
367*13101SVenki.Rajagopalan@Sun.COM 	 * request is expected to be answered.  However, it does mention that
368*13101SVenki.Rajagopalan@Sun.COM 	 * in the worst case, the vhub update messages from the gateway must
369*13101SVenki.Rajagopalan@Sun.COM 	 * be seen atleast once in 2.5 * GW_KA_PERIOD (already saved in
370*13101SVenki.Rajagopalan@Sun.COM 	 * pp_gw_ka_ticks), so we'll settle for that limit.
371*13101SVenki.Rajagopalan@Sun.COM 	 */
372*13101SVenki.Rajagopalan@Sun.COM 	deadline = ddi_get_lbolt() + ss->ei_gw_props->pp_gw_ka_ticks;
373*13101SVenki.Rajagopalan@Sun.COM 
374*13101SVenki.Rajagopalan@Sun.COM 	/*
375*13101SVenki.Rajagopalan@Sun.COM 	 * Wait for vhub table to be constructed. If we wake up with a
376*13101SVenki.Rajagopalan@Sun.COM 	 * vhub table construction failure, record the reason.
377*13101SVenki.Rajagopalan@Sun.COM 	 */
378*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&vnic->vn_lock);
379*13101SVenki.Rajagopalan@Sun.COM 	while (vnic->vn_state == EIB_LOGIN_TBL_WAIT) {
380*13101SVenki.Rajagopalan@Sun.COM 		if (cv_timedwait(&vnic->vn_cv, &vnic->vn_lock,
381*13101SVenki.Rajagopalan@Sun.COM 		    deadline) == -1) {
382*13101SVenki.Rajagopalan@Sun.COM 			if (vnic->vn_state == EIB_LOGIN_TBL_WAIT)
383*13101SVenki.Rajagopalan@Sun.COM 				vnic->vn_state = EIB_LOGIN_TIMED_OUT;
384*13101SVenki.Rajagopalan@Sun.COM 		}
385*13101SVenki.Rajagopalan@Sun.COM 	}
386*13101SVenki.Rajagopalan@Sun.COM 
387*13101SVenki.Rajagopalan@Sun.COM 	if (vnic->vn_state != EIB_LOGIN_TBL_DONE) {
388*13101SVenki.Rajagopalan@Sun.COM 		ret = EIB_E_FAILURE;
389*13101SVenki.Rajagopalan@Sun.COM 		*err =  (vnic->vn_state == EIB_LOGIN_TIMED_OUT) ?
390*13101SVenki.Rajagopalan@Sun.COM 		    ETIME : ECANCELED;
391*13101SVenki.Rajagopalan@Sun.COM 	}
392*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&vnic->vn_lock);
393*13101SVenki.Rajagopalan@Sun.COM 
394*13101SVenki.Rajagopalan@Sun.COM 	return (ret);
395*13101SVenki.Rajagopalan@Sun.COM }
396*13101SVenki.Rajagopalan@Sun.COM 
397*13101SVenki.Rajagopalan@Sun.COM void
eib_vnic_vhub_table_done(eib_vnic_t * vnic,uint_t result_state)398*13101SVenki.Rajagopalan@Sun.COM eib_vnic_vhub_table_done(eib_vnic_t *vnic, uint_t result_state)
399*13101SVenki.Rajagopalan@Sun.COM {
400*13101SVenki.Rajagopalan@Sun.COM 	ASSERT(result_state == EIB_LOGIN_TBL_DONE ||
401*13101SVenki.Rajagopalan@Sun.COM 	    result_state == EIB_LOGIN_TBL_FAILED);
402*13101SVenki.Rajagopalan@Sun.COM 
403*13101SVenki.Rajagopalan@Sun.COM 	/*
404*13101SVenki.Rajagopalan@Sun.COM 	 * Construction of vhub table for the vnic is done one way or
405*13101SVenki.Rajagopalan@Sun.COM 	 * the other.  Set the login wait state appropriately and signal
406*13101SVenki.Rajagopalan@Sun.COM 	 * the waiter. If it's a vhub table failure, we shouldn't parse
407*13101SVenki.Rajagopalan@Sun.COM 	 * any more vhub table or vhub update packets until the vnic state
408*13101SVenki.Rajagopalan@Sun.COM 	 * is changed.
409*13101SVenki.Rajagopalan@Sun.COM 	 */
410*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&vnic->vn_lock);
411*13101SVenki.Rajagopalan@Sun.COM 	vnic->vn_state = result_state;
412*13101SVenki.Rajagopalan@Sun.COM 	cv_signal(&vnic->vn_cv);
413*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&vnic->vn_lock);
414*13101SVenki.Rajagopalan@Sun.COM }
415*13101SVenki.Rajagopalan@Sun.COM 
416*13101SVenki.Rajagopalan@Sun.COM int
eib_vnic_join_data_mcg(eib_t * ss,eib_vnic_t * vnic,uint8_t * mcast_mac,boolean_t rejoin,int * err)417*13101SVenki.Rajagopalan@Sun.COM eib_vnic_join_data_mcg(eib_t *ss, eib_vnic_t *vnic, uint8_t *mcast_mac,
418*13101SVenki.Rajagopalan@Sun.COM     boolean_t rejoin, int *err)
419*13101SVenki.Rajagopalan@Sun.COM {
420*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = vnic->vn_data_chan;
421*13101SVenki.Rajagopalan@Sun.COM 	eib_login_data_t *ld = &vnic->vn_login_data;
422*13101SVenki.Rajagopalan@Sun.COM 	eib_mcg_t *mcg;
423*13101SVenki.Rajagopalan@Sun.COM 	eib_mcg_t *elem;
424*13101SVenki.Rajagopalan@Sun.COM 	eib_mcg_t *tail;
425*13101SVenki.Rajagopalan@Sun.COM 	ibt_mcg_info_t *mcg_info;
426*13101SVenki.Rajagopalan@Sun.COM 	ibt_mcg_attr_t mcg_attr;
427*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
428*13101SVenki.Rajagopalan@Sun.COM 
429*13101SVenki.Rajagopalan@Sun.COM 	/*
430*13101SVenki.Rajagopalan@Sun.COM 	 * Compose the multicast MGID to join
431*13101SVenki.Rajagopalan@Sun.COM 	 */
432*13101SVenki.Rajagopalan@Sun.COM 	bzero(&mcg_attr, sizeof (ibt_mcg_attr_t));
433*13101SVenki.Rajagopalan@Sun.COM 
434*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_make_vhub_mgid(ld->ld_gw_mgid_prefix,
435*13101SVenki.Rajagopalan@Sun.COM 	    (uint8_t)EIB_MGID_VHUB_DATA, mcast_mac, ld->ld_n_mac_mcgid, 0,
436*13101SVenki.Rajagopalan@Sun.COM 	    ld->ld_vhub_id, &(mcg_attr.mc_mgid));
437*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_pkey = (ib_pkey_t)ld->ld_vhub_pkey;
438*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_qkey = (ib_qkey_t)EIB_DATA_QKEY;
439*13101SVenki.Rajagopalan@Sun.COM 
440*13101SVenki.Rajagopalan@Sun.COM 	/*
441*13101SVenki.Rajagopalan@Sun.COM 	 * Allocate for and prepare the mcg to add to our list
442*13101SVenki.Rajagopalan@Sun.COM 	 */
443*13101SVenki.Rajagopalan@Sun.COM 	mcg_info = kmem_zalloc(sizeof (ibt_mcg_info_t), KM_NOSLEEP);
444*13101SVenki.Rajagopalan@Sun.COM 	if (mcg_info == NULL) {
445*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_vnic_join_data_mcg: "
446*13101SVenki.Rajagopalan@Sun.COM 		    "no memory, failed to join mcg (mac=%x:%x:%x:%x:%x:%x)",
447*13101SVenki.Rajagopalan@Sun.COM 		    mcast_mac[0], mcast_mac[1], mcast_mac[2],
448*13101SVenki.Rajagopalan@Sun.COM 		    mcast_mac[3], mcast_mac[4], mcast_mac[5]);
449*13101SVenki.Rajagopalan@Sun.COM 
450*13101SVenki.Rajagopalan@Sun.COM 		*err = ENOMEM;
451*13101SVenki.Rajagopalan@Sun.COM 		goto vnic_join_data_mcg_fail;
452*13101SVenki.Rajagopalan@Sun.COM 	}
453*13101SVenki.Rajagopalan@Sun.COM 	mcg = kmem_zalloc(sizeof (eib_mcg_t), KM_NOSLEEP);
454*13101SVenki.Rajagopalan@Sun.COM 	if (mcg == NULL) {
455*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_vnic_join_data_mcg: "
456*13101SVenki.Rajagopalan@Sun.COM 		    "no memory, failed to join mcg (mac=%x:%x:%x:%x:%x:%x)",
457*13101SVenki.Rajagopalan@Sun.COM 		    mcast_mac[0], mcast_mac[1], mcast_mac[2],
458*13101SVenki.Rajagopalan@Sun.COM 		    mcast_mac[3], mcast_mac[4], mcast_mac[5]);
459*13101SVenki.Rajagopalan@Sun.COM 
460*13101SVenki.Rajagopalan@Sun.COM 		*err = ENOMEM;
461*13101SVenki.Rajagopalan@Sun.COM 		goto vnic_join_data_mcg_fail;
462*13101SVenki.Rajagopalan@Sun.COM 	}
463*13101SVenki.Rajagopalan@Sun.COM 	mcg->mg_next = NULL;
464*13101SVenki.Rajagopalan@Sun.COM 	mcg->mg_rgid = ss->ei_props->ep_sgid;
465*13101SVenki.Rajagopalan@Sun.COM 	mcg->mg_mgid = mcg_attr.mc_mgid;
466*13101SVenki.Rajagopalan@Sun.COM 	mcg->mg_join_state = IB_MC_JSTATE_FULL;
467*13101SVenki.Rajagopalan@Sun.COM 	mcg->mg_mcginfo = mcg_info;
468*13101SVenki.Rajagopalan@Sun.COM 	bcopy(mcast_mac, mcg->mg_mac, ETHERADDRL);
469*13101SVenki.Rajagopalan@Sun.COM 
470*13101SVenki.Rajagopalan@Sun.COM 	/*
471*13101SVenki.Rajagopalan@Sun.COM 	 * Join the multicast group
472*13101SVenki.Rajagopalan@Sun.COM 	 *
473*13101SVenki.Rajagopalan@Sun.COM 	 * Should we query for the mcg and join instead of attempting to
474*13101SVenki.Rajagopalan@Sun.COM 	 * join directly ?
475*13101SVenki.Rajagopalan@Sun.COM 	 */
476*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_join_state = mcg->mg_join_state;
477*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_flow = 0;
478*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_tclass = 0;
479*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_sl = 0;
480*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_scope = 0;	/* IB_MC_SCOPE_SUBNET_LOCAL perhaps ? */
481*13101SVenki.Rajagopalan@Sun.COM 
482*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_join_mcg(mcg->mg_rgid, &mcg_attr, mcg_info, NULL, NULL);
483*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
484*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_vnic_join_data_mcg: "
485*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_join_mcg(mgid=%llx.%llx, pkey=0x%x, qkey=0x%lx, "
486*13101SVenki.Rajagopalan@Sun.COM 		    "jstate=0x%x) failed, ret=%d", mcg_attr.mc_mgid.gid_prefix,
487*13101SVenki.Rajagopalan@Sun.COM 		    mcg_attr.mc_mgid.gid_guid, mcg_attr.mc_pkey,
488*13101SVenki.Rajagopalan@Sun.COM 		    mcg_attr.mc_qkey, mcg_attr.mc_join_state, ret);
489*13101SVenki.Rajagopalan@Sun.COM 
490*13101SVenki.Rajagopalan@Sun.COM 		*err = EINVAL;
491*13101SVenki.Rajagopalan@Sun.COM 		goto vnic_join_data_mcg_fail;
492*13101SVenki.Rajagopalan@Sun.COM 	}
493*13101SVenki.Rajagopalan@Sun.COM 
494*13101SVenki.Rajagopalan@Sun.COM 	/*
495*13101SVenki.Rajagopalan@Sun.COM 	 * Attach to the group to receive multicast messages
496*13101SVenki.Rajagopalan@Sun.COM 	 */
497*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_attach_mcg(chan->ch_chan, mcg_info);
498*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
499*13101SVenki.Rajagopalan@Sun.COM 		*err = EINVAL;
500*13101SVenki.Rajagopalan@Sun.COM 
501*13101SVenki.Rajagopalan@Sun.COM 		ret = ibt_leave_mcg(mcg->mg_rgid, mcg->mg_mgid,
502*13101SVenki.Rajagopalan@Sun.COM 		    eib_reserved_gid, mcg->mg_join_state);
503*13101SVenki.Rajagopalan@Sun.COM 		if (ret != EIB_E_SUCCESS) {
504*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
505*13101SVenki.Rajagopalan@Sun.COM 			    "eib_vnic_join_data_mcg: "
506*13101SVenki.Rajagopalan@Sun.COM 			    "ibt_leave_mcg(mgid=%llx.%llx, jstate=0x%x) "
507*13101SVenki.Rajagopalan@Sun.COM 			    "failed, ret=%d", mcg->mg_mgid.gid_prefix,
508*13101SVenki.Rajagopalan@Sun.COM 			    mcg->mg_mgid.gid_guid, mcg->mg_join_state, ret);
509*13101SVenki.Rajagopalan@Sun.COM 		}
510*13101SVenki.Rajagopalan@Sun.COM 
511*13101SVenki.Rajagopalan@Sun.COM 		goto vnic_join_data_mcg_fail;
512*13101SVenki.Rajagopalan@Sun.COM 	}
513*13101SVenki.Rajagopalan@Sun.COM 
514*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&chan->ch_vhub_lock);
515*13101SVenki.Rajagopalan@Sun.COM 
516*13101SVenki.Rajagopalan@Sun.COM 	tail = NULL;
517*13101SVenki.Rajagopalan@Sun.COM 	for (elem = chan->ch_vhub_data; elem != NULL; elem = elem->mg_next) {
518*13101SVenki.Rajagopalan@Sun.COM 		if ((elem->mg_mgid.gid_prefix == mcg_attr.mc_mgid.gid_prefix) &&
519*13101SVenki.Rajagopalan@Sun.COM 		    (elem->mg_mgid.gid_guid == mcg_attr.mc_mgid.gid_guid)) {
520*13101SVenki.Rajagopalan@Sun.COM 			break;
521*13101SVenki.Rajagopalan@Sun.COM 		}
522*13101SVenki.Rajagopalan@Sun.COM 		tail = elem;
523*13101SVenki.Rajagopalan@Sun.COM 	}
524*13101SVenki.Rajagopalan@Sun.COM 
525*13101SVenki.Rajagopalan@Sun.COM 	/*
526*13101SVenki.Rajagopalan@Sun.COM 	 * If we had't already joined to this mcg, add the newly joined mcg
527*13101SVenki.Rajagopalan@Sun.COM 	 * to the tail and return success
528*13101SVenki.Rajagopalan@Sun.COM 	 */
529*13101SVenki.Rajagopalan@Sun.COM 	if (elem == NULL) {
530*13101SVenki.Rajagopalan@Sun.COM 		if (tail)
531*13101SVenki.Rajagopalan@Sun.COM 			tail->mg_next = mcg;
532*13101SVenki.Rajagopalan@Sun.COM 		else
533*13101SVenki.Rajagopalan@Sun.COM 			chan->ch_vhub_data = mcg;
534*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&chan->ch_vhub_lock);
535*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_SUCCESS);
536*13101SVenki.Rajagopalan@Sun.COM 	}
537*13101SVenki.Rajagopalan@Sun.COM 
538*13101SVenki.Rajagopalan@Sun.COM 	/*
539*13101SVenki.Rajagopalan@Sun.COM 	 * Duplicate.  We need to leave one of the two joins.  If "rejoin"
540*13101SVenki.Rajagopalan@Sun.COM 	 * was requested, leave the old join, otherwise leave the new join.
541*13101SVenki.Rajagopalan@Sun.COM 	 *
542*13101SVenki.Rajagopalan@Sun.COM 	 * Note that we must not detach the qp from the mcg, since if this
543*13101SVenki.Rajagopalan@Sun.COM 	 * was a dup, a second ibt_attach_mcg() above would've simply been
544*13101SVenki.Rajagopalan@Sun.COM 	 * a nop.
545*13101SVenki.Rajagopalan@Sun.COM 	 *
546*13101SVenki.Rajagopalan@Sun.COM 	 * Note also that the leave may not be successful here if our presence
547*13101SVenki.Rajagopalan@Sun.COM 	 * has been removed by the SM, but we need to do this to prevent leaks
548*13101SVenki.Rajagopalan@Sun.COM 	 * in ibtf.
549*13101SVenki.Rajagopalan@Sun.COM 	 */
550*13101SVenki.Rajagopalan@Sun.COM 	if (rejoin) {
551*13101SVenki.Rajagopalan@Sun.COM 		ASSERT(elem->mg_mcginfo != NULL);
552*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(elem->mg_mcginfo, sizeof (ibt_mcg_info_t));
553*13101SVenki.Rajagopalan@Sun.COM 		(void) ibt_leave_mcg(elem->mg_rgid, elem->mg_mgid,
554*13101SVenki.Rajagopalan@Sun.COM 		    eib_reserved_gid, elem->mg_join_state);
555*13101SVenki.Rajagopalan@Sun.COM 		/*
556*13101SVenki.Rajagopalan@Sun.COM 		 * Copy the new mcg over the old one (including the new
557*13101SVenki.Rajagopalan@Sun.COM 		 * mg_mcginfo), but preserve the link to the next element
558*13101SVenki.Rajagopalan@Sun.COM 		 * on the list
559*13101SVenki.Rajagopalan@Sun.COM 		 */
560*13101SVenki.Rajagopalan@Sun.COM 		mcg->mg_next = elem->mg_next;
561*13101SVenki.Rajagopalan@Sun.COM 		bcopy(mcg, elem, sizeof (eib_mcg_t));
562*13101SVenki.Rajagopalan@Sun.COM 	} else {
563*13101SVenki.Rajagopalan@Sun.COM 		ASSERT(mcg->mg_mcginfo != NULL);
564*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(mcg->mg_mcginfo, sizeof (ibt_mcg_info_t));
565*13101SVenki.Rajagopalan@Sun.COM 		(void) ibt_leave_mcg(mcg->mg_rgid, mcg->mg_mgid,
566*13101SVenki.Rajagopalan@Sun.COM 		    eib_reserved_gid, mcg->mg_join_state);
567*13101SVenki.Rajagopalan@Sun.COM 	}
568*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&chan->ch_vhub_lock);
569*13101SVenki.Rajagopalan@Sun.COM 
570*13101SVenki.Rajagopalan@Sun.COM 	kmem_free(mcg, sizeof (eib_mcg_t));
571*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
572*13101SVenki.Rajagopalan@Sun.COM 
573*13101SVenki.Rajagopalan@Sun.COM vnic_join_data_mcg_fail:
574*13101SVenki.Rajagopalan@Sun.COM 	if (mcg) {
575*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(mcg, sizeof (eib_mcg_t));
576*13101SVenki.Rajagopalan@Sun.COM 	}
577*13101SVenki.Rajagopalan@Sun.COM 	if (mcg_info) {
578*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(mcg_info, sizeof (ibt_mcg_info_t));
579*13101SVenki.Rajagopalan@Sun.COM 	}
580*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_FAILURE);
581*13101SVenki.Rajagopalan@Sun.COM }
582*13101SVenki.Rajagopalan@Sun.COM 
583*13101SVenki.Rajagopalan@Sun.COM int
eib_vnic_setup_dest(eib_vnic_t * vnic,eib_wqe_t * swqe,uint8_t * dmac,uint16_t vlan)584*13101SVenki.Rajagopalan@Sun.COM eib_vnic_setup_dest(eib_vnic_t *vnic, eib_wqe_t *swqe, uint8_t *dmac,
585*13101SVenki.Rajagopalan@Sun.COM     uint16_t vlan)
586*13101SVenki.Rajagopalan@Sun.COM {
587*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = vnic->vn_ss;
588*13101SVenki.Rajagopalan@Sun.COM 	eib_stats_t *stats = ss->ei_stats;
589*13101SVenki.Rajagopalan@Sun.COM 	eib_avect_t *av;
590*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_map_t ucast;
591*13101SVenki.Rajagopalan@Sun.COM 	ibt_mcg_info_t mcast;
592*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
593*13101SVenki.Rajagopalan@Sun.COM 	int dtype;
594*13101SVenki.Rajagopalan@Sun.COM 	int rv;
595*13101SVenki.Rajagopalan@Sun.COM 
596*13101SVenki.Rajagopalan@Sun.COM 	/*
597*13101SVenki.Rajagopalan@Sun.COM 	 * Lookup the destination in the vhub table or in our mcg list
598*13101SVenki.Rajagopalan@Sun.COM 	 */
599*13101SVenki.Rajagopalan@Sun.COM 	rv = eib_vnic_lookup_dest(vnic, dmac, vlan, &ucast, &mcast, &dtype);
600*13101SVenki.Rajagopalan@Sun.COM 	if (rv != EIB_E_SUCCESS) {
601*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_vnic_setup_dest: "
602*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_lookup_dest(dmac=%x:%x:%x:%x:%x:%x, vlan=0x%x) "
603*13101SVenki.Rajagopalan@Sun.COM 		    "failed", dmac[0], dmac[1], dmac[2], dmac[3], dmac[4],
604*13101SVenki.Rajagopalan@Sun.COM 		    dmac[5], vlan);
605*13101SVenki.Rajagopalan@Sun.COM 
606*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
607*13101SVenki.Rajagopalan@Sun.COM 	}
608*13101SVenki.Rajagopalan@Sun.COM 
609*13101SVenki.Rajagopalan@Sun.COM 	/*
610*13101SVenki.Rajagopalan@Sun.COM 	 * If we found a unicast address, get an address vector for the lid
611*13101SVenki.Rajagopalan@Sun.COM 	 * and sl, modify the ud dest based on the address vector and return.
612*13101SVenki.Rajagopalan@Sun.COM 	 * If we found a multicast address, use the address vector in the
613*13101SVenki.Rajagopalan@Sun.COM 	 * mcg info to modify the ud dest and return.
614*13101SVenki.Rajagopalan@Sun.COM 	 */
615*13101SVenki.Rajagopalan@Sun.COM 	if (dtype == EIB_TX_UNICAST) {
616*13101SVenki.Rajagopalan@Sun.COM 		if ((av = eib_ibt_hold_avect(ss, ucast.mp_lid,
617*13101SVenki.Rajagopalan@Sun.COM 		    ucast.mp_sl)) == NULL) {
618*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
619*13101SVenki.Rajagopalan@Sun.COM 			    "eib_vnic_setup_dest: "
620*13101SVenki.Rajagopalan@Sun.COM 			    "eib_ibt_hold_avect(lid=0x%x, sl=0x%x) failed",
621*13101SVenki.Rajagopalan@Sun.COM 			    ucast.mp_lid, ucast.mp_sl);
622*13101SVenki.Rajagopalan@Sun.COM 
623*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_FAILURE);
624*13101SVenki.Rajagopalan@Sun.COM 		}
625*13101SVenki.Rajagopalan@Sun.COM 		ret = ibt_modify_ud_dest(swqe->qe_dest, EIB_DATA_QKEY,
626*13101SVenki.Rajagopalan@Sun.COM 		    ucast.mp_qpn, &av->av_vect);
627*13101SVenki.Rajagopalan@Sun.COM 
628*13101SVenki.Rajagopalan@Sun.COM 		eib_ibt_release_avect(ss, av);
629*13101SVenki.Rajagopalan@Sun.COM 
630*13101SVenki.Rajagopalan@Sun.COM 		if (ret != IBT_SUCCESS) {
631*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
632*13101SVenki.Rajagopalan@Sun.COM 			    "eib_vnic_setup_dest: "
633*13101SVenki.Rajagopalan@Sun.COM 			    "ibt_modify_ud_dest(qpn=0x%lx, qkey=0x%lx) "
634*13101SVenki.Rajagopalan@Sun.COM 			    "failed, ret=%d", ucast.mp_qpn, EIB_DATA_QKEY, ret);
635*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_FAILURE);
636*13101SVenki.Rajagopalan@Sun.COM 		}
637*13101SVenki.Rajagopalan@Sun.COM 	} else {
638*13101SVenki.Rajagopalan@Sun.COM 		ret = ibt_modify_ud_dest(swqe->qe_dest, EIB_DATA_QKEY,
639*13101SVenki.Rajagopalan@Sun.COM 		    IB_MC_QPN, &(mcast.mc_adds_vect));
640*13101SVenki.Rajagopalan@Sun.COM 
641*13101SVenki.Rajagopalan@Sun.COM 		if (dtype == EIB_TX_BROADCAST)
642*13101SVenki.Rajagopalan@Sun.COM 			EIB_INCR_COUNTER(&stats->st_brdcstxmit);
643*13101SVenki.Rajagopalan@Sun.COM 		else
644*13101SVenki.Rajagopalan@Sun.COM 			EIB_INCR_COUNTER(&stats->st_multixmit);
645*13101SVenki.Rajagopalan@Sun.COM 
646*13101SVenki.Rajagopalan@Sun.COM 		if (ret != IBT_SUCCESS) {
647*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
648*13101SVenki.Rajagopalan@Sun.COM 			    "eib_vnic_setup_dest: "
649*13101SVenki.Rajagopalan@Sun.COM 			    "ibt_modify_ud_dest(mc_qpn=0x%lx, qkey=0x%lx) "
650*13101SVenki.Rajagopalan@Sun.COM 			    "failed, ret=%d", IB_MC_QPN, EIB_DATA_QKEY, ret);
651*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_FAILURE);
652*13101SVenki.Rajagopalan@Sun.COM 		}
653*13101SVenki.Rajagopalan@Sun.COM 	}
654*13101SVenki.Rajagopalan@Sun.COM 
655*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
656*13101SVenki.Rajagopalan@Sun.COM }
657*13101SVenki.Rajagopalan@Sun.COM 
658*13101SVenki.Rajagopalan@Sun.COM void
eib_vnic_leave_data_mcg(eib_t * ss,eib_vnic_t * vnic,uint8_t * mcast_mac)659*13101SVenki.Rajagopalan@Sun.COM eib_vnic_leave_data_mcg(eib_t *ss, eib_vnic_t *vnic, uint8_t *mcast_mac)
660*13101SVenki.Rajagopalan@Sun.COM {
661*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_vnic_join_data_mcg(ss, vnic, mcast_mac);
662*13101SVenki.Rajagopalan@Sun.COM }
663*13101SVenki.Rajagopalan@Sun.COM 
664*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
665*13101SVenki.Rajagopalan@Sun.COM void
eib_vnic_init_tables(eib_t * ss,eib_vnic_t * vnic)666*13101SVenki.Rajagopalan@Sun.COM eib_vnic_init_tables(eib_t *ss, eib_vnic_t *vnic)
667*13101SVenki.Rajagopalan@Sun.COM {
668*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_table_t *tbl;
669*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_update_t *upd;
670*13101SVenki.Rajagopalan@Sun.COM 
671*13101SVenki.Rajagopalan@Sun.COM 	tbl = kmem_zalloc(sizeof (eib_vhub_table_t), KM_SLEEP);
672*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&tbl->tb_lock, NULL, MUTEX_DRIVER, NULL);
673*13101SVenki.Rajagopalan@Sun.COM 	tbl->tb_eport_state = FIP_EPORT_UP;
674*13101SVenki.Rajagopalan@Sun.COM 
675*13101SVenki.Rajagopalan@Sun.COM 	upd = kmem_zalloc(sizeof (eib_vhub_update_t), KM_SLEEP);
676*13101SVenki.Rajagopalan@Sun.COM 	mutex_init(&upd->up_lock, NULL, MUTEX_DRIVER, NULL);
677*13101SVenki.Rajagopalan@Sun.COM 
678*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&vnic->vn_lock);
679*13101SVenki.Rajagopalan@Sun.COM 	vnic->vn_vhub_table = tbl;
680*13101SVenki.Rajagopalan@Sun.COM 	vnic->vn_vhub_update = upd;
681*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&vnic->vn_lock);
682*13101SVenki.Rajagopalan@Sun.COM }
683*13101SVenki.Rajagopalan@Sun.COM 
684*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
685*13101SVenki.Rajagopalan@Sun.COM void
eib_vnic_fini_tables(eib_t * ss,eib_vnic_t * vnic,boolean_t clobber)686*13101SVenki.Rajagopalan@Sun.COM eib_vnic_fini_tables(eib_t *ss, eib_vnic_t *vnic, boolean_t clobber)
687*13101SVenki.Rajagopalan@Sun.COM {
688*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_update_t *upd;
689*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_table_t *tbl;
690*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_map_t *elem;
691*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_map_t *nxt;
692*13101SVenki.Rajagopalan@Sun.COM 	int i;
693*13101SVenki.Rajagopalan@Sun.COM 
694*13101SVenki.Rajagopalan@Sun.COM 	/*
695*13101SVenki.Rajagopalan@Sun.COM 	 * We come here only when we've either completely detached from
696*13101SVenki.Rajagopalan@Sun.COM 	 * the vhub multicast groups and so cannot receive anymore table
697*13101SVenki.Rajagopalan@Sun.COM 	 * or update control messages, or we've had a recent vhub table
698*13101SVenki.Rajagopalan@Sun.COM 	 * construction failure and the vnic state is currently
699*13101SVenki.Rajagopalan@Sun.COM 	 * EIB_LOGIN_TBL_FAILED and so won't parse any table or update
700*13101SVenki.Rajagopalan@Sun.COM 	 * control messages.  Also, since we haven't completed the vnic
701*13101SVenki.Rajagopalan@Sun.COM 	 * creation, no one from the tx path will be accessing the
702*13101SVenki.Rajagopalan@Sun.COM 	 * vn_vhub_table entries either.  All said, we're free to play
703*13101SVenki.Rajagopalan@Sun.COM 	 * around with the vnic's vn_vhub_table and vn_vhub_update here.
704*13101SVenki.Rajagopalan@Sun.COM 	 */
705*13101SVenki.Rajagopalan@Sun.COM 
706*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&vnic->vn_lock);
707*13101SVenki.Rajagopalan@Sun.COM 	upd = vnic->vn_vhub_update;
708*13101SVenki.Rajagopalan@Sun.COM 	tbl = vnic->vn_vhub_table;
709*13101SVenki.Rajagopalan@Sun.COM 	if (clobber) {
710*13101SVenki.Rajagopalan@Sun.COM 		vnic->vn_vhub_update = NULL;
711*13101SVenki.Rajagopalan@Sun.COM 		vnic->vn_vhub_table = NULL;
712*13101SVenki.Rajagopalan@Sun.COM 	}
713*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&vnic->vn_lock);
714*13101SVenki.Rajagopalan@Sun.COM 
715*13101SVenki.Rajagopalan@Sun.COM 	/*
716*13101SVenki.Rajagopalan@Sun.COM 	 * Destroy the vhub update entries if any
717*13101SVenki.Rajagopalan@Sun.COM 	 */
718*13101SVenki.Rajagopalan@Sun.COM 	if (upd) {
719*13101SVenki.Rajagopalan@Sun.COM 		/*
720*13101SVenki.Rajagopalan@Sun.COM 		 * Wipe clean the list of vnic entries accumulated via
721*13101SVenki.Rajagopalan@Sun.COM 		 * vhub updates so far.  Release eib_vhub_update_t only
722*13101SVenki.Rajagopalan@Sun.COM 		 * if explicitly asked to do so
723*13101SVenki.Rajagopalan@Sun.COM 		 */
724*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&upd->up_lock);
725*13101SVenki.Rajagopalan@Sun.COM 		for (elem = upd->up_vnic_entry; elem != NULL; elem = nxt) {
726*13101SVenki.Rajagopalan@Sun.COM 			nxt = elem->mp_next;
727*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(elem, sizeof (eib_vhub_map_t));
728*13101SVenki.Rajagopalan@Sun.COM 		}
729*13101SVenki.Rajagopalan@Sun.COM 		upd->up_vnic_entry = NULL;
730*13101SVenki.Rajagopalan@Sun.COM 		upd->up_tusn = 0;
731*13101SVenki.Rajagopalan@Sun.COM 		upd->up_eport_state = 0;
732*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&upd->up_lock);
733*13101SVenki.Rajagopalan@Sun.COM 
734*13101SVenki.Rajagopalan@Sun.COM 		if (clobber) {
735*13101SVenki.Rajagopalan@Sun.COM 			mutex_destroy(&upd->up_lock);
736*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(upd, sizeof (eib_vhub_update_t));
737*13101SVenki.Rajagopalan@Sun.COM 		}
738*13101SVenki.Rajagopalan@Sun.COM 	}
739*13101SVenki.Rajagopalan@Sun.COM 
740*13101SVenki.Rajagopalan@Sun.COM 	/*
741*13101SVenki.Rajagopalan@Sun.COM 	 * Destroy the vhub table entries
742*13101SVenki.Rajagopalan@Sun.COM 	 */
743*13101SVenki.Rajagopalan@Sun.COM 	if (tbl == NULL)
744*13101SVenki.Rajagopalan@Sun.COM 		return;
745*13101SVenki.Rajagopalan@Sun.COM 
746*13101SVenki.Rajagopalan@Sun.COM 	/*
747*13101SVenki.Rajagopalan@Sun.COM 	 * Wipe clean the list of entries in the vhub table collected so
748*13101SVenki.Rajagopalan@Sun.COM 	 * far. Release eib_vhub_table_t only if explicitly asked to do so.
749*13101SVenki.Rajagopalan@Sun.COM 	 */
750*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&tbl->tb_lock);
751*13101SVenki.Rajagopalan@Sun.COM 
752*13101SVenki.Rajagopalan@Sun.COM 	if (tbl->tb_gateway) {
753*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(tbl->tb_gateway, sizeof (eib_vhub_map_t));
754*13101SVenki.Rajagopalan@Sun.COM 		tbl->tb_gateway = NULL;
755*13101SVenki.Rajagopalan@Sun.COM 	}
756*13101SVenki.Rajagopalan@Sun.COM 
757*13101SVenki.Rajagopalan@Sun.COM 	if (tbl->tb_unicast_miss) {
758*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(tbl->tb_unicast_miss, sizeof (eib_vhub_map_t));
759*13101SVenki.Rajagopalan@Sun.COM 		tbl->tb_unicast_miss = NULL;
760*13101SVenki.Rajagopalan@Sun.COM 	}
761*13101SVenki.Rajagopalan@Sun.COM 
762*13101SVenki.Rajagopalan@Sun.COM 	if (tbl->tb_vhub_multicast) {
763*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(tbl->tb_vhub_multicast, sizeof (eib_vhub_map_t));
764*13101SVenki.Rajagopalan@Sun.COM 		tbl->tb_vhub_multicast = NULL;
765*13101SVenki.Rajagopalan@Sun.COM 	}
766*13101SVenki.Rajagopalan@Sun.COM 
767*13101SVenki.Rajagopalan@Sun.COM 	if (!eib_wa_no_mcast_entries) {
768*13101SVenki.Rajagopalan@Sun.COM 		for (i = 0; i < EIB_TB_NBUCKETS; i++) {
769*13101SVenki.Rajagopalan@Sun.COM 			for (elem = tbl->tb_mcast_entry[i]; elem != NULL;
770*13101SVenki.Rajagopalan@Sun.COM 			    elem = nxt) {
771*13101SVenki.Rajagopalan@Sun.COM 				nxt = elem->mp_next;
772*13101SVenki.Rajagopalan@Sun.COM 				kmem_free(elem, sizeof (eib_vhub_map_t));
773*13101SVenki.Rajagopalan@Sun.COM 			}
774*13101SVenki.Rajagopalan@Sun.COM 			tbl->tb_mcast_entry[i] = NULL;
775*13101SVenki.Rajagopalan@Sun.COM 		}
776*13101SVenki.Rajagopalan@Sun.COM 	}
777*13101SVenki.Rajagopalan@Sun.COM 
778*13101SVenki.Rajagopalan@Sun.COM 	for (i = 0; i < EIB_TB_NBUCKETS; i++) {
779*13101SVenki.Rajagopalan@Sun.COM 		for (elem = tbl->tb_vnic_entry[i]; elem != NULL; elem = nxt) {
780*13101SVenki.Rajagopalan@Sun.COM 			nxt = elem->mp_next;
781*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(elem, sizeof (eib_vhub_map_t));
782*13101SVenki.Rajagopalan@Sun.COM 		}
783*13101SVenki.Rajagopalan@Sun.COM 		tbl->tb_vnic_entry[i] = NULL;
784*13101SVenki.Rajagopalan@Sun.COM 	}
785*13101SVenki.Rajagopalan@Sun.COM 
786*13101SVenki.Rajagopalan@Sun.COM 	tbl->tb_tusn = 0;
787*13101SVenki.Rajagopalan@Sun.COM 	tbl->tb_eport_state = 0;
788*13101SVenki.Rajagopalan@Sun.COM 	tbl->tb_entries_seen = 0;
789*13101SVenki.Rajagopalan@Sun.COM 	tbl->tb_entries_in_table = 0;
790*13101SVenki.Rajagopalan@Sun.COM 	tbl->tb_checksum = 0;
791*13101SVenki.Rajagopalan@Sun.COM 
792*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&tbl->tb_lock);
793*13101SVenki.Rajagopalan@Sun.COM 
794*13101SVenki.Rajagopalan@Sun.COM 	/*
795*13101SVenki.Rajagopalan@Sun.COM 	 * Don't throw away space created for holding vhub table if we haven't
796*13101SVenki.Rajagopalan@Sun.COM 	 * been explicitly asked to do so
797*13101SVenki.Rajagopalan@Sun.COM 	 */
798*13101SVenki.Rajagopalan@Sun.COM 	if (clobber) {
799*13101SVenki.Rajagopalan@Sun.COM 		mutex_destroy(&tbl->tb_lock);
800*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(tbl, sizeof (eib_vhub_table_t));
801*13101SVenki.Rajagopalan@Sun.COM 	}
802*13101SVenki.Rajagopalan@Sun.COM }
803*13101SVenki.Rajagopalan@Sun.COM 
804*13101SVenki.Rajagopalan@Sun.COM eib_chan_t *
eib_vnic_get_data_chan(eib_t * ss,int vinst)805*13101SVenki.Rajagopalan@Sun.COM eib_vnic_get_data_chan(eib_t *ss, int vinst)
806*13101SVenki.Rajagopalan@Sun.COM {
807*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_t *vnic;
808*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = NULL;
809*13101SVenki.Rajagopalan@Sun.COM 
810*13101SVenki.Rajagopalan@Sun.COM 	if (vinst >= 0 && vinst < EIB_MAX_VNICS) {
811*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ss->ei_vnic_lock);
812*13101SVenki.Rajagopalan@Sun.COM 		if ((vnic = ss->ei_vnic[vinst]) != NULL)
813*13101SVenki.Rajagopalan@Sun.COM 			chan = vnic->vn_data_chan;
814*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ss->ei_vnic_lock);
815*13101SVenki.Rajagopalan@Sun.COM 	}
816*13101SVenki.Rajagopalan@Sun.COM 
817*13101SVenki.Rajagopalan@Sun.COM 	return (chan);
818*13101SVenki.Rajagopalan@Sun.COM }
819*13101SVenki.Rajagopalan@Sun.COM 
820*13101SVenki.Rajagopalan@Sun.COM void
eib_vnic_need_new(eib_t * ss,uint8_t * mac,uint16_t vlan)821*13101SVenki.Rajagopalan@Sun.COM eib_vnic_need_new(eib_t *ss, uint8_t *mac, uint16_t vlan)
822*13101SVenki.Rajagopalan@Sun.COM {
823*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_req_t *vrq;
824*13101SVenki.Rajagopalan@Sun.COM 
825*13101SVenki.Rajagopalan@Sun.COM 	EIB_INCR_COUNTER(&ss->ei_stats->st_noxmitbuf);
826*13101SVenki.Rajagopalan@Sun.COM 
827*13101SVenki.Rajagopalan@Sun.COM 	/*
828*13101SVenki.Rajagopalan@Sun.COM 	 * Create a new vnic request for this {mac,vlan} tuple
829*13101SVenki.Rajagopalan@Sun.COM 	 */
830*13101SVenki.Rajagopalan@Sun.COM 	vrq = kmem_zalloc(sizeof (eib_vnic_req_t), KM_NOSLEEP);
831*13101SVenki.Rajagopalan@Sun.COM 	if (vrq == NULL) {
832*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_vnic_need_new: "
833*13101SVenki.Rajagopalan@Sun.COM 		    "no memory, failed to queue new vnic creation request");
834*13101SVenki.Rajagopalan@Sun.COM 		return;
835*13101SVenki.Rajagopalan@Sun.COM 	}
836*13101SVenki.Rajagopalan@Sun.COM 	vrq->vr_next = NULL;
837*13101SVenki.Rajagopalan@Sun.COM 	vrq->vr_req = EIB_CR_REQ_NEW_VNIC;
838*13101SVenki.Rajagopalan@Sun.COM 	bcopy(mac, vrq->vr_mac, ETHERADDRL);
839*13101SVenki.Rajagopalan@Sun.COM 	vrq->vr_vlan = vlan;
840*13101SVenki.Rajagopalan@Sun.COM 
841*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_enqueue_req(ss, vrq);
842*13101SVenki.Rajagopalan@Sun.COM }
843*13101SVenki.Rajagopalan@Sun.COM 
844*13101SVenki.Rajagopalan@Sun.COM void
eib_vnic_enqueue_req(eib_t * ss,eib_vnic_req_t * vrq)845*13101SVenki.Rajagopalan@Sun.COM eib_vnic_enqueue_req(eib_t *ss, eib_vnic_req_t *vrq)
846*13101SVenki.Rajagopalan@Sun.COM {
847*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_req_t *elem = NULL;
848*13101SVenki.Rajagopalan@Sun.COM 	uint8_t *m;
849*13101SVenki.Rajagopalan@Sun.COM 
850*13101SVenki.Rajagopalan@Sun.COM 	/*
851*13101SVenki.Rajagopalan@Sun.COM 	 * Enqueue this new vnic request with the vnic creator and
852*13101SVenki.Rajagopalan@Sun.COM 	 * signal it.
853*13101SVenki.Rajagopalan@Sun.COM 	 */
854*13101SVenki.Rajagopalan@Sun.COM 	m = vrq->vr_mac;
855*13101SVenki.Rajagopalan@Sun.COM 	EIB_DPRINTF_DEBUG(ss->ei_instance, "eib_vnic_enqueue_req: "
856*13101SVenki.Rajagopalan@Sun.COM 	    "BEGIN file request for creation of %x:%x:%x:%x:%x:%x, 0x%x",
857*13101SVenki.Rajagopalan@Sun.COM 	    m[0], m[1], m[2], m[3], m[4], m[5], vrq->vr_vlan);
858*13101SVenki.Rajagopalan@Sun.COM 
859*13101SVenki.Rajagopalan@Sun.COM 
860*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_vnic_req_lock);
861*13101SVenki.Rajagopalan@Sun.COM 
862*13101SVenki.Rajagopalan@Sun.COM 	/*
863*13101SVenki.Rajagopalan@Sun.COM 	 * Death request has the highest priority.  If we've already been asked
864*13101SVenki.Rajagopalan@Sun.COM 	 * to die, we don't entertain any more requests.
865*13101SVenki.Rajagopalan@Sun.COM 	 */
866*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_vnic_req) {
867*13101SVenki.Rajagopalan@Sun.COM 		if (ss->ei_vnic_req->vr_req == EIB_CR_REQ_DIE) {
868*13101SVenki.Rajagopalan@Sun.COM 			mutex_exit(&ss->ei_vnic_req_lock);
869*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(vrq, sizeof (eib_vnic_req_t));
870*13101SVenki.Rajagopalan@Sun.COM 			return;
871*13101SVenki.Rajagopalan@Sun.COM 		}
872*13101SVenki.Rajagopalan@Sun.COM 	}
873*13101SVenki.Rajagopalan@Sun.COM 
874*13101SVenki.Rajagopalan@Sun.COM 	if (vrq->vr_req == EIB_CR_REQ_DIE || vrq->vr_req == EIB_CR_REQ_FLUSH) {
875*13101SVenki.Rajagopalan@Sun.COM 		vrq->vr_next = ss->ei_vnic_req;
876*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_vnic_req = vrq;
877*13101SVenki.Rajagopalan@Sun.COM 	} else {
878*13101SVenki.Rajagopalan@Sun.COM 		/*
879*13101SVenki.Rajagopalan@Sun.COM 		 * If there's already a creation request for this vnic that's
880*13101SVenki.Rajagopalan@Sun.COM 		 * being processed, return immediately without adding a new
881*13101SVenki.Rajagopalan@Sun.COM 		 * request.
882*13101SVenki.Rajagopalan@Sun.COM 		 */
883*13101SVenki.Rajagopalan@Sun.COM 		if ((elem = ss->ei_pending_vnic_req) != NULL) {
884*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_DEBUG(ss->ei_instance,
885*13101SVenki.Rajagopalan@Sun.COM 			    "eib_vnic_enqueue_req: "
886*13101SVenki.Rajagopalan@Sun.COM 			    "ei_pending_vnic_req not NULL");
887*13101SVenki.Rajagopalan@Sun.COM 
888*13101SVenki.Rajagopalan@Sun.COM 			if ((elem->vr_vlan == vrq->vr_vlan) &&
889*13101SVenki.Rajagopalan@Sun.COM 			    (bcmp(elem->vr_mac, vrq->vr_mac,
890*13101SVenki.Rajagopalan@Sun.COM 			    ETHERADDRL) == 0)) {
891*13101SVenki.Rajagopalan@Sun.COM 				EIB_DPRINTF_DEBUG(ss->ei_instance,
892*13101SVenki.Rajagopalan@Sun.COM 				    "eib_vnic_enqueue_req: "
893*13101SVenki.Rajagopalan@Sun.COM 				    "pending request already present for "
894*13101SVenki.Rajagopalan@Sun.COM 				    "%x:%x:%x:%x:%x:%x, 0x%x", m[0], m[1], m[2],
895*13101SVenki.Rajagopalan@Sun.COM 				    m[3], m[4], m[5], vrq->vr_vlan);
896*13101SVenki.Rajagopalan@Sun.COM 
897*13101SVenki.Rajagopalan@Sun.COM 				mutex_exit(&ss->ei_vnic_req_lock);
898*13101SVenki.Rajagopalan@Sun.COM 				kmem_free(vrq, sizeof (eib_vnic_req_t));
899*13101SVenki.Rajagopalan@Sun.COM 
900*13101SVenki.Rajagopalan@Sun.COM 				EIB_DPRINTF_DEBUG(ss->ei_instance,
901*13101SVenki.Rajagopalan@Sun.COM 				    "eib_vnic_enqueue_req: "
902*13101SVenki.Rajagopalan@Sun.COM 				    "END file request");
903*13101SVenki.Rajagopalan@Sun.COM 				return;
904*13101SVenki.Rajagopalan@Sun.COM 			}
905*13101SVenki.Rajagopalan@Sun.COM 
906*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_DEBUG(ss->ei_instance,
907*13101SVenki.Rajagopalan@Sun.COM 			    "eib_vnic_enqueue_req: "
908*13101SVenki.Rajagopalan@Sun.COM 			    "NO pending request for %x:%x:%x:%x:%x:%x, 0x%x",
909*13101SVenki.Rajagopalan@Sun.COM 			    m[0], m[1], m[2], m[3], m[4], m[5], vrq->vr_vlan);
910*13101SVenki.Rajagopalan@Sun.COM 		}
911*13101SVenki.Rajagopalan@Sun.COM 
912*13101SVenki.Rajagopalan@Sun.COM 		/*
913*13101SVenki.Rajagopalan@Sun.COM 		 * Or if there's one waiting in the queue for processing, do
914*13101SVenki.Rajagopalan@Sun.COM 		 * the same thing
915*13101SVenki.Rajagopalan@Sun.COM 		 */
916*13101SVenki.Rajagopalan@Sun.COM 		for (elem = ss->ei_vnic_req; elem; elem = elem->vr_next) {
917*13101SVenki.Rajagopalan@Sun.COM 			/*
918*13101SVenki.Rajagopalan@Sun.COM 			 * If there's already a create request for this vnic
919*13101SVenki.Rajagopalan@Sun.COM 			 * waiting in the queue, return immediately
920*13101SVenki.Rajagopalan@Sun.COM 			 */
921*13101SVenki.Rajagopalan@Sun.COM 			if (elem->vr_req == EIB_CR_REQ_NEW_VNIC) {
922*13101SVenki.Rajagopalan@Sun.COM 				if ((elem->vr_vlan == vrq->vr_vlan) &&
923*13101SVenki.Rajagopalan@Sun.COM 				    (bcmp(elem->vr_mac, vrq->vr_mac,
924*13101SVenki.Rajagopalan@Sun.COM 				    ETHERADDRL) == 0)) {
925*13101SVenki.Rajagopalan@Sun.COM 
926*13101SVenki.Rajagopalan@Sun.COM 					EIB_DPRINTF_DEBUG(ss->ei_instance,
927*13101SVenki.Rajagopalan@Sun.COM 					    "eib_vnic_enqueue_req: "
928*13101SVenki.Rajagopalan@Sun.COM 					    "request already present for "
929*13101SVenki.Rajagopalan@Sun.COM 					    "%x:%x:%x:%x:%x:%x, 0x%x", m[0],
930*13101SVenki.Rajagopalan@Sun.COM 					    m[1], m[2], m[3], m[4], m[5],
931*13101SVenki.Rajagopalan@Sun.COM 					    vrq->vr_vlan);
932*13101SVenki.Rajagopalan@Sun.COM 
933*13101SVenki.Rajagopalan@Sun.COM 					mutex_exit(&ss->ei_vnic_req_lock);
934*13101SVenki.Rajagopalan@Sun.COM 					kmem_free(vrq, sizeof (eib_vnic_req_t));
935*13101SVenki.Rajagopalan@Sun.COM 
936*13101SVenki.Rajagopalan@Sun.COM 					EIB_DPRINTF_DEBUG(ss->ei_instance,
937*13101SVenki.Rajagopalan@Sun.COM 					    "eib_vnic_enqueue_req: "
938*13101SVenki.Rajagopalan@Sun.COM 					    "END file request");
939*13101SVenki.Rajagopalan@Sun.COM 					return;
940*13101SVenki.Rajagopalan@Sun.COM 				}
941*13101SVenki.Rajagopalan@Sun.COM 			}
942*13101SVenki.Rajagopalan@Sun.COM 
943*13101SVenki.Rajagopalan@Sun.COM 			if (elem->vr_next == NULL) {
944*13101SVenki.Rajagopalan@Sun.COM 				EIB_DPRINTF_DEBUG(ss->ei_instance,
945*13101SVenki.Rajagopalan@Sun.COM 				    "eib_vnic_enqueue_req: "
946*13101SVenki.Rajagopalan@Sun.COM 				    "request not found, filing afresh");
947*13101SVenki.Rajagopalan@Sun.COM 				break;
948*13101SVenki.Rajagopalan@Sun.COM 			}
949*13101SVenki.Rajagopalan@Sun.COM 		}
950*13101SVenki.Rajagopalan@Sun.COM 
951*13101SVenki.Rajagopalan@Sun.COM 		/*
952*13101SVenki.Rajagopalan@Sun.COM 		 * Otherwise queue up this new creation request and signal the
953*13101SVenki.Rajagopalan@Sun.COM 		 * service thread.
954*13101SVenki.Rajagopalan@Sun.COM 		 */
955*13101SVenki.Rajagopalan@Sun.COM 		if (elem) {
956*13101SVenki.Rajagopalan@Sun.COM 			elem->vr_next = vrq;
957*13101SVenki.Rajagopalan@Sun.COM 		} else {
958*13101SVenki.Rajagopalan@Sun.COM 			ss->ei_vnic_req = vrq;
959*13101SVenki.Rajagopalan@Sun.COM 		}
960*13101SVenki.Rajagopalan@Sun.COM 	}
961*13101SVenki.Rajagopalan@Sun.COM 
962*13101SVenki.Rajagopalan@Sun.COM 	cv_signal(&ss->ei_vnic_req_cv);
963*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_vnic_req_lock);
964*13101SVenki.Rajagopalan@Sun.COM 
965*13101SVenki.Rajagopalan@Sun.COM 	EIB_DPRINTF_DEBUG(ss->ei_instance,
966*13101SVenki.Rajagopalan@Sun.COM 	    "eib_vnic_enqueue_req: END file request");
967*13101SVenki.Rajagopalan@Sun.COM }
968*13101SVenki.Rajagopalan@Sun.COM 
969*13101SVenki.Rajagopalan@Sun.COM void
eib_vnic_update_failed_macs(eib_t * ss,uint8_t * old_mac,uint16_t old_vlan,uint8_t * new_mac,uint16_t new_vlan)970*13101SVenki.Rajagopalan@Sun.COM eib_vnic_update_failed_macs(eib_t *ss, uint8_t *old_mac, uint16_t old_vlan,
971*13101SVenki.Rajagopalan@Sun.COM     uint8_t *new_mac, uint16_t new_vlan)
972*13101SVenki.Rajagopalan@Sun.COM {
973*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_req_t *vrq;
974*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_req_t *elem;
975*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_req_t *prev;
976*13101SVenki.Rajagopalan@Sun.COM 
977*13101SVenki.Rajagopalan@Sun.COM 	vrq = kmem_zalloc(sizeof (eib_vnic_req_t), KM_NOSLEEP);
978*13101SVenki.Rajagopalan@Sun.COM 	if (vrq == NULL) {
979*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
980*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_update_failed_macs: "
981*13101SVenki.Rajagopalan@Sun.COM 		    "no memory, failed to drop old mac");
982*13101SVenki.Rajagopalan@Sun.COM 	} else {
983*13101SVenki.Rajagopalan@Sun.COM 		vrq->vr_next = NULL;
984*13101SVenki.Rajagopalan@Sun.COM 		vrq->vr_req = 0;	/* unused */
985*13101SVenki.Rajagopalan@Sun.COM 		bcopy(old_mac, vrq->vr_mac, ETHERADDRL);
986*13101SVenki.Rajagopalan@Sun.COM 		vrq->vr_vlan = old_vlan;
987*13101SVenki.Rajagopalan@Sun.COM 	}
988*13101SVenki.Rajagopalan@Sun.COM 
989*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_vnic_req_lock);
990*13101SVenki.Rajagopalan@Sun.COM 
991*13101SVenki.Rajagopalan@Sun.COM 	/*
992*13101SVenki.Rajagopalan@Sun.COM 	 * We'll search the failed vnics list to see if the new {mac,vlan}
993*13101SVenki.Rajagopalan@Sun.COM 	 * tuple is in there and remove it if present (since the new address
994*13101SVenki.Rajagopalan@Sun.COM 	 * is no longer "failed").
995*13101SVenki.Rajagopalan@Sun.COM 	 */
996*13101SVenki.Rajagopalan@Sun.COM 	prev = NULL;
997*13101SVenki.Rajagopalan@Sun.COM 	for (elem = ss->ei_failed_vnic_req; elem; elem = elem->vr_next) {
998*13101SVenki.Rajagopalan@Sun.COM 		if ((bcmp(elem->vr_mac, new_mac, ETHERADDRL) == 0) &&
999*13101SVenki.Rajagopalan@Sun.COM 		    (elem->vr_vlan == new_vlan)) {
1000*13101SVenki.Rajagopalan@Sun.COM 			if (prev) {
1001*13101SVenki.Rajagopalan@Sun.COM 				prev->vr_next = elem->vr_next;
1002*13101SVenki.Rajagopalan@Sun.COM 			} else {
1003*13101SVenki.Rajagopalan@Sun.COM 				ss->ei_failed_vnic_req = elem->vr_next;
1004*13101SVenki.Rajagopalan@Sun.COM 			}
1005*13101SVenki.Rajagopalan@Sun.COM 			elem->vr_next = NULL;
1006*13101SVenki.Rajagopalan@Sun.COM 			break;
1007*13101SVenki.Rajagopalan@Sun.COM 		}
1008*13101SVenki.Rajagopalan@Sun.COM 	}
1009*13101SVenki.Rajagopalan@Sun.COM 	if (elem) {
1010*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(elem, sizeof (eib_vnic_req_t));
1011*13101SVenki.Rajagopalan@Sun.COM 	}
1012*13101SVenki.Rajagopalan@Sun.COM 
1013*13101SVenki.Rajagopalan@Sun.COM 	/*
1014*13101SVenki.Rajagopalan@Sun.COM 	 * We'll also insert the old {mac,vlan} tuple to the "failed vnic req"
1015*13101SVenki.Rajagopalan@Sun.COM 	 * list (it shouldn't be there already), to avoid trying to recreate
1016*13101SVenki.Rajagopalan@Sun.COM 	 * the vnic we just explicitly discarded.
1017*13101SVenki.Rajagopalan@Sun.COM 	 */
1018*13101SVenki.Rajagopalan@Sun.COM 	if (vrq) {
1019*13101SVenki.Rajagopalan@Sun.COM 		vrq->vr_next = ss->ei_failed_vnic_req;
1020*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_failed_vnic_req = vrq;
1021*13101SVenki.Rajagopalan@Sun.COM 	}
1022*13101SVenki.Rajagopalan@Sun.COM 
1023*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_vnic_req_lock);
1024*13101SVenki.Rajagopalan@Sun.COM }
1025*13101SVenki.Rajagopalan@Sun.COM 
1026*13101SVenki.Rajagopalan@Sun.COM void
eib_vnic_resurrect_zombies(eib_t * ss,uint8_t * vn0_mac)1027*13101SVenki.Rajagopalan@Sun.COM eib_vnic_resurrect_zombies(eib_t *ss, uint8_t *vn0_mac)
1028*13101SVenki.Rajagopalan@Sun.COM {
1029*13101SVenki.Rajagopalan@Sun.COM 	int inst;
1030*13101SVenki.Rajagopalan@Sun.COM 
1031*13101SVenki.Rajagopalan@Sun.COM 	/*
1032*13101SVenki.Rajagopalan@Sun.COM 	 * We want to restart/relogin each vnic instance with the gateway,
1033*13101SVenki.Rajagopalan@Sun.COM 	 * but with the same vnic id and instance as before.
1034*13101SVenki.Rajagopalan@Sun.COM 	 */
1035*13101SVenki.Rajagopalan@Sun.COM 	while ((inst = EIB_FIND_LSB_SET(ss->ei_zombie_vnics)) != -1) {
1036*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
1037*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_resurrect_zombies: "
1038*13101SVenki.Rajagopalan@Sun.COM 		    "calling eib_vnic_restart(vn_inst=%d)", inst);
1039*13101SVenki.Rajagopalan@Sun.COM 
1040*13101SVenki.Rajagopalan@Sun.COM 		eib_vnic_restart(ss, inst, vn0_mac);
1041*13101SVenki.Rajagopalan@Sun.COM 
1042*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
1043*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_resurrect_zombies: "
1044*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_restart(vn_inst=%d) done", inst);
1045*13101SVenki.Rajagopalan@Sun.COM 	}
1046*13101SVenki.Rajagopalan@Sun.COM }
1047*13101SVenki.Rajagopalan@Sun.COM 
1048*13101SVenki.Rajagopalan@Sun.COM void
eib_vnic_restart(eib_t * ss,int inst,uint8_t * vn0_mac)1049*13101SVenki.Rajagopalan@Sun.COM eib_vnic_restart(eib_t *ss, int inst, uint8_t *vn0_mac)
1050*13101SVenki.Rajagopalan@Sun.COM {
1051*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_t *vnic;
1052*13101SVenki.Rajagopalan@Sun.COM 	eib_login_data_t *ld;
1053*13101SVenki.Rajagopalan@Sun.COM 	uint8_t old_mac[ETHERADDRL];
1054*13101SVenki.Rajagopalan@Sun.COM 	int ret;
1055*13101SVenki.Rajagopalan@Sun.COM 	int err;
1056*13101SVenki.Rajagopalan@Sun.COM 
1057*13101SVenki.Rajagopalan@Sun.COM 	if (inst < 0 || inst >= EIB_MAX_VNICS) {
1058*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1059*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_restart: "
1060*13101SVenki.Rajagopalan@Sun.COM 		    "vnic instance (%d) invalid", inst);
1061*13101SVenki.Rajagopalan@Sun.COM 		return;
1062*13101SVenki.Rajagopalan@Sun.COM 	}
1063*13101SVenki.Rajagopalan@Sun.COM 
1064*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_modify_enter(ss, EIB_VN_BEING_MODIFIED);
1065*13101SVenki.Rajagopalan@Sun.COM 	if ((vnic = ss->ei_vnic[inst]) != NULL) {
1066*13101SVenki.Rajagopalan@Sun.COM 		/*
1067*13101SVenki.Rajagopalan@Sun.COM 		 * Remember what mac was allocated for this vnic last time
1068*13101SVenki.Rajagopalan@Sun.COM 		 */
1069*13101SVenki.Rajagopalan@Sun.COM 		bcopy(vnic->vn_login_data.ld_assigned_mac, old_mac, ETHERADDRL);
1070*13101SVenki.Rajagopalan@Sun.COM 
1071*13101SVenki.Rajagopalan@Sun.COM 		/*
1072*13101SVenki.Rajagopalan@Sun.COM 		 * Tear down and restart this vnic instance
1073*13101SVenki.Rajagopalan@Sun.COM 		 */
1074*13101SVenki.Rajagopalan@Sun.COM 		eib_rb_vnic_create_common(ss, vnic, ~0);
1075*13101SVenki.Rajagopalan@Sun.COM 		ret = eib_vnic_create_common(ss, vnic, &err);
1076*13101SVenki.Rajagopalan@Sun.COM 		if (ret != EIB_E_SUCCESS) {
1077*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
1078*13101SVenki.Rajagopalan@Sun.COM 			    "eib_vnic_restart: "
1079*13101SVenki.Rajagopalan@Sun.COM 			    "eib_vnic_create_common(vnic_inst=%d) failed, "
1080*13101SVenki.Rajagopalan@Sun.COM 			    "ret=%d", inst, err);
1081*13101SVenki.Rajagopalan@Sun.COM 		}
1082*13101SVenki.Rajagopalan@Sun.COM 
1083*13101SVenki.Rajagopalan@Sun.COM 		/*
1084*13101SVenki.Rajagopalan@Sun.COM 		 * If this is vnic instance 0 and if our current assigned mac is
1085*13101SVenki.Rajagopalan@Sun.COM 		 * different from what was assigned last time, we need to pass
1086*13101SVenki.Rajagopalan@Sun.COM 		 * this information back to the caller, so the mac layer can be
1087*13101SVenki.Rajagopalan@Sun.COM 		 * appropriately informed. We will also queue up the old mac
1088*13101SVenki.Rajagopalan@Sun.COM 		 * and vlan in the "failed vnic req" list, so any future packets
1089*13101SVenki.Rajagopalan@Sun.COM 		 * to this address on this interface will be dropped.
1090*13101SVenki.Rajagopalan@Sun.COM 		 */
1091*13101SVenki.Rajagopalan@Sun.COM 		ld = &vnic->vn_login_data;
1092*13101SVenki.Rajagopalan@Sun.COM 		if ((inst == 0) &&
1093*13101SVenki.Rajagopalan@Sun.COM 		    (bcmp(ld->ld_assigned_mac, old_mac, ETHERADDRL) != 0)) {
1094*13101SVenki.Rajagopalan@Sun.COM 			uint8_t *m = ld->ld_assigned_mac;
1095*13101SVenki.Rajagopalan@Sun.COM 
1096*13101SVenki.Rajagopalan@Sun.COM 			if (vn0_mac != NULL) {
1097*13101SVenki.Rajagopalan@Sun.COM 				bcopy(ld->ld_assigned_mac, vn0_mac,
1098*13101SVenki.Rajagopalan@Sun.COM 				    ETHERADDRL);
1099*13101SVenki.Rajagopalan@Sun.COM 			}
1100*13101SVenki.Rajagopalan@Sun.COM 
1101*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_VERBOSE(ss->ei_instance,
1102*13101SVenki.Rajagopalan@Sun.COM 			    "eib_vnic_restart: updating failed macs list "
1103*13101SVenki.Rajagopalan@Sun.COM 			    "old=%x:%x:%x:%x:%x:%x, new=%x:%x:%x:%x:%x:%x, "
1104*13101SVenki.Rajagopalan@Sun.COM 			    "vlan=0x%x", old_mac[0], old_mac[1], old_mac[2],
1105*13101SVenki.Rajagopalan@Sun.COM 			    old_mac[3], old_mac[4], old_mac[5], m[0], m[1],
1106*13101SVenki.Rajagopalan@Sun.COM 			    m[2], m[3], m[4], m[5], vnic->vn_vlan);
1107*13101SVenki.Rajagopalan@Sun.COM 
1108*13101SVenki.Rajagopalan@Sun.COM 			eib_vnic_update_failed_macs(ss, old_mac, vnic->vn_vlan,
1109*13101SVenki.Rajagopalan@Sun.COM 			    ld->ld_assigned_mac, vnic->vn_vlan);
1110*13101SVenki.Rajagopalan@Sun.COM 		}
1111*13101SVenki.Rajagopalan@Sun.COM 
1112*13101SVenki.Rajagopalan@Sun.COM 		/*
1113*13101SVenki.Rajagopalan@Sun.COM 		 * No longer a zombie or need to rejoin mcgs
1114*13101SVenki.Rajagopalan@Sun.COM 		 */
1115*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ss->ei_vnic_lock);
1116*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_zombie_vnics &= (~((uint64_t)1 << inst));
1117*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_rejoin_vnics &= (~((uint64_t)1 << inst));
1118*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ss->ei_vnic_lock);
1119*13101SVenki.Rajagopalan@Sun.COM 	}
1120*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_modify_exit(ss, EIB_VN_BEING_MODIFIED);
1121*13101SVenki.Rajagopalan@Sun.COM }
1122*13101SVenki.Rajagopalan@Sun.COM 
1123*13101SVenki.Rajagopalan@Sun.COM void
eib_vnic_rejoin_mcgs(eib_t * ss)1124*13101SVenki.Rajagopalan@Sun.COM eib_vnic_rejoin_mcgs(eib_t *ss)
1125*13101SVenki.Rajagopalan@Sun.COM {
1126*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_t *vnic;
1127*13101SVenki.Rajagopalan@Sun.COM 	int inst;
1128*13101SVenki.Rajagopalan@Sun.COM 
1129*13101SVenki.Rajagopalan@Sun.COM 	/*
1130*13101SVenki.Rajagopalan@Sun.COM 	 * For each vnic that still requires re-join, go through the
1131*13101SVenki.Rajagopalan@Sun.COM 	 * control channels and data channel and reattach/rejoin mcgs.
1132*13101SVenki.Rajagopalan@Sun.COM 	 */
1133*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_vnic_lock);
1134*13101SVenki.Rajagopalan@Sun.COM 	while ((inst = EIB_FIND_LSB_SET(ss->ei_rejoin_vnics)) != -1) {
1135*13101SVenki.Rajagopalan@Sun.COM 		if ((vnic = ss->ei_vnic[inst]) != NULL) {
1136*13101SVenki.Rajagopalan@Sun.COM 			eib_vnic_reattach_ctl_mcgs(ss, vnic);
1137*13101SVenki.Rajagopalan@Sun.COM 			eib_vnic_rejoin_data_mcgs(ss, vnic);
1138*13101SVenki.Rajagopalan@Sun.COM 		}
1139*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_rejoin_vnics &= (~((uint64_t)1 << inst));
1140*13101SVenki.Rajagopalan@Sun.COM 	}
1141*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_vnic_lock);
1142*13101SVenki.Rajagopalan@Sun.COM }
1143*13101SVenki.Rajagopalan@Sun.COM 
1144*13101SVenki.Rajagopalan@Sun.COM void
eib_rb_vnic_create(eib_t * ss,eib_vnic_t * vnic,uint_t progress)1145*13101SVenki.Rajagopalan@Sun.COM eib_rb_vnic_create(eib_t *ss, eib_vnic_t *vnic, uint_t progress)
1146*13101SVenki.Rajagopalan@Sun.COM {
1147*13101SVenki.Rajagopalan@Sun.COM 	if (progress & EIB_VNIC_CREATE_COMMON_DONE) {
1148*13101SVenki.Rajagopalan@Sun.COM 		eib_rb_vnic_create_common(ss, vnic, ~0);
1149*13101SVenki.Rajagopalan@Sun.COM 	}
1150*13101SVenki.Rajagopalan@Sun.COM 
1151*13101SVenki.Rajagopalan@Sun.COM 	if (progress & EIB_VNIC_GOT_INSTANCE) {
1152*13101SVenki.Rajagopalan@Sun.COM 		eib_vnic_ret_instance(ss, vnic->vn_instance);
1153*13101SVenki.Rajagopalan@Sun.COM 		vnic->vn_instance = -1;
1154*13101SVenki.Rajagopalan@Sun.COM 	}
1155*13101SVenki.Rajagopalan@Sun.COM 
1156*13101SVenki.Rajagopalan@Sun.COM 	if (progress & EIB_VNIC_STRUCT_ALLOCD) {
1157*13101SVenki.Rajagopalan@Sun.COM 		cv_destroy(&vnic->vn_cv);
1158*13101SVenki.Rajagopalan@Sun.COM 		mutex_destroy(&vnic->vn_lock);
1159*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(vnic, sizeof (eib_vnic_t));
1160*13101SVenki.Rajagopalan@Sun.COM 	}
1161*13101SVenki.Rajagopalan@Sun.COM }
1162*13101SVenki.Rajagopalan@Sun.COM 
1163*13101SVenki.Rajagopalan@Sun.COM /*
1164*13101SVenki.Rajagopalan@Sun.COM  * Currently, we only allow 64 vnics per eoib device instance, for
1165*13101SVenki.Rajagopalan@Sun.COM  * reasons described in eib.h (see EIB_VNIC_ID() definition), so we
1166*13101SVenki.Rajagopalan@Sun.COM  * could use a simple bitmap to assign the vnic instance numbers.
1167*13101SVenki.Rajagopalan@Sun.COM  * Once we start allowing more vnics per device instance, this
1168*13101SVenki.Rajagopalan@Sun.COM  * allocation scheme will need to be changed.
1169*13101SVenki.Rajagopalan@Sun.COM  */
1170*13101SVenki.Rajagopalan@Sun.COM static int
eib_vnic_get_instance(eib_t * ss,int * vinst)1171*13101SVenki.Rajagopalan@Sun.COM eib_vnic_get_instance(eib_t *ss, int *vinst)
1172*13101SVenki.Rajagopalan@Sun.COM {
1173*13101SVenki.Rajagopalan@Sun.COM 	int bitpos;
1174*13101SVenki.Rajagopalan@Sun.COM 	uint64_t nval;
1175*13101SVenki.Rajagopalan@Sun.COM 
1176*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_vnic_lock);
1177*13101SVenki.Rajagopalan@Sun.COM 
1178*13101SVenki.Rajagopalan@Sun.COM 	/*
1179*13101SVenki.Rajagopalan@Sun.COM 	 * What we have is the active vnics list --  the in-use vnics are
1180*13101SVenki.Rajagopalan@Sun.COM 	 * indicated by a 1 in the bit position, and the free ones are
1181*13101SVenki.Rajagopalan@Sun.COM 	 * indicated by 0.  We need to find the least significant '0' bit
1182*13101SVenki.Rajagopalan@Sun.COM 	 * to get the first free vnic instance.  Or we could bit-reverse
1183*13101SVenki.Rajagopalan@Sun.COM 	 * the active list and locate the least significant '1'.
1184*13101SVenki.Rajagopalan@Sun.COM 	 */
1185*13101SVenki.Rajagopalan@Sun.COM 	nval = ~(ss->ei_active_vnics);
1186*13101SVenki.Rajagopalan@Sun.COM 	if (nval == 0)
1187*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1188*13101SVenki.Rajagopalan@Sun.COM 
1189*13101SVenki.Rajagopalan@Sun.COM 	/*
1190*13101SVenki.Rajagopalan@Sun.COM 	 * The single bit-position values in a 64-bit integer are relatively
1191*13101SVenki.Rajagopalan@Sun.COM 	 * prime with 67, so performing a modulus division with 67 guarantees
1192*13101SVenki.Rajagopalan@Sun.COM 	 * a unique number between 0 and 63 for each value (setbit_mod67[]).
1193*13101SVenki.Rajagopalan@Sun.COM 	 */
1194*13101SVenki.Rajagopalan@Sun.COM 	bitpos = EIB_FIND_LSB_SET(nval);
1195*13101SVenki.Rajagopalan@Sun.COM 	if (bitpos == -1)
1196*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1197*13101SVenki.Rajagopalan@Sun.COM 
1198*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_active_vnics |= ((uint64_t)1 << bitpos);
1199*13101SVenki.Rajagopalan@Sun.COM 	*vinst = bitpos;
1200*13101SVenki.Rajagopalan@Sun.COM 
1201*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_vnic_lock);
1202*13101SVenki.Rajagopalan@Sun.COM 
1203*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
1204*13101SVenki.Rajagopalan@Sun.COM }
1205*13101SVenki.Rajagopalan@Sun.COM 
1206*13101SVenki.Rajagopalan@Sun.COM static void
eib_vnic_ret_instance(eib_t * ss,int vinst)1207*13101SVenki.Rajagopalan@Sun.COM eib_vnic_ret_instance(eib_t *ss, int vinst)
1208*13101SVenki.Rajagopalan@Sun.COM {
1209*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_vnic_lock);
1210*13101SVenki.Rajagopalan@Sun.COM 
1211*13101SVenki.Rajagopalan@Sun.COM 	if (vinst >= EIB_MAX_VNICS) {
1212*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1213*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_ret_instance: "
1214*13101SVenki.Rajagopalan@Sun.COM 		    "vnic instance (%d) invalid", vinst);
1215*13101SVenki.Rajagopalan@Sun.COM 	} else if ((ss->ei_active_vnics & ((uint64_t)1 << vinst)) == 0) {
1216*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1217*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_ret_instance: "
1218*13101SVenki.Rajagopalan@Sun.COM 		    "vnic instance (%d) not active!", vinst);
1219*13101SVenki.Rajagopalan@Sun.COM 	} else {
1220*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_active_vnics &= (~((uint64_t)1 << vinst));
1221*13101SVenki.Rajagopalan@Sun.COM 	}
1222*13101SVenki.Rajagopalan@Sun.COM 
1223*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_vnic_lock);
1224*13101SVenki.Rajagopalan@Sun.COM }
1225*13101SVenki.Rajagopalan@Sun.COM 
1226*13101SVenki.Rajagopalan@Sun.COM static void
eib_vnic_modify_enter(eib_t * ss,uint_t op)1227*13101SVenki.Rajagopalan@Sun.COM eib_vnic_modify_enter(eib_t *ss, uint_t op)
1228*13101SVenki.Rajagopalan@Sun.COM {
1229*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_vnic_lock);
1230*13101SVenki.Rajagopalan@Sun.COM 	while (ss->ei_vnic_state & EIB_VN_BEING_MODIFIED)
1231*13101SVenki.Rajagopalan@Sun.COM 		cv_wait(&ss->ei_vnic_cv, &ss->ei_vnic_lock);
1232*13101SVenki.Rajagopalan@Sun.COM 
1233*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_vnic_state |= op;
1234*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_vnic_lock);
1235*13101SVenki.Rajagopalan@Sun.COM }
1236*13101SVenki.Rajagopalan@Sun.COM 
1237*13101SVenki.Rajagopalan@Sun.COM static void
eib_vnic_modify_exit(eib_t * ss,uint_t op)1238*13101SVenki.Rajagopalan@Sun.COM eib_vnic_modify_exit(eib_t *ss, uint_t op)
1239*13101SVenki.Rajagopalan@Sun.COM {
1240*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_vnic_lock);
1241*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_vnic_state &= (~op);
1242*13101SVenki.Rajagopalan@Sun.COM 	cv_broadcast(&ss->ei_vnic_cv);
1243*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_vnic_lock);
1244*13101SVenki.Rajagopalan@Sun.COM }
1245*13101SVenki.Rajagopalan@Sun.COM 
1246*13101SVenki.Rajagopalan@Sun.COM static int
eib_vnic_create_common(eib_t * ss,eib_vnic_t * vnic,int * err)1247*13101SVenki.Rajagopalan@Sun.COM eib_vnic_create_common(eib_t *ss, eib_vnic_t *vnic, int *err)
1248*13101SVenki.Rajagopalan@Sun.COM {
1249*13101SVenki.Rajagopalan@Sun.COM 	uint_t progress = 0;
1250*13101SVenki.Rajagopalan@Sun.COM 
1251*13101SVenki.Rajagopalan@Sun.COM 	/*
1252*13101SVenki.Rajagopalan@Sun.COM 	 * When we receive login acks within this vnic creation
1253*13101SVenki.Rajagopalan@Sun.COM 	 * routine we need a way to retrieve the vnic structure
1254*13101SVenki.Rajagopalan@Sun.COM 	 * from the vnic instance, so store this somewhere. Note
1255*13101SVenki.Rajagopalan@Sun.COM 	 * that there can be only one outstanding vnic creation
1256*13101SVenki.Rajagopalan@Sun.COM 	 * at any point of time, so we only need one vnic struct.
1257*13101SVenki.Rajagopalan@Sun.COM 	 */
1258*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_vnic_lock);
1259*13101SVenki.Rajagopalan@Sun.COM 	ASSERT(ss->ei_vnic_pending == NULL);
1260*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_vnic_pending = vnic;
1261*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_vnic_lock);
1262*13101SVenki.Rajagopalan@Sun.COM 
1263*13101SVenki.Rajagopalan@Sun.COM 	/*
1264*13101SVenki.Rajagopalan@Sun.COM 	 * Create a control qp for this vnic
1265*13101SVenki.Rajagopalan@Sun.COM 	 */
1266*13101SVenki.Rajagopalan@Sun.COM 	if (eib_ctl_create_qp(ss, vnic, err) != EIB_E_SUCCESS) {
1267*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1268*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_create_common: "
1269*13101SVenki.Rajagopalan@Sun.COM 		    "eib_ctl_create_qp(vn_id=0x%x) failed, ret=%d",
1270*13101SVenki.Rajagopalan@Sun.COM 		    vnic->vn_id, *err);
1271*13101SVenki.Rajagopalan@Sun.COM 		goto vnic_create_common_fail;
1272*13101SVenki.Rajagopalan@Sun.COM 	}
1273*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_VNIC_CTLQP_CREATED;
1274*13101SVenki.Rajagopalan@Sun.COM 
1275*13101SVenki.Rajagopalan@Sun.COM 	/*
1276*13101SVenki.Rajagopalan@Sun.COM 	 * Create a data qp for this vnic
1277*13101SVenki.Rajagopalan@Sun.COM 	 */
1278*13101SVenki.Rajagopalan@Sun.COM 	if (eib_data_create_qp(ss, vnic, err) != EIB_E_SUCCESS) {
1279*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1280*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_create_common: "
1281*13101SVenki.Rajagopalan@Sun.COM 		    "eib_data_create_qp(vn_id=0x%x) failed, ret=%d",
1282*13101SVenki.Rajagopalan@Sun.COM 		    vnic->vn_id, *err);
1283*13101SVenki.Rajagopalan@Sun.COM 		goto vnic_create_common_fail;
1284*13101SVenki.Rajagopalan@Sun.COM 	}
1285*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_VNIC_DATAQP_CREATED;
1286*13101SVenki.Rajagopalan@Sun.COM 
1287*13101SVenki.Rajagopalan@Sun.COM 	/*
1288*13101SVenki.Rajagopalan@Sun.COM 	 * Login to the gateway with this vnic's parameters
1289*13101SVenki.Rajagopalan@Sun.COM 	 */
1290*13101SVenki.Rajagopalan@Sun.COM 	if (eib_fip_login(ss, vnic, err) != EIB_E_SUCCESS) {
1291*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1292*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_create_common: "
1293*13101SVenki.Rajagopalan@Sun.COM 		    "eib_fip_login(vn_id=0x%x) failed, ret=%d",
1294*13101SVenki.Rajagopalan@Sun.COM 		    vnic->vn_id, *err);
1295*13101SVenki.Rajagopalan@Sun.COM 		goto vnic_create_common_fail;
1296*13101SVenki.Rajagopalan@Sun.COM 	}
1297*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_VNIC_LOGIN_DONE;
1298*13101SVenki.Rajagopalan@Sun.COM 
1299*13101SVenki.Rajagopalan@Sun.COM 	/*
1300*13101SVenki.Rajagopalan@Sun.COM 	 * Associate the control and data qps for the vnic with the
1301*13101SVenki.Rajagopalan@Sun.COM 	 * vHUB partition
1302*13101SVenki.Rajagopalan@Sun.COM 	 */
1303*13101SVenki.Rajagopalan@Sun.COM 	if (eib_vnic_set_partition(ss, vnic, err) != EIB_E_SUCCESS) {
1304*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1305*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_create_common: "
1306*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_set_partition(vn_id=0x%x) failed, ret=%d",
1307*13101SVenki.Rajagopalan@Sun.COM 		    vnic->vn_id, *err);
1308*13101SVenki.Rajagopalan@Sun.COM 		goto vnic_create_common_fail;
1309*13101SVenki.Rajagopalan@Sun.COM 	}
1310*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_VNIC_PARTITION_SET;
1311*13101SVenki.Rajagopalan@Sun.COM 
1312*13101SVenki.Rajagopalan@Sun.COM 	/*
1313*13101SVenki.Rajagopalan@Sun.COM 	 * Post initial set of rx buffers on the control qp to the HCA
1314*13101SVenki.Rajagopalan@Sun.COM 	 */
1315*13101SVenki.Rajagopalan@Sun.COM 	if (eib_chan_post_rx(ss, vnic->vn_ctl_chan, NULL) != EIB_E_SUCCESS) {
1316*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1317*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_create_common: "
1318*13101SVenki.Rajagopalan@Sun.COM 		    "eib_chan_post_rx(vn_id=0x%x, CTL_QP) failed, ret=%d",
1319*13101SVenki.Rajagopalan@Sun.COM 		    vnic->vn_id, *err);
1320*13101SVenki.Rajagopalan@Sun.COM 
1321*13101SVenki.Rajagopalan@Sun.COM 		*err = ENOMEM;
1322*13101SVenki.Rajagopalan@Sun.COM 		goto vnic_create_common_fail;
1323*13101SVenki.Rajagopalan@Sun.COM 	}
1324*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_VNIC_RX_POSTED_TO_CTLQP;
1325*13101SVenki.Rajagopalan@Sun.COM 
1326*13101SVenki.Rajagopalan@Sun.COM 	/*
1327*13101SVenki.Rajagopalan@Sun.COM 	 * Post initial set of rx buffers on the data qp to the HCA
1328*13101SVenki.Rajagopalan@Sun.COM 	 */
1329*13101SVenki.Rajagopalan@Sun.COM 	if (eib_chan_post_rx(ss, vnic->vn_data_chan, NULL) != EIB_E_SUCCESS) {
1330*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1331*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_create_common: "
1332*13101SVenki.Rajagopalan@Sun.COM 		    "eib_chan_post_rx(vn_id=0x%x, DATA_QP) failed, ret=%d",
1333*13101SVenki.Rajagopalan@Sun.COM 		    vnic->vn_id, *err);
1334*13101SVenki.Rajagopalan@Sun.COM 
1335*13101SVenki.Rajagopalan@Sun.COM 		*err = ENOMEM;
1336*13101SVenki.Rajagopalan@Sun.COM 		goto vnic_create_common_fail;
1337*13101SVenki.Rajagopalan@Sun.COM 	}
1338*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_VNIC_RX_POSTED_TO_DATAQP;
1339*13101SVenki.Rajagopalan@Sun.COM 
1340*13101SVenki.Rajagopalan@Sun.COM 	/*
1341*13101SVenki.Rajagopalan@Sun.COM 	 * Attach to the vHUB table and vHUB update multicast groups
1342*13101SVenki.Rajagopalan@Sun.COM 	 */
1343*13101SVenki.Rajagopalan@Sun.COM 	if (eib_vnic_attach_ctl_mcgs(ss, vnic, err) != EIB_E_SUCCESS) {
1344*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1345*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_create_common: "
1346*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_attach_ctl_mcgs(vn_id=0x%x) failed, ret=%d",
1347*13101SVenki.Rajagopalan@Sun.COM 		    vnic->vn_id, *err);
1348*13101SVenki.Rajagopalan@Sun.COM 		goto vnic_create_common_fail;
1349*13101SVenki.Rajagopalan@Sun.COM 	}
1350*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_VNIC_ATTACHED_TO_CTL_MCGS;
1351*13101SVenki.Rajagopalan@Sun.COM 
1352*13101SVenki.Rajagopalan@Sun.COM 	/*
1353*13101SVenki.Rajagopalan@Sun.COM 	 * Send the vHUB table request and construct the vhub table
1354*13101SVenki.Rajagopalan@Sun.COM 	 */
1355*13101SVenki.Rajagopalan@Sun.COM 	if (eib_fip_vhub_table(ss, vnic, err) != EIB_E_SUCCESS) {
1356*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1357*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_create_common: "
1358*13101SVenki.Rajagopalan@Sun.COM 		    "eib_fip_vhub_table(vn_id=0x%x) failed, ret=%d",
1359*13101SVenki.Rajagopalan@Sun.COM 		    vnic->vn_id, *err);
1360*13101SVenki.Rajagopalan@Sun.COM 		goto vnic_create_common_fail;
1361*13101SVenki.Rajagopalan@Sun.COM 	}
1362*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_VNIC_GOT_VHUB_TABLE;
1363*13101SVenki.Rajagopalan@Sun.COM 
1364*13101SVenki.Rajagopalan@Sun.COM 	/*
1365*13101SVenki.Rajagopalan@Sun.COM 	 * Detach from the vHUB table mcg (we no longer need the vHUB
1366*13101SVenki.Rajagopalan@Sun.COM 	 * table messages) and start the keepalives for this vnic.
1367*13101SVenki.Rajagopalan@Sun.COM 	 */
1368*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_start_keepalives(ss, vnic);
1369*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_vnic_attach_vhub_table(ss, vnic);
1370*13101SVenki.Rajagopalan@Sun.COM 
1371*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_VNIC_KEEPALIVES_STARTED;
1372*13101SVenki.Rajagopalan@Sun.COM 
1373*13101SVenki.Rajagopalan@Sun.COM 	/*
1374*13101SVenki.Rajagopalan@Sun.COM 	 * All ethernet vnics are automatically members of the broadcast
1375*13101SVenki.Rajagopalan@Sun.COM 	 * group for the vlan they are participating in, so join the
1376*13101SVenki.Rajagopalan@Sun.COM 	 * ethernet broadcast group.  Note that when we restart vnics,
1377*13101SVenki.Rajagopalan@Sun.COM 	 * we rejoin the mcgs, so we pass B_TRUE to eib_vnic_join_data_mcg().
1378*13101SVenki.Rajagopalan@Sun.COM 	 */
1379*13101SVenki.Rajagopalan@Sun.COM 	if (eib_vnic_join_data_mcg(ss, vnic, eib_broadcast_mac, B_TRUE,
1380*13101SVenki.Rajagopalan@Sun.COM 	    err) != EIB_E_SUCCESS) {
1381*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1382*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_create_common: "
1383*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_join_data_mcg(vn_id=0x%x, BCAST_GROUP) failed, "
1384*13101SVenki.Rajagopalan@Sun.COM 		    "ret=%d", vnic->vn_id, *err);
1385*13101SVenki.Rajagopalan@Sun.COM 		goto vnic_create_common_fail;
1386*13101SVenki.Rajagopalan@Sun.COM 	}
1387*13101SVenki.Rajagopalan@Sun.COM 	progress |= EIB_VNIC_BROADCAST_JOINED;
1388*13101SVenki.Rajagopalan@Sun.COM 
1389*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_vnic_lock);
1390*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_vnic[vnic->vn_instance] == NULL) {
1391*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_vnic[vnic->vn_instance] = vnic;
1392*13101SVenki.Rajagopalan@Sun.COM 	}
1393*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_vnic_pending = NULL;
1394*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_vnic_lock);
1395*13101SVenki.Rajagopalan@Sun.COM 
1396*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
1397*13101SVenki.Rajagopalan@Sun.COM 
1398*13101SVenki.Rajagopalan@Sun.COM vnic_create_common_fail:
1399*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_vnic_create_common(ss, vnic, progress);
1400*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_FAILURE);
1401*13101SVenki.Rajagopalan@Sun.COM }
1402*13101SVenki.Rajagopalan@Sun.COM 
1403*13101SVenki.Rajagopalan@Sun.COM static int
eib_vnic_set_partition(eib_t * ss,eib_vnic_t * vnic,int * err)1404*13101SVenki.Rajagopalan@Sun.COM eib_vnic_set_partition(eib_t *ss, eib_vnic_t *vnic, int *err)
1405*13101SVenki.Rajagopalan@Sun.COM {
1406*13101SVenki.Rajagopalan@Sun.COM 	int ret;
1407*13101SVenki.Rajagopalan@Sun.COM 
1408*13101SVenki.Rajagopalan@Sun.COM 	/*
1409*13101SVenki.Rajagopalan@Sun.COM 	 * Associate the control channel with the vhub partition
1410*13101SVenki.Rajagopalan@Sun.COM 	 */
1411*13101SVenki.Rajagopalan@Sun.COM 	ret = eib_ibt_modify_chan_pkey(ss, vnic->vn_ctl_chan,
1412*13101SVenki.Rajagopalan@Sun.COM 	    vnic->vn_login_data.ld_vhub_pkey);
1413*13101SVenki.Rajagopalan@Sun.COM 	if (ret != EIB_E_SUCCESS) {
1414*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1415*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_set_partition: "
1416*13101SVenki.Rajagopalan@Sun.COM 		    "eib_ibt_modify_chan_pkey(vn_id=0x%x, CTL_CHAN, "
1417*13101SVenki.Rajagopalan@Sun.COM 		    "vhub_pkey=0x%x) failed", vnic->vn_id,
1418*13101SVenki.Rajagopalan@Sun.COM 		    vnic->vn_login_data.ld_vhub_pkey);
1419*13101SVenki.Rajagopalan@Sun.COM 		*err = EINVAL;
1420*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1421*13101SVenki.Rajagopalan@Sun.COM 	}
1422*13101SVenki.Rajagopalan@Sun.COM 
1423*13101SVenki.Rajagopalan@Sun.COM 	/*
1424*13101SVenki.Rajagopalan@Sun.COM 	 * Now, do the same thing for the data channel. Note that if a
1425*13101SVenki.Rajagopalan@Sun.COM 	 * failure happens, the channel state(s) are left as-is, since
1426*13101SVenki.Rajagopalan@Sun.COM 	 * it is pointless to try to change them back using the same
1427*13101SVenki.Rajagopalan@Sun.COM 	 * interfaces that have just failed.
1428*13101SVenki.Rajagopalan@Sun.COM 	 */
1429*13101SVenki.Rajagopalan@Sun.COM 	ret = eib_ibt_modify_chan_pkey(ss, vnic->vn_data_chan,
1430*13101SVenki.Rajagopalan@Sun.COM 	    vnic->vn_login_data.ld_vhub_pkey);
1431*13101SVenki.Rajagopalan@Sun.COM 	if (ret != EIB_E_SUCCESS) {
1432*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1433*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_set_partition: "
1434*13101SVenki.Rajagopalan@Sun.COM 		    "eib_ibt_modify_chan_pkey(vn_id=0x%x, DATA_CHAN, "
1435*13101SVenki.Rajagopalan@Sun.COM 		    "vhub_pkey=0x%x) failed", vnic->vn_id,
1436*13101SVenki.Rajagopalan@Sun.COM 		    vnic->vn_login_data.ld_vhub_pkey);
1437*13101SVenki.Rajagopalan@Sun.COM 		*err = EINVAL;
1438*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1439*13101SVenki.Rajagopalan@Sun.COM 	}
1440*13101SVenki.Rajagopalan@Sun.COM 
1441*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
1442*13101SVenki.Rajagopalan@Sun.COM }
1443*13101SVenki.Rajagopalan@Sun.COM 
1444*13101SVenki.Rajagopalan@Sun.COM static void
eib_vnic_make_vhub_mgid(uint8_t * mg_prefix,uint8_t mg_type,uint8_t * mcast_mac,uint8_t n_mac,uint8_t rss_hash,uint32_t vhub_id,ib_gid_t * mgid)1445*13101SVenki.Rajagopalan@Sun.COM eib_vnic_make_vhub_mgid(uint8_t *mg_prefix, uint8_t mg_type,
1446*13101SVenki.Rajagopalan@Sun.COM     uint8_t *mcast_mac, uint8_t n_mac, uint8_t rss_hash, uint32_t vhub_id,
1447*13101SVenki.Rajagopalan@Sun.COM     ib_gid_t *mgid)
1448*13101SVenki.Rajagopalan@Sun.COM {
1449*13101SVenki.Rajagopalan@Sun.COM 	eib_mgid_t em;
1450*13101SVenki.Rajagopalan@Sun.COM 	uint64_t dmac_mask;
1451*13101SVenki.Rajagopalan@Sun.COM 	uint64_t dmac = 0;
1452*13101SVenki.Rajagopalan@Sun.COM 	uint8_t *dmac_str = (uint8_t *)&dmac;
1453*13101SVenki.Rajagopalan@Sun.COM 	uint_t	vhub_id_nw;
1454*13101SVenki.Rajagopalan@Sun.COM 	uint8_t *vhub_id_str = (uint8_t *)&vhub_id_nw;
1455*13101SVenki.Rajagopalan@Sun.COM 
1456*13101SVenki.Rajagopalan@Sun.COM 	/*
1457*13101SVenki.Rajagopalan@Sun.COM 	 * Copy mgid prefix and type
1458*13101SVenki.Rajagopalan@Sun.COM 	 */
1459*13101SVenki.Rajagopalan@Sun.COM 	bcopy(mg_prefix, em.gd_spec.sp_mgid_prefix, FIP_MGID_PREFIX_LEN);
1460*13101SVenki.Rajagopalan@Sun.COM 	em.gd_spec.sp_type = mg_type;
1461*13101SVenki.Rajagopalan@Sun.COM 
1462*13101SVenki.Rajagopalan@Sun.COM 	/*
1463*13101SVenki.Rajagopalan@Sun.COM 	 * Take n_mac bits from mcast_mac and copy dmac
1464*13101SVenki.Rajagopalan@Sun.COM 	 */
1465*13101SVenki.Rajagopalan@Sun.COM 	bcopy(mcast_mac, dmac_str + 2, ETHERADDRL);
1466*13101SVenki.Rajagopalan@Sun.COM 	dmac_mask = ((uint64_t)1 << n_mac) - 1;
1467*13101SVenki.Rajagopalan@Sun.COM 	dmac_mask = htonll(dmac_mask);
1468*13101SVenki.Rajagopalan@Sun.COM 	dmac &= dmac_mask;
1469*13101SVenki.Rajagopalan@Sun.COM 	bcopy(dmac_str + 2, em.gd_spec.sp_dmac, ETHERADDRL);
1470*13101SVenki.Rajagopalan@Sun.COM 
1471*13101SVenki.Rajagopalan@Sun.COM 	/*
1472*13101SVenki.Rajagopalan@Sun.COM 	 * Copy rss hash and prepare vhub id from gw port id and vlan
1473*13101SVenki.Rajagopalan@Sun.COM 	 */
1474*13101SVenki.Rajagopalan@Sun.COM 	em.gd_spec.sp_rss_hash = rss_hash;
1475*13101SVenki.Rajagopalan@Sun.COM 
1476*13101SVenki.Rajagopalan@Sun.COM 	vhub_id_nw = htonl(vhub_id);
1477*13101SVenki.Rajagopalan@Sun.COM 	bcopy(vhub_id_str + 1, em.gd_spec.sp_vhub_id, FIP_VHUBID_LEN);
1478*13101SVenki.Rajagopalan@Sun.COM 
1479*13101SVenki.Rajagopalan@Sun.COM 	/*
1480*13101SVenki.Rajagopalan@Sun.COM 	 * Ok, now we've assembled the mgid as per EoIB spec. We now have to
1481*13101SVenki.Rajagopalan@Sun.COM 	 * represent it in the way Solaris IBTF wants it and return (sigh).
1482*13101SVenki.Rajagopalan@Sun.COM 	 */
1483*13101SVenki.Rajagopalan@Sun.COM 	mgid->gid_prefix = ntohll(em.gd_sol.gid_prefix);
1484*13101SVenki.Rajagopalan@Sun.COM 	mgid->gid_guid = ntohll(em.gd_sol.gid_guid);
1485*13101SVenki.Rajagopalan@Sun.COM }
1486*13101SVenki.Rajagopalan@Sun.COM 
1487*13101SVenki.Rajagopalan@Sun.COM static int
eib_vnic_attach_ctl_mcgs(eib_t * ss,eib_vnic_t * vnic,int * err)1488*13101SVenki.Rajagopalan@Sun.COM eib_vnic_attach_ctl_mcgs(eib_t *ss, eib_vnic_t *vnic, int *err)
1489*13101SVenki.Rajagopalan@Sun.COM {
1490*13101SVenki.Rajagopalan@Sun.COM 	/*
1491*13101SVenki.Rajagopalan@Sun.COM 	 * Get tb_vhub_table and tb_vhub_update allocated and ready before
1492*13101SVenki.Rajagopalan@Sun.COM 	 * attaching to the vhub table and vhub update mcgs
1493*13101SVenki.Rajagopalan@Sun.COM 	 */
1494*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_init_tables(ss, vnic);
1495*13101SVenki.Rajagopalan@Sun.COM 
1496*13101SVenki.Rajagopalan@Sun.COM 	if (eib_vnic_attach_vhub_update(ss, vnic) != EIB_E_SUCCESS) {
1497*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1498*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_attach_ctl_mcgs: "
1499*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_attach_vhub_update(vn_id=0x%x) failed",
1500*13101SVenki.Rajagopalan@Sun.COM 		    vnic->vn_id);
1501*13101SVenki.Rajagopalan@Sun.COM 
1502*13101SVenki.Rajagopalan@Sun.COM 		*err = EINVAL;
1503*13101SVenki.Rajagopalan@Sun.COM 		eib_vnic_fini_tables(ss, vnic, B_TRUE);
1504*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1505*13101SVenki.Rajagopalan@Sun.COM 	}
1506*13101SVenki.Rajagopalan@Sun.COM 
1507*13101SVenki.Rajagopalan@Sun.COM 	if (eib_vnic_attach_vhub_table(ss, vnic) != EIB_E_SUCCESS) {
1508*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1509*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_attach_ctl_mcgs: "
1510*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_attach_vhub_table(vn_id=0x%x) failed",
1511*13101SVenki.Rajagopalan@Sun.COM 		    vnic->vn_id);
1512*13101SVenki.Rajagopalan@Sun.COM 
1513*13101SVenki.Rajagopalan@Sun.COM 		*err = EINVAL;
1514*13101SVenki.Rajagopalan@Sun.COM 		eib_rb_vnic_attach_vhub_update(ss, vnic);
1515*13101SVenki.Rajagopalan@Sun.COM 		eib_vnic_fini_tables(ss, vnic, B_TRUE);
1516*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1517*13101SVenki.Rajagopalan@Sun.COM 	}
1518*13101SVenki.Rajagopalan@Sun.COM 
1519*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
1520*13101SVenki.Rajagopalan@Sun.COM }
1521*13101SVenki.Rajagopalan@Sun.COM 
1522*13101SVenki.Rajagopalan@Sun.COM static int
eib_vnic_attach_vhub_table(eib_t * ss,eib_vnic_t * vnic)1523*13101SVenki.Rajagopalan@Sun.COM eib_vnic_attach_vhub_table(eib_t *ss, eib_vnic_t *vnic)
1524*13101SVenki.Rajagopalan@Sun.COM {
1525*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = vnic->vn_ctl_chan;
1526*13101SVenki.Rajagopalan@Sun.COM 	eib_login_data_t *ld = &vnic->vn_login_data;
1527*13101SVenki.Rajagopalan@Sun.COM 	eib_mcg_t *mcg;
1528*13101SVenki.Rajagopalan@Sun.COM 	ibt_mcg_info_t *tbl_mcginfo;
1529*13101SVenki.Rajagopalan@Sun.COM 	ibt_mcg_attr_t mcg_attr;
1530*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
1531*13101SVenki.Rajagopalan@Sun.COM 	uint_t entries;
1532*13101SVenki.Rajagopalan@Sun.COM 
1533*13101SVenki.Rajagopalan@Sun.COM 	/*
1534*13101SVenki.Rajagopalan@Sun.COM 	 * Compose the MGID for receiving VHUB table
1535*13101SVenki.Rajagopalan@Sun.COM 	 */
1536*13101SVenki.Rajagopalan@Sun.COM 	bzero(&mcg_attr, sizeof (ibt_mcg_attr_t));
1537*13101SVenki.Rajagopalan@Sun.COM 
1538*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_make_vhub_mgid(ld->ld_gw_mgid_prefix,
1539*13101SVenki.Rajagopalan@Sun.COM 	    (uint8_t)EIB_MGID_VHUB_TABLE, eib_broadcast_mac, ld->ld_n_mac_mcgid,
1540*13101SVenki.Rajagopalan@Sun.COM 	    0, ld->ld_vhub_id, &(mcg_attr.mc_mgid));
1541*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_pkey = (ib_pkey_t)ld->ld_vhub_pkey;
1542*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_qkey = (ib_qkey_t)EIB_FIP_QKEY;
1543*13101SVenki.Rajagopalan@Sun.COM 
1544*13101SVenki.Rajagopalan@Sun.COM 	/*
1545*13101SVenki.Rajagopalan@Sun.COM 	 * Locate the multicast group for receiving vhub table
1546*13101SVenki.Rajagopalan@Sun.COM 	 */
1547*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_query_mcg(ss->ei_props->ep_sgid, &mcg_attr, 1,
1548*13101SVenki.Rajagopalan@Sun.COM 	    &tbl_mcginfo, &entries);
1549*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
1550*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1551*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_attach_vhub_table: "
1552*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_query_mcg(mgid=%llx.%llx, pkey=0x%x) failed, "
1553*13101SVenki.Rajagopalan@Sun.COM 		    "ret=%d", mcg_attr.mc_mgid.gid_prefix,
1554*13101SVenki.Rajagopalan@Sun.COM 		    mcg_attr.mc_mgid.gid_guid, mcg_attr.mc_pkey, ret);
1555*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1556*13101SVenki.Rajagopalan@Sun.COM 	}
1557*13101SVenki.Rajagopalan@Sun.COM 
1558*13101SVenki.Rajagopalan@Sun.COM 	/*
1559*13101SVenki.Rajagopalan@Sun.COM 	 * Allocate for and prepare the mcg to add to our list
1560*13101SVenki.Rajagopalan@Sun.COM 	 */
1561*13101SVenki.Rajagopalan@Sun.COM 	mcg = kmem_zalloc(sizeof (eib_mcg_t), KM_NOSLEEP);
1562*13101SVenki.Rajagopalan@Sun.COM 	if (mcg == NULL) {
1563*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1564*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_attach_vhub_table: "
1565*13101SVenki.Rajagopalan@Sun.COM 		    "no memory, failed to attach to vhub table "
1566*13101SVenki.Rajagopalan@Sun.COM 		    "(mgid=%llx.%llx, pkey=0x%x)", mcg_attr.mc_mgid.gid_prefix,
1567*13101SVenki.Rajagopalan@Sun.COM 		    mcg_attr.mc_mgid.gid_guid, mcg_attr.mc_pkey);
1568*13101SVenki.Rajagopalan@Sun.COM 		ibt_free_mcg_info(tbl_mcginfo, 1);
1569*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1570*13101SVenki.Rajagopalan@Sun.COM 	}
1571*13101SVenki.Rajagopalan@Sun.COM 
1572*13101SVenki.Rajagopalan@Sun.COM 	mcg->mg_next = NULL;
1573*13101SVenki.Rajagopalan@Sun.COM 	mcg->mg_rgid = ss->ei_props->ep_sgid;
1574*13101SVenki.Rajagopalan@Sun.COM 	mcg->mg_mgid = mcg_attr.mc_mgid;
1575*13101SVenki.Rajagopalan@Sun.COM 	mcg->mg_join_state = IB_MC_JSTATE_FULL;
1576*13101SVenki.Rajagopalan@Sun.COM 	mcg->mg_mcginfo = tbl_mcginfo;
1577*13101SVenki.Rajagopalan@Sun.COM 	bcopy(eib_broadcast_mac, mcg->mg_mac, ETHERADDRL);
1578*13101SVenki.Rajagopalan@Sun.COM 
1579*13101SVenki.Rajagopalan@Sun.COM 	/*
1580*13101SVenki.Rajagopalan@Sun.COM 	 * Join the multicast group
1581*13101SVenki.Rajagopalan@Sun.COM 	 */
1582*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_join_state = mcg->mg_join_state;
1583*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_flow = tbl_mcginfo->mc_adds_vect.av_flow;
1584*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_tclass = tbl_mcginfo->mc_adds_vect.av_tclass;
1585*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_sl = tbl_mcginfo->mc_adds_vect.av_srvl;
1586*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_scope = 0;	/* IB_MC_SCOPE_SUBNET_LOCAL perhaps ? */
1587*13101SVenki.Rajagopalan@Sun.COM 
1588*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_join_mcg(mcg->mg_rgid, &mcg_attr, tbl_mcginfo, NULL, NULL);
1589*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
1590*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1591*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_attach_vhub_table: "
1592*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_join_mcg(mgid=%llx.%llx, pkey=0x%x, jstate=0x%x) "
1593*13101SVenki.Rajagopalan@Sun.COM 		    "failed, ret=%d", mcg_attr.mc_mgid.gid_prefix,
1594*13101SVenki.Rajagopalan@Sun.COM 		    mcg_attr.mc_mgid.gid_guid, mcg_attr.mc_pkey,
1595*13101SVenki.Rajagopalan@Sun.COM 		    mcg_attr.mc_join_state, ret);
1596*13101SVenki.Rajagopalan@Sun.COM 
1597*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(mcg, sizeof (eib_mcg_t));
1598*13101SVenki.Rajagopalan@Sun.COM 		ibt_free_mcg_info(tbl_mcginfo, 1);
1599*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1600*13101SVenki.Rajagopalan@Sun.COM 	}
1601*13101SVenki.Rajagopalan@Sun.COM 
1602*13101SVenki.Rajagopalan@Sun.COM 	/*
1603*13101SVenki.Rajagopalan@Sun.COM 	 * Attach to the multicast group to receive tbl multicasts
1604*13101SVenki.Rajagopalan@Sun.COM 	 */
1605*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_attach_mcg(chan->ch_chan, tbl_mcginfo);
1606*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
1607*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1608*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_attach_vhub_table: "
1609*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_attach_mcg(mgid=%llx.%llx, pkey=0x%x) "
1610*13101SVenki.Rajagopalan@Sun.COM 		    "failed, ret=%d", mcg_attr.mc_mgid.gid_prefix,
1611*13101SVenki.Rajagopalan@Sun.COM 		    mcg_attr.mc_mgid.gid_guid, mcg_attr.mc_pkey);
1612*13101SVenki.Rajagopalan@Sun.COM 
1613*13101SVenki.Rajagopalan@Sun.COM 		(void) ibt_leave_mcg(mcg->mg_rgid, mcg->mg_mgid,
1614*13101SVenki.Rajagopalan@Sun.COM 		    eib_reserved_gid, mcg->mg_join_state);
1615*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(mcg, sizeof (eib_mcg_t));
1616*13101SVenki.Rajagopalan@Sun.COM 		ibt_free_mcg_info(tbl_mcginfo, 1);
1617*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1618*13101SVenki.Rajagopalan@Sun.COM 	}
1619*13101SVenki.Rajagopalan@Sun.COM 
1620*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&chan->ch_vhub_lock);
1621*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_vhub_table = mcg;
1622*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&chan->ch_vhub_lock);
1623*13101SVenki.Rajagopalan@Sun.COM 
1624*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
1625*13101SVenki.Rajagopalan@Sun.COM }
1626*13101SVenki.Rajagopalan@Sun.COM 
1627*13101SVenki.Rajagopalan@Sun.COM static int
eib_vnic_attach_vhub_update(eib_t * ss,eib_vnic_t * vnic)1628*13101SVenki.Rajagopalan@Sun.COM eib_vnic_attach_vhub_update(eib_t *ss, eib_vnic_t *vnic)
1629*13101SVenki.Rajagopalan@Sun.COM {
1630*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = vnic->vn_ctl_chan;
1631*13101SVenki.Rajagopalan@Sun.COM 	eib_login_data_t *ld = &vnic->vn_login_data;
1632*13101SVenki.Rajagopalan@Sun.COM 	eib_mcg_t *mcg;
1633*13101SVenki.Rajagopalan@Sun.COM 	ibt_mcg_info_t *upd_mcginfo;
1634*13101SVenki.Rajagopalan@Sun.COM 	ibt_mcg_attr_t mcg_attr;
1635*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
1636*13101SVenki.Rajagopalan@Sun.COM 	uint_t entries;
1637*13101SVenki.Rajagopalan@Sun.COM 
1638*13101SVenki.Rajagopalan@Sun.COM 	/*
1639*13101SVenki.Rajagopalan@Sun.COM 	 * Compose the MGID for receiving VHUB updates
1640*13101SVenki.Rajagopalan@Sun.COM 	 */
1641*13101SVenki.Rajagopalan@Sun.COM 	bzero(&mcg_attr, sizeof (ibt_mcg_attr_t));
1642*13101SVenki.Rajagopalan@Sun.COM 
1643*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_make_vhub_mgid(ld->ld_gw_mgid_prefix,
1644*13101SVenki.Rajagopalan@Sun.COM 	    (uint8_t)EIB_MGID_VHUB_UPDATE, eib_broadcast_mac,
1645*13101SVenki.Rajagopalan@Sun.COM 	    ld->ld_n_mac_mcgid, 0, ld->ld_vhub_id, &(mcg_attr.mc_mgid));
1646*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_pkey = (ib_pkey_t)ld->ld_vhub_pkey;
1647*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_qkey = (ib_qkey_t)EIB_FIP_QKEY;
1648*13101SVenki.Rajagopalan@Sun.COM 
1649*13101SVenki.Rajagopalan@Sun.COM 	/*
1650*13101SVenki.Rajagopalan@Sun.COM 	 * Locate the multicast group for receiving vhub updates
1651*13101SVenki.Rajagopalan@Sun.COM 	 */
1652*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_query_mcg(ss->ei_props->ep_sgid, &mcg_attr, 1,
1653*13101SVenki.Rajagopalan@Sun.COM 	    &upd_mcginfo, &entries);
1654*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
1655*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1656*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_attach_vhub_update: "
1657*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_query_mcg(mgid=%llx.%llx, pkey=0x%x) failed, "
1658*13101SVenki.Rajagopalan@Sun.COM 		    "ret=%d", mcg_attr.mc_mgid.gid_prefix,
1659*13101SVenki.Rajagopalan@Sun.COM 		    mcg_attr.mc_mgid.gid_guid, mcg_attr.mc_pkey, ret);
1660*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1661*13101SVenki.Rajagopalan@Sun.COM 	}
1662*13101SVenki.Rajagopalan@Sun.COM 
1663*13101SVenki.Rajagopalan@Sun.COM 	/*
1664*13101SVenki.Rajagopalan@Sun.COM 	 * Allocate for and prepare the mcg to add to our list
1665*13101SVenki.Rajagopalan@Sun.COM 	 */
1666*13101SVenki.Rajagopalan@Sun.COM 	mcg = kmem_zalloc(sizeof (eib_mcg_t), KM_NOSLEEP);
1667*13101SVenki.Rajagopalan@Sun.COM 	if (mcg == NULL) {
1668*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1669*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_attach_vhub_update: "
1670*13101SVenki.Rajagopalan@Sun.COM 		    "no memory, failed to attach to vhub update "
1671*13101SVenki.Rajagopalan@Sun.COM 		    "(mgid=%llx.%llx, pkey=0x%x)", mcg_attr.mc_mgid.gid_prefix,
1672*13101SVenki.Rajagopalan@Sun.COM 		    mcg_attr.mc_mgid.gid_guid, mcg_attr.mc_pkey);
1673*13101SVenki.Rajagopalan@Sun.COM 
1674*13101SVenki.Rajagopalan@Sun.COM 		ibt_free_mcg_info(upd_mcginfo, 1);
1675*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1676*13101SVenki.Rajagopalan@Sun.COM 	}
1677*13101SVenki.Rajagopalan@Sun.COM 
1678*13101SVenki.Rajagopalan@Sun.COM 	mcg->mg_next = NULL;
1679*13101SVenki.Rajagopalan@Sun.COM 	mcg->mg_rgid = ss->ei_props->ep_sgid;
1680*13101SVenki.Rajagopalan@Sun.COM 	mcg->mg_mgid = mcg_attr.mc_mgid;
1681*13101SVenki.Rajagopalan@Sun.COM 	mcg->mg_join_state = IB_MC_JSTATE_FULL;
1682*13101SVenki.Rajagopalan@Sun.COM 	mcg->mg_mcginfo = upd_mcginfo;
1683*13101SVenki.Rajagopalan@Sun.COM 	bcopy(eib_broadcast_mac, mcg->mg_mac, ETHERADDRL);
1684*13101SVenki.Rajagopalan@Sun.COM 
1685*13101SVenki.Rajagopalan@Sun.COM 	/*
1686*13101SVenki.Rajagopalan@Sun.COM 	 * Join the multicast group
1687*13101SVenki.Rajagopalan@Sun.COM 	 */
1688*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_join_state = mcg->mg_join_state;
1689*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_flow = upd_mcginfo->mc_adds_vect.av_flow;
1690*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_tclass = upd_mcginfo->mc_adds_vect.av_tclass;
1691*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_sl = upd_mcginfo->mc_adds_vect.av_srvl;
1692*13101SVenki.Rajagopalan@Sun.COM 	mcg_attr.mc_scope = 0;	/* IB_MC_SCOPE_SUBNET_LOCAL perhaps ? */
1693*13101SVenki.Rajagopalan@Sun.COM 
1694*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_join_mcg(mcg->mg_rgid, &mcg_attr, upd_mcginfo, NULL, NULL);
1695*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
1696*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1697*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_attach_vhub_update: "
1698*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_join_mcg(mgid=%llx.%llx, pkey=0x%x, jstate=0x%x) "
1699*13101SVenki.Rajagopalan@Sun.COM 		    "failed, ret=%d", mcg_attr.mc_mgid.gid_prefix,
1700*13101SVenki.Rajagopalan@Sun.COM 		    mcg_attr.mc_mgid.gid_guid, mcg_attr.mc_pkey,
1701*13101SVenki.Rajagopalan@Sun.COM 		    mcg_attr.mc_join_state, ret);
1702*13101SVenki.Rajagopalan@Sun.COM 
1703*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(mcg, sizeof (eib_mcg_t));
1704*13101SVenki.Rajagopalan@Sun.COM 		ibt_free_mcg_info(upd_mcginfo, 1);
1705*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1706*13101SVenki.Rajagopalan@Sun.COM 	}
1707*13101SVenki.Rajagopalan@Sun.COM 
1708*13101SVenki.Rajagopalan@Sun.COM 	/*
1709*13101SVenki.Rajagopalan@Sun.COM 	 * Attach to the multicast group to receive upd multicasts
1710*13101SVenki.Rajagopalan@Sun.COM 	 */
1711*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_attach_mcg(chan->ch_chan, upd_mcginfo);
1712*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
1713*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1714*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_attach_vhub_update: "
1715*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_attach_mcg(mgid=%llx.%llx, pkey=0x%x) "
1716*13101SVenki.Rajagopalan@Sun.COM 		    "failed, ret=%d", mcg_attr.mc_mgid.gid_prefix,
1717*13101SVenki.Rajagopalan@Sun.COM 		    mcg_attr.mc_mgid.gid_guid, mcg_attr.mc_pkey);
1718*13101SVenki.Rajagopalan@Sun.COM 
1719*13101SVenki.Rajagopalan@Sun.COM 		(void) ibt_leave_mcg(mcg->mg_rgid, mcg->mg_mgid,
1720*13101SVenki.Rajagopalan@Sun.COM 		    eib_reserved_gid, mcg->mg_join_state);
1721*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(mcg, sizeof (eib_mcg_t));
1722*13101SVenki.Rajagopalan@Sun.COM 		ibt_free_mcg_info(upd_mcginfo, 1);
1723*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1724*13101SVenki.Rajagopalan@Sun.COM 	}
1725*13101SVenki.Rajagopalan@Sun.COM 
1726*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&chan->ch_vhub_lock);
1727*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_vhub_update = mcg;
1728*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&chan->ch_vhub_lock);
1729*13101SVenki.Rajagopalan@Sun.COM 
1730*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
1731*13101SVenki.Rajagopalan@Sun.COM }
1732*13101SVenki.Rajagopalan@Sun.COM 
1733*13101SVenki.Rajagopalan@Sun.COM static void
eib_vnic_start_keepalives(eib_t * ss,eib_vnic_t * vnic)1734*13101SVenki.Rajagopalan@Sun.COM eib_vnic_start_keepalives(eib_t *ss, eib_vnic_t *vnic)
1735*13101SVenki.Rajagopalan@Sun.COM {
1736*13101SVenki.Rajagopalan@Sun.COM 	eib_ka_vnics_t *kav;
1737*13101SVenki.Rajagopalan@Sun.COM 	eib_ka_vnics_t *elem;
1738*13101SVenki.Rajagopalan@Sun.COM 	int err;
1739*13101SVenki.Rajagopalan@Sun.COM 
1740*13101SVenki.Rajagopalan@Sun.COM 	kav = kmem_zalloc(sizeof (eib_ka_vnics_t), KM_SLEEP);
1741*13101SVenki.Rajagopalan@Sun.COM 	kav->ka_vnic = vnic;
1742*13101SVenki.Rajagopalan@Sun.COM 	kav->ka_next = NULL;
1743*13101SVenki.Rajagopalan@Sun.COM 
1744*13101SVenki.Rajagopalan@Sun.COM 	/*
1745*13101SVenki.Rajagopalan@Sun.COM 	 * Send the first keepalive and then queue this vnic up with
1746*13101SVenki.Rajagopalan@Sun.COM 	 * the keepalives manager
1747*13101SVenki.Rajagopalan@Sun.COM 	 */
1748*13101SVenki.Rajagopalan@Sun.COM 	(void) eib_fip_heartbeat(ss, vnic, &err);
1749*13101SVenki.Rajagopalan@Sun.COM 
1750*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_ka_vnics_lock);
1751*13101SVenki.Rajagopalan@Sun.COM 	for (elem = ss->ei_ka_vnics; elem; elem = elem->ka_next) {
1752*13101SVenki.Rajagopalan@Sun.COM 		if (elem->ka_next == NULL)
1753*13101SVenki.Rajagopalan@Sun.COM 			break;
1754*13101SVenki.Rajagopalan@Sun.COM 	}
1755*13101SVenki.Rajagopalan@Sun.COM 	if (elem) {
1756*13101SVenki.Rajagopalan@Sun.COM 		elem->ka_next = kav;
1757*13101SVenki.Rajagopalan@Sun.COM 	} else {
1758*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_ka_vnics = kav;
1759*13101SVenki.Rajagopalan@Sun.COM 	}
1760*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_ka_vnics_lock);
1761*13101SVenki.Rajagopalan@Sun.COM }
1762*13101SVenki.Rajagopalan@Sun.COM 
1763*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
1764*13101SVenki.Rajagopalan@Sun.COM static int
eib_vnic_lookup_dest(eib_vnic_t * vnic,uint8_t * dmac,uint16_t vlan,eib_vhub_map_t * ucast,ibt_mcg_info_t * mcast,int * dtype)1765*13101SVenki.Rajagopalan@Sun.COM eib_vnic_lookup_dest(eib_vnic_t *vnic, uint8_t *dmac, uint16_t vlan,
1766*13101SVenki.Rajagopalan@Sun.COM     eib_vhub_map_t *ucast, ibt_mcg_info_t *mcast, int *dtype)
1767*13101SVenki.Rajagopalan@Sun.COM {
1768*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = vnic->vn_ss;
1769*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_map_t *elem;
1770*13101SVenki.Rajagopalan@Sun.COM 	eib_mcg_t *mcg;
1771*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = vnic->vn_data_chan;
1772*13101SVenki.Rajagopalan@Sun.COM 	eib_login_data_t *ld = &vnic->vn_login_data;
1773*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_map_t *gw;
1774*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_table_t *tbl;
1775*13101SVenki.Rajagopalan@Sun.COM 	uint8_t bkt = (dmac[ETHERADDRL-1]) % EIB_TB_NBUCKETS;
1776*13101SVenki.Rajagopalan@Sun.COM 	ib_gid_t mgid;
1777*13101SVenki.Rajagopalan@Sun.COM 
1778*13101SVenki.Rajagopalan@Sun.COM 	/*
1779*13101SVenki.Rajagopalan@Sun.COM 	 * If this was a unicast dmac, locate the vhub entry matching the
1780*13101SVenki.Rajagopalan@Sun.COM 	 * unicast dmac in our vhub table.  If it's not found, return the
1781*13101SVenki.Rajagopalan@Sun.COM 	 * gateway entry
1782*13101SVenki.Rajagopalan@Sun.COM 	 */
1783*13101SVenki.Rajagopalan@Sun.COM 	if (EIB_UNICAST_MAC(dmac)) {
1784*13101SVenki.Rajagopalan@Sun.COM 
1785*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&vnic->vn_lock);
1786*13101SVenki.Rajagopalan@Sun.COM 		if ((tbl = vnic->vn_vhub_table) == NULL) {
1787*13101SVenki.Rajagopalan@Sun.COM 			mutex_exit(&vnic->vn_lock);
1788*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_FAILURE);
1789*13101SVenki.Rajagopalan@Sun.COM 		}
1790*13101SVenki.Rajagopalan@Sun.COM 
1791*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&tbl->tb_lock);
1792*13101SVenki.Rajagopalan@Sun.COM 		gw = tbl->tb_gateway;
1793*13101SVenki.Rajagopalan@Sun.COM 		for (elem = tbl->tb_vnic_entry[bkt]; elem != NULL;
1794*13101SVenki.Rajagopalan@Sun.COM 		    elem = elem->mp_next) {
1795*13101SVenki.Rajagopalan@Sun.COM 			if (bcmp(elem->mp_mac, dmac, ETHERADDRL) == 0)
1796*13101SVenki.Rajagopalan@Sun.COM 				break;
1797*13101SVenki.Rajagopalan@Sun.COM 		}
1798*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&tbl->tb_lock);
1799*13101SVenki.Rajagopalan@Sun.COM 
1800*13101SVenki.Rajagopalan@Sun.COM 		if ((elem == NULL) && (gw == NULL)) {
1801*13101SVenki.Rajagopalan@Sun.COM 			mutex_exit(&vnic->vn_lock);
1802*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_FAILURE);
1803*13101SVenki.Rajagopalan@Sun.COM 		}
1804*13101SVenki.Rajagopalan@Sun.COM 
1805*13101SVenki.Rajagopalan@Sun.COM 		*dtype = EIB_TX_UNICAST;
1806*13101SVenki.Rajagopalan@Sun.COM 		if (elem) {
1807*13101SVenki.Rajagopalan@Sun.COM 			bcopy(elem, ucast, sizeof (eib_vhub_map_t));
1808*13101SVenki.Rajagopalan@Sun.COM 		} else {
1809*13101SVenki.Rajagopalan@Sun.COM 			bcopy(gw, ucast, sizeof (eib_vhub_map_t));
1810*13101SVenki.Rajagopalan@Sun.COM 		}
1811*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&vnic->vn_lock);
1812*13101SVenki.Rajagopalan@Sun.COM 
1813*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_SUCCESS);
1814*13101SVenki.Rajagopalan@Sun.COM 	}
1815*13101SVenki.Rajagopalan@Sun.COM 
1816*13101SVenki.Rajagopalan@Sun.COM 	/*
1817*13101SVenki.Rajagopalan@Sun.COM 	 * Is it a broadcast ?
1818*13101SVenki.Rajagopalan@Sun.COM 	 */
1819*13101SVenki.Rajagopalan@Sun.COM 	*dtype = (bcmp(dmac, eib_broadcast_mac, ETHERADDRL) == 0) ?
1820*13101SVenki.Rajagopalan@Sun.COM 	    EIB_TX_BROADCAST : EIB_TX_MULTICAST;
1821*13101SVenki.Rajagopalan@Sun.COM 
1822*13101SVenki.Rajagopalan@Sun.COM 	/*
1823*13101SVenki.Rajagopalan@Sun.COM 	 * If this was a multicast dmac, prepare the mgid and look for it
1824*13101SVenki.Rajagopalan@Sun.COM 	 * in the list of mcgs we've joined and use the address vector from
1825*13101SVenki.Rajagopalan@Sun.COM 	 * the mcginfo stored there.
1826*13101SVenki.Rajagopalan@Sun.COM 	 *
1827*13101SVenki.Rajagopalan@Sun.COM 	 * Note that since we don't have a way to associate each vlan with
1828*13101SVenki.Rajagopalan@Sun.COM 	 * the mcg (see eib_m_multicast()), we'll prepare the mgid to use
1829*13101SVenki.Rajagopalan@Sun.COM 	 * the broadcast channel all the time.
1830*13101SVenki.Rajagopalan@Sun.COM 	 */
1831*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_make_vhub_mgid(ld->ld_gw_mgid_prefix,
1832*13101SVenki.Rajagopalan@Sun.COM 	    (uint8_t)EIB_MGID_VHUB_DATA, eib_broadcast_mac, ld->ld_n_mac_mcgid,
1833*13101SVenki.Rajagopalan@Sun.COM 	    0, ld->ld_vhub_id, &mgid);
1834*13101SVenki.Rajagopalan@Sun.COM 
1835*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&chan->ch_vhub_lock);
1836*13101SVenki.Rajagopalan@Sun.COM 	for (mcg = chan->ch_vhub_data; mcg; mcg = mcg->mg_next) {
1837*13101SVenki.Rajagopalan@Sun.COM 		if ((mcg->mg_mgid.gid_prefix == mgid.gid_prefix) &&
1838*13101SVenki.Rajagopalan@Sun.COM 		    (mcg->mg_mgid.gid_guid == mgid.gid_guid)) {
1839*13101SVenki.Rajagopalan@Sun.COM 			break;
1840*13101SVenki.Rajagopalan@Sun.COM 		}
1841*13101SVenki.Rajagopalan@Sun.COM 	}
1842*13101SVenki.Rajagopalan@Sun.COM 	if (mcg == NULL) {
1843*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&chan->ch_vhub_lock);
1844*13101SVenki.Rajagopalan@Sun.COM 
1845*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_vnic_lookup_dest: "
1846*13101SVenki.Rajagopalan@Sun.COM 		    "could not find mgid %llx.%llx",
1847*13101SVenki.Rajagopalan@Sun.COM 		    mgid.gid_prefix, mgid.gid_guid);
1848*13101SVenki.Rajagopalan@Sun.COM 
1849*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1850*13101SVenki.Rajagopalan@Sun.COM 	}
1851*13101SVenki.Rajagopalan@Sun.COM 
1852*13101SVenki.Rajagopalan@Sun.COM 	bcopy(mcg->mg_mcginfo, mcast, sizeof (ibt_mcg_info_t));
1853*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&chan->ch_vhub_lock);
1854*13101SVenki.Rajagopalan@Sun.COM 
1855*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
1856*13101SVenki.Rajagopalan@Sun.COM }
1857*13101SVenki.Rajagopalan@Sun.COM 
1858*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
1859*13101SVenki.Rajagopalan@Sun.COM static void
eib_vnic_leave_all_data_mcgs(eib_t * ss,eib_vnic_t * vnic)1860*13101SVenki.Rajagopalan@Sun.COM eib_vnic_leave_all_data_mcgs(eib_t *ss, eib_vnic_t *vnic)
1861*13101SVenki.Rajagopalan@Sun.COM {
1862*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = vnic->vn_data_chan;
1863*13101SVenki.Rajagopalan@Sun.COM 	eib_mcg_t *mcglist;
1864*13101SVenki.Rajagopalan@Sun.COM 	eib_mcg_t *mcg;
1865*13101SVenki.Rajagopalan@Sun.COM 	eib_mcg_t *nxt = NULL;
1866*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
1867*13101SVenki.Rajagopalan@Sun.COM 
1868*13101SVenki.Rajagopalan@Sun.COM 	/*
1869*13101SVenki.Rajagopalan@Sun.COM 	 * First, take the ch_vhub_data mcg chain out of chan
1870*13101SVenki.Rajagopalan@Sun.COM 	 */
1871*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&chan->ch_vhub_lock);
1872*13101SVenki.Rajagopalan@Sun.COM 	mcglist = chan->ch_vhub_data;
1873*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_vhub_data = NULL;
1874*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&chan->ch_vhub_lock);
1875*13101SVenki.Rajagopalan@Sun.COM 
1876*13101SVenki.Rajagopalan@Sun.COM 	/*
1877*13101SVenki.Rajagopalan@Sun.COM 	 * Go through the chain of mcgs we've joined, detach the qp from the
1878*13101SVenki.Rajagopalan@Sun.COM 	 * mcg, leave the group and free all associated stuff
1879*13101SVenki.Rajagopalan@Sun.COM 	 */
1880*13101SVenki.Rajagopalan@Sun.COM 	for (mcg = mcglist; mcg != NULL; mcg = nxt) {
1881*13101SVenki.Rajagopalan@Sun.COM 		nxt = mcg->mg_next;
1882*13101SVenki.Rajagopalan@Sun.COM 
1883*13101SVenki.Rajagopalan@Sun.COM 		ret = ibt_detach_mcg(chan->ch_chan, mcg->mg_mcginfo);
1884*13101SVenki.Rajagopalan@Sun.COM 		if (ret != IBT_SUCCESS) {
1885*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
1886*13101SVenki.Rajagopalan@Sun.COM 			    "eib_vnic_leave_all_data_mcgs: "
1887*13101SVenki.Rajagopalan@Sun.COM 			    "ibt_detach_mcg(chan_hdl=0x%llx, mcinfo=0x%llx, "
1888*13101SVenki.Rajagopalan@Sun.COM 			    "mgid=%llx.%llx) failed, ret=%d", chan->ch_chan,
1889*13101SVenki.Rajagopalan@Sun.COM 			    mcg->mg_mcginfo, mcg->mg_mgid.gid_prefix,
1890*13101SVenki.Rajagopalan@Sun.COM 			    mcg->mg_mgid.gid_guid, ret);
1891*13101SVenki.Rajagopalan@Sun.COM 		}
1892*13101SVenki.Rajagopalan@Sun.COM 
1893*13101SVenki.Rajagopalan@Sun.COM 		ret = ibt_leave_mcg(mcg->mg_rgid, mcg->mg_mgid,
1894*13101SVenki.Rajagopalan@Sun.COM 		    eib_reserved_gid, mcg->mg_join_state);
1895*13101SVenki.Rajagopalan@Sun.COM 		if (ret != IBT_SUCCESS) {
1896*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
1897*13101SVenki.Rajagopalan@Sun.COM 			    "eib_vnic_leave_all_data_mcgs: "
1898*13101SVenki.Rajagopalan@Sun.COM 			    "ibt_leave_mcg(mgid=%llx.%llx, jstate=0x%x) "
1899*13101SVenki.Rajagopalan@Sun.COM 			    "failed, ret=%d", mcg->mg_mgid.gid_prefix,
1900*13101SVenki.Rajagopalan@Sun.COM 			    mcg->mg_mgid.gid_guid, mcg->mg_join_state, ret);
1901*13101SVenki.Rajagopalan@Sun.COM 		}
1902*13101SVenki.Rajagopalan@Sun.COM 
1903*13101SVenki.Rajagopalan@Sun.COM 		if (mcg->mg_mcginfo)
1904*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(mcg->mg_mcginfo, sizeof (ibt_mcg_info_t));
1905*13101SVenki.Rajagopalan@Sun.COM 
1906*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(mcg, sizeof (eib_mcg_t));
1907*13101SVenki.Rajagopalan@Sun.COM 	}
1908*13101SVenki.Rajagopalan@Sun.COM }
1909*13101SVenki.Rajagopalan@Sun.COM 
1910*13101SVenki.Rajagopalan@Sun.COM static void
eib_vnic_rejoin_data_mcgs(eib_t * ss,eib_vnic_t * vnic)1911*13101SVenki.Rajagopalan@Sun.COM eib_vnic_rejoin_data_mcgs(eib_t *ss, eib_vnic_t *vnic)
1912*13101SVenki.Rajagopalan@Sun.COM {
1913*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = vnic->vn_data_chan;
1914*13101SVenki.Rajagopalan@Sun.COM 	eib_mcg_t *mcglist;
1915*13101SVenki.Rajagopalan@Sun.COM 	eib_mcg_t *mcg;
1916*13101SVenki.Rajagopalan@Sun.COM 	eib_mcg_t *next;
1917*13101SVenki.Rajagopalan@Sun.COM 	int err;
1918*13101SVenki.Rajagopalan@Sun.COM 
1919*13101SVenki.Rajagopalan@Sun.COM 	/*
1920*13101SVenki.Rajagopalan@Sun.COM 	 * Grab the current list of mcgs
1921*13101SVenki.Rajagopalan@Sun.COM 	 */
1922*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&chan->ch_vhub_lock);
1923*13101SVenki.Rajagopalan@Sun.COM 	mcglist = chan->ch_vhub_data;
1924*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_vhub_data = NULL;
1925*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&chan->ch_vhub_lock);
1926*13101SVenki.Rajagopalan@Sun.COM 
1927*13101SVenki.Rajagopalan@Sun.COM 	/*
1928*13101SVenki.Rajagopalan@Sun.COM 	 * When rejoin data mcgs is called, we may not even be marked as
1929*13101SVenki.Rajagopalan@Sun.COM 	 * joined in SM's records.  But we still have to leave the old
1930*13101SVenki.Rajagopalan@Sun.COM 	 * one first to prevent leaks in ibtf.
1931*13101SVenki.Rajagopalan@Sun.COM 	 */
1932*13101SVenki.Rajagopalan@Sun.COM 	for (mcg = mcglist; mcg != NULL; mcg = next) {
1933*13101SVenki.Rajagopalan@Sun.COM 		next = mcg->mg_next;
1934*13101SVenki.Rajagopalan@Sun.COM 		mcg->mg_next = NULL;
1935*13101SVenki.Rajagopalan@Sun.COM 
1936*13101SVenki.Rajagopalan@Sun.COM 		(void) ibt_detach_mcg(chan->ch_chan, mcg->mg_mcginfo);
1937*13101SVenki.Rajagopalan@Sun.COM 		(void) ibt_leave_mcg(mcg->mg_rgid, mcg->mg_mgid,
1938*13101SVenki.Rajagopalan@Sun.COM 		    eib_reserved_gid, mcg->mg_join_state);
1939*13101SVenki.Rajagopalan@Sun.COM 
1940*13101SVenki.Rajagopalan@Sun.COM 		if (eib_vnic_join_data_mcg(ss, vnic, mcg->mg_mac, B_TRUE,
1941*13101SVenki.Rajagopalan@Sun.COM 		    &err) != EIB_E_SUCCESS) {
1942*13101SVenki.Rajagopalan@Sun.COM 			uint8_t *m;
1943*13101SVenki.Rajagopalan@Sun.COM 
1944*13101SVenki.Rajagopalan@Sun.COM 			m = mcg->mg_mac;
1945*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
1946*13101SVenki.Rajagopalan@Sun.COM 			    "eib_vnic_rejoin_data_mcgs: "
1947*13101SVenki.Rajagopalan@Sun.COM 			    "eib_vnic_join_data_mcg(mcmac=%x:%x:%x:%x:%x:%x) "
1948*13101SVenki.Rajagopalan@Sun.COM 			    "failed, ret=%d", m[0], m[1], m[2], m[3],
1949*13101SVenki.Rajagopalan@Sun.COM 			    m[4], m[5], err);
1950*13101SVenki.Rajagopalan@Sun.COM 		}
1951*13101SVenki.Rajagopalan@Sun.COM 		if (mcg->mg_mcginfo) {
1952*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(mcg->mg_mcginfo, sizeof (ibt_mcg_info_t));
1953*13101SVenki.Rajagopalan@Sun.COM 		}
1954*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(mcg, sizeof (eib_mcg_t));
1955*13101SVenki.Rajagopalan@Sun.COM 	}
1956*13101SVenki.Rajagopalan@Sun.COM }
1957*13101SVenki.Rajagopalan@Sun.COM 
1958*13101SVenki.Rajagopalan@Sun.COM static void
eib_vnic_reattach_ctl_mcgs(eib_t * ss,eib_vnic_t * vnic)1959*13101SVenki.Rajagopalan@Sun.COM eib_vnic_reattach_ctl_mcgs(eib_t *ss, eib_vnic_t *vnic)
1960*13101SVenki.Rajagopalan@Sun.COM {
1961*13101SVenki.Rajagopalan@Sun.COM 	/*
1962*13101SVenki.Rajagopalan@Sun.COM 	 * For reattaching to control mcgs, we will not reinitialize the
1963*13101SVenki.Rajagopalan@Sun.COM 	 * vhub table/vhub update we've constructed.  We'll simply detach
1964*13101SVenki.Rajagopalan@Sun.COM 	 * from the table and update mcgs and reattach to them.  Hopefully,
1965*13101SVenki.Rajagopalan@Sun.COM 	 * we wouldn't have missed any updates and won't have to restart
1966*13101SVenki.Rajagopalan@Sun.COM 	 * the vnic.
1967*13101SVenki.Rajagopalan@Sun.COM 	 */
1968*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_vnic_attach_vhub_table(ss, vnic);
1969*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_vnic_attach_vhub_update(ss, vnic);
1970*13101SVenki.Rajagopalan@Sun.COM 
1971*13101SVenki.Rajagopalan@Sun.COM 	if (eib_vnic_attach_vhub_update(ss, vnic) != EIB_E_SUCCESS) {
1972*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1973*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_reattach_ctl_mcgs: "
1974*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_attach_vhub_update(vn_id=0x%x) failed",
1975*13101SVenki.Rajagopalan@Sun.COM 		    vnic->vn_id);
1976*13101SVenki.Rajagopalan@Sun.COM 	}
1977*13101SVenki.Rajagopalan@Sun.COM 
1978*13101SVenki.Rajagopalan@Sun.COM 	if (eib_vnic_attach_vhub_table(ss, vnic) != EIB_E_SUCCESS) {
1979*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
1980*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_reattach_ctl_mcgs: "
1981*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_attach_vhub_table(vn_id=0x%x) failed",
1982*13101SVenki.Rajagopalan@Sun.COM 		    vnic->vn_id);
1983*13101SVenki.Rajagopalan@Sun.COM 
1984*13101SVenki.Rajagopalan@Sun.COM 		eib_rb_vnic_attach_vhub_update(ss, vnic);
1985*13101SVenki.Rajagopalan@Sun.COM 	}
1986*13101SVenki.Rajagopalan@Sun.COM }
1987*13101SVenki.Rajagopalan@Sun.COM 
1988*13101SVenki.Rajagopalan@Sun.COM static void
eib_rb_vnic_create_common(eib_t * ss,eib_vnic_t * vnic,uint_t progress)1989*13101SVenki.Rajagopalan@Sun.COM eib_rb_vnic_create_common(eib_t *ss, eib_vnic_t *vnic, uint_t progress)
1990*13101SVenki.Rajagopalan@Sun.COM {
1991*13101SVenki.Rajagopalan@Sun.COM 	int err;
1992*13101SVenki.Rajagopalan@Sun.COM 
1993*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_vnic_lock);
1994*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_vnic[vnic->vn_instance] = NULL;
1995*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_vnic_pending = NULL;
1996*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_vnic_lock);
1997*13101SVenki.Rajagopalan@Sun.COM 
1998*13101SVenki.Rajagopalan@Sun.COM 	if (progress & EIB_VNIC_BROADCAST_JOINED) {
1999*13101SVenki.Rajagopalan@Sun.COM 		eib_vnic_leave_all_data_mcgs(ss, vnic);
2000*13101SVenki.Rajagopalan@Sun.COM 	}
2001*13101SVenki.Rajagopalan@Sun.COM 
2002*13101SVenki.Rajagopalan@Sun.COM 	if (progress & EIB_VNIC_KEEPALIVES_STARTED) {
2003*13101SVenki.Rajagopalan@Sun.COM 		eib_rb_vnic_start_keepalives(ss, vnic);
2004*13101SVenki.Rajagopalan@Sun.COM 	}
2005*13101SVenki.Rajagopalan@Sun.COM 
2006*13101SVenki.Rajagopalan@Sun.COM 	if (progress & EIB_VNIC_ATTACHED_TO_CTL_MCGS) {
2007*13101SVenki.Rajagopalan@Sun.COM 		eib_rb_vnic_attach_ctl_mcgs(ss, vnic);
2008*13101SVenki.Rajagopalan@Sun.COM 	}
2009*13101SVenki.Rajagopalan@Sun.COM 
2010*13101SVenki.Rajagopalan@Sun.COM 	if (progress & EIB_VNIC_LOGIN_DONE) {
2011*13101SVenki.Rajagopalan@Sun.COM 		(void) eib_fip_logout(ss, vnic, &err);
2012*13101SVenki.Rajagopalan@Sun.COM 	}
2013*13101SVenki.Rajagopalan@Sun.COM 
2014*13101SVenki.Rajagopalan@Sun.COM 	if (progress & EIB_VNIC_DATAQP_CREATED) {
2015*13101SVenki.Rajagopalan@Sun.COM 		eib_rb_data_create_qp(ss, vnic);
2016*13101SVenki.Rajagopalan@Sun.COM 	}
2017*13101SVenki.Rajagopalan@Sun.COM 
2018*13101SVenki.Rajagopalan@Sun.COM 	if (progress & EIB_VNIC_CTLQP_CREATED) {
2019*13101SVenki.Rajagopalan@Sun.COM 		eib_rb_ctl_create_qp(ss, vnic);
2020*13101SVenki.Rajagopalan@Sun.COM 	}
2021*13101SVenki.Rajagopalan@Sun.COM }
2022*13101SVenki.Rajagopalan@Sun.COM 
2023*13101SVenki.Rajagopalan@Sun.COM static void
eib_rb_vnic_attach_ctl_mcgs(eib_t * ss,eib_vnic_t * vnic)2024*13101SVenki.Rajagopalan@Sun.COM eib_rb_vnic_attach_ctl_mcgs(eib_t *ss, eib_vnic_t *vnic)
2025*13101SVenki.Rajagopalan@Sun.COM {
2026*13101SVenki.Rajagopalan@Sun.COM 	/*
2027*13101SVenki.Rajagopalan@Sun.COM 	 * Detach from the vhub table and vhub update mcgs before blowing
2028*13101SVenki.Rajagopalan@Sun.COM 	 * up vn_vhub_table and vn_vhub_update, since these are assumed to
2029*13101SVenki.Rajagopalan@Sun.COM 	 * be available by the control cq handler.
2030*13101SVenki.Rajagopalan@Sun.COM 	 */
2031*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_vnic_attach_vhub_table(ss, vnic);
2032*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_vnic_attach_vhub_update(ss, vnic);
2033*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_fini_tables(ss, vnic, B_TRUE);
2034*13101SVenki.Rajagopalan@Sun.COM }
2035*13101SVenki.Rajagopalan@Sun.COM 
2036*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
2037*13101SVenki.Rajagopalan@Sun.COM static void
eib_rb_vnic_attach_vhub_table(eib_t * ss,eib_vnic_t * vnic)2038*13101SVenki.Rajagopalan@Sun.COM eib_rb_vnic_attach_vhub_table(eib_t *ss, eib_vnic_t *vnic)
2039*13101SVenki.Rajagopalan@Sun.COM {
2040*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = vnic->vn_ctl_chan;
2041*13101SVenki.Rajagopalan@Sun.COM 	eib_mcg_t *mcg;
2042*13101SVenki.Rajagopalan@Sun.COM 	ibt_channel_hdl_t chan_hdl;
2043*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
2044*13101SVenki.Rajagopalan@Sun.COM 
2045*13101SVenki.Rajagopalan@Sun.COM 	if (chan == NULL)
2046*13101SVenki.Rajagopalan@Sun.COM 		return;
2047*13101SVenki.Rajagopalan@Sun.COM 
2048*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&chan->ch_vhub_lock);
2049*13101SVenki.Rajagopalan@Sun.COM 	chan_hdl = chan->ch_chan;
2050*13101SVenki.Rajagopalan@Sun.COM 	mcg = chan->ch_vhub_table;
2051*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_vhub_table = NULL;
2052*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&chan->ch_vhub_lock);
2053*13101SVenki.Rajagopalan@Sun.COM 
2054*13101SVenki.Rajagopalan@Sun.COM 	if (chan_hdl && mcg) {
2055*13101SVenki.Rajagopalan@Sun.COM 		ret = ibt_detach_mcg(chan_hdl, mcg->mg_mcginfo);
2056*13101SVenki.Rajagopalan@Sun.COM 		if (ret != IBT_SUCCESS) {
2057*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
2058*13101SVenki.Rajagopalan@Sun.COM 			    "eib_rb_vnic_attach_vhub_table: "
2059*13101SVenki.Rajagopalan@Sun.COM 			    "ibt_detach_mcg(chan_hdl=0x%llx, mcinfo=0x%llx, "
2060*13101SVenki.Rajagopalan@Sun.COM 			    "mgid=%llx.%llx) failed, ret=%d", chan_hdl,
2061*13101SVenki.Rajagopalan@Sun.COM 			    mcg->mg_mcginfo, mcg->mg_mgid.gid_prefix,
2062*13101SVenki.Rajagopalan@Sun.COM 			    mcg->mg_mgid.gid_guid, ret);
2063*13101SVenki.Rajagopalan@Sun.COM 		}
2064*13101SVenki.Rajagopalan@Sun.COM 
2065*13101SVenki.Rajagopalan@Sun.COM 		ret = ibt_leave_mcg(mcg->mg_rgid, mcg->mg_mgid,
2066*13101SVenki.Rajagopalan@Sun.COM 		    eib_reserved_gid, mcg->mg_join_state);
2067*13101SVenki.Rajagopalan@Sun.COM 		if (ret != IBT_SUCCESS) {
2068*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
2069*13101SVenki.Rajagopalan@Sun.COM 			    "eib_rb_vnic_attach_vhub_table: "
2070*13101SVenki.Rajagopalan@Sun.COM 			    "ibt_leave_mcg(mgid=%llx.%llx, jstate=0x%x) "
2071*13101SVenki.Rajagopalan@Sun.COM 			    "failed, ret=%d", mcg->mg_mgid.gid_prefix,
2072*13101SVenki.Rajagopalan@Sun.COM 			    mcg->mg_mgid.gid_guid, mcg->mg_join_state, ret);
2073*13101SVenki.Rajagopalan@Sun.COM 		}
2074*13101SVenki.Rajagopalan@Sun.COM 
2075*13101SVenki.Rajagopalan@Sun.COM 		if (mcg->mg_mcginfo) {
2076*13101SVenki.Rajagopalan@Sun.COM 			ibt_free_mcg_info(mcg->mg_mcginfo, 1);
2077*13101SVenki.Rajagopalan@Sun.COM 		}
2078*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(mcg, sizeof (eib_mcg_t));
2079*13101SVenki.Rajagopalan@Sun.COM 	}
2080*13101SVenki.Rajagopalan@Sun.COM }
2081*13101SVenki.Rajagopalan@Sun.COM 
2082*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
2083*13101SVenki.Rajagopalan@Sun.COM static void
eib_rb_vnic_attach_vhub_update(eib_t * ss,eib_vnic_t * vnic)2084*13101SVenki.Rajagopalan@Sun.COM eib_rb_vnic_attach_vhub_update(eib_t *ss, eib_vnic_t *vnic)
2085*13101SVenki.Rajagopalan@Sun.COM {
2086*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = vnic->vn_ctl_chan;
2087*13101SVenki.Rajagopalan@Sun.COM 	eib_mcg_t *mcg;
2088*13101SVenki.Rajagopalan@Sun.COM 	ibt_channel_hdl_t chan_hdl;
2089*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
2090*13101SVenki.Rajagopalan@Sun.COM 
2091*13101SVenki.Rajagopalan@Sun.COM 	if (chan == NULL)
2092*13101SVenki.Rajagopalan@Sun.COM 		return;
2093*13101SVenki.Rajagopalan@Sun.COM 
2094*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&chan->ch_vhub_lock);
2095*13101SVenki.Rajagopalan@Sun.COM 	chan_hdl = chan->ch_chan;
2096*13101SVenki.Rajagopalan@Sun.COM 	mcg = chan->ch_vhub_update;
2097*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_vhub_update = NULL;
2098*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&chan->ch_vhub_lock);
2099*13101SVenki.Rajagopalan@Sun.COM 
2100*13101SVenki.Rajagopalan@Sun.COM 	if (chan_hdl && mcg) {
2101*13101SVenki.Rajagopalan@Sun.COM 		ret = ibt_detach_mcg(chan_hdl, mcg->mg_mcginfo);
2102*13101SVenki.Rajagopalan@Sun.COM 		if (ret != IBT_SUCCESS) {
2103*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
2104*13101SVenki.Rajagopalan@Sun.COM 			    "eib_rb_vnic_attach_vhub_update: "
2105*13101SVenki.Rajagopalan@Sun.COM 			    "ibt_detach_mcg(chan_hdl=0x%llx, mcinfo=0x%llx, "
2106*13101SVenki.Rajagopalan@Sun.COM 			    "mgid=%llx.%llx) failed, ret=%d", chan_hdl,
2107*13101SVenki.Rajagopalan@Sun.COM 			    mcg->mg_mcginfo, mcg->mg_mgid.gid_prefix,
2108*13101SVenki.Rajagopalan@Sun.COM 			    mcg->mg_mgid.gid_guid, ret);
2109*13101SVenki.Rajagopalan@Sun.COM 		}
2110*13101SVenki.Rajagopalan@Sun.COM 
2111*13101SVenki.Rajagopalan@Sun.COM 		ret = ibt_leave_mcg(mcg->mg_rgid, mcg->mg_mgid,
2112*13101SVenki.Rajagopalan@Sun.COM 		    eib_reserved_gid, mcg->mg_join_state);
2113*13101SVenki.Rajagopalan@Sun.COM 		if (ret != IBT_SUCCESS) {
2114*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
2115*13101SVenki.Rajagopalan@Sun.COM 			    "eib_rb_vnic_attach_vhub_update: "
2116*13101SVenki.Rajagopalan@Sun.COM 			    "ibt_leave_mcg(mgid=%llx.%llx, jstate=0x%x) "
2117*13101SVenki.Rajagopalan@Sun.COM 			    "failed, ret=%d", mcg->mg_mgid.gid_prefix,
2118*13101SVenki.Rajagopalan@Sun.COM 			    mcg->mg_mgid.gid_guid, mcg->mg_join_state, ret);
2119*13101SVenki.Rajagopalan@Sun.COM 		}
2120*13101SVenki.Rajagopalan@Sun.COM 
2121*13101SVenki.Rajagopalan@Sun.COM 		if (mcg->mg_mcginfo) {
2122*13101SVenki.Rajagopalan@Sun.COM 			ibt_free_mcg_info(mcg->mg_mcginfo, 1);
2123*13101SVenki.Rajagopalan@Sun.COM 		}
2124*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(mcg, sizeof (eib_mcg_t));
2125*13101SVenki.Rajagopalan@Sun.COM 	}
2126*13101SVenki.Rajagopalan@Sun.COM }
2127*13101SVenki.Rajagopalan@Sun.COM 
2128*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
2129*13101SVenki.Rajagopalan@Sun.COM static void
eib_rb_vnic_start_keepalives(eib_t * ss,eib_vnic_t * vnic)2130*13101SVenki.Rajagopalan@Sun.COM eib_rb_vnic_start_keepalives(eib_t *ss, eib_vnic_t *vnic)
2131*13101SVenki.Rajagopalan@Sun.COM {
2132*13101SVenki.Rajagopalan@Sun.COM 	eib_ka_vnics_t *prev;
2133*13101SVenki.Rajagopalan@Sun.COM 	eib_ka_vnics_t *elem;
2134*13101SVenki.Rajagopalan@Sun.COM 
2135*13101SVenki.Rajagopalan@Sun.COM 	/*
2136*13101SVenki.Rajagopalan@Sun.COM 	 * We only need to locate and remove the vnic entry from the
2137*13101SVenki.Rajagopalan@Sun.COM 	 * keepalives manager list
2138*13101SVenki.Rajagopalan@Sun.COM 	 */
2139*13101SVenki.Rajagopalan@Sun.COM 
2140*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ss->ei_ka_vnics_lock);
2141*13101SVenki.Rajagopalan@Sun.COM 
2142*13101SVenki.Rajagopalan@Sun.COM 	prev = NULL;
2143*13101SVenki.Rajagopalan@Sun.COM 	for (elem = ss->ei_ka_vnics; elem; elem = elem->ka_next) {
2144*13101SVenki.Rajagopalan@Sun.COM 		if (elem->ka_vnic == vnic)
2145*13101SVenki.Rajagopalan@Sun.COM 			break;
2146*13101SVenki.Rajagopalan@Sun.COM 
2147*13101SVenki.Rajagopalan@Sun.COM 		prev = elem;
2148*13101SVenki.Rajagopalan@Sun.COM 	}
2149*13101SVenki.Rajagopalan@Sun.COM 	if (elem == NULL) {
2150*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
2151*13101SVenki.Rajagopalan@Sun.COM 		    "eib_rb_vnic_start_keepalives: no keepalive element found "
2152*13101SVenki.Rajagopalan@Sun.COM 		    "for vnic 0x%llx (vn_inst=%d) with keepalive manager",
2153*13101SVenki.Rajagopalan@Sun.COM 		    vnic, vnic->vn_instance);
2154*13101SVenki.Rajagopalan@Sun.COM 	} else {
2155*13101SVenki.Rajagopalan@Sun.COM 		if (prev) {
2156*13101SVenki.Rajagopalan@Sun.COM 			prev->ka_next = elem->ka_next;
2157*13101SVenki.Rajagopalan@Sun.COM 		} else {
2158*13101SVenki.Rajagopalan@Sun.COM 			ss->ei_ka_vnics = elem->ka_next;
2159*13101SVenki.Rajagopalan@Sun.COM 		}
2160*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(elem, sizeof (eib_ka_vnics_t));
2161*13101SVenki.Rajagopalan@Sun.COM 	}
2162*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ss->ei_ka_vnics_lock);
2163*13101SVenki.Rajagopalan@Sun.COM }
2164*13101SVenki.Rajagopalan@Sun.COM 
2165*13101SVenki.Rajagopalan@Sun.COM /*ARGSUSED*/
2166*13101SVenki.Rajagopalan@Sun.COM static void
eib_rb_vnic_join_data_mcg(eib_t * ss,eib_vnic_t * vnic,uint8_t * mcast_mac)2167*13101SVenki.Rajagopalan@Sun.COM eib_rb_vnic_join_data_mcg(eib_t *ss, eib_vnic_t *vnic, uint8_t *mcast_mac)
2168*13101SVenki.Rajagopalan@Sun.COM {
2169*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = vnic->vn_data_chan;
2170*13101SVenki.Rajagopalan@Sun.COM 	eib_mcg_t *prev;
2171*13101SVenki.Rajagopalan@Sun.COM 	eib_mcg_t *mcg;
2172*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
2173*13101SVenki.Rajagopalan@Sun.COM 
2174*13101SVenki.Rajagopalan@Sun.COM 	/*
2175*13101SVenki.Rajagopalan@Sun.COM 	 * Search our list and remove the item if found
2176*13101SVenki.Rajagopalan@Sun.COM 	 */
2177*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&chan->ch_vhub_lock);
2178*13101SVenki.Rajagopalan@Sun.COM 
2179*13101SVenki.Rajagopalan@Sun.COM 	prev = NULL;
2180*13101SVenki.Rajagopalan@Sun.COM 	for (mcg = chan->ch_vhub_data; mcg != NULL; mcg = mcg->mg_next) {
2181*13101SVenki.Rajagopalan@Sun.COM 		if (bcmp(mcg->mg_mac, mcast_mac, ETHERADDRL) == 0)
2182*13101SVenki.Rajagopalan@Sun.COM 			break;
2183*13101SVenki.Rajagopalan@Sun.COM 		prev = mcg;
2184*13101SVenki.Rajagopalan@Sun.COM 	}
2185*13101SVenki.Rajagopalan@Sun.COM 
2186*13101SVenki.Rajagopalan@Sun.COM 	if (mcg == NULL) {
2187*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&chan->ch_vhub_lock);
2188*13101SVenki.Rajagopalan@Sun.COM 		return;
2189*13101SVenki.Rajagopalan@Sun.COM 	}
2190*13101SVenki.Rajagopalan@Sun.COM 
2191*13101SVenki.Rajagopalan@Sun.COM 	if (prev != NULL)
2192*13101SVenki.Rajagopalan@Sun.COM 		prev->mg_next = mcg->mg_next;
2193*13101SVenki.Rajagopalan@Sun.COM 	else
2194*13101SVenki.Rajagopalan@Sun.COM 		chan->ch_vhub_data = mcg->mg_next;
2195*13101SVenki.Rajagopalan@Sun.COM 
2196*13101SVenki.Rajagopalan@Sun.COM 	mcg->mg_next = NULL;
2197*13101SVenki.Rajagopalan@Sun.COM 
2198*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&chan->ch_vhub_lock);
2199*13101SVenki.Rajagopalan@Sun.COM 
2200*13101SVenki.Rajagopalan@Sun.COM 	/*
2201*13101SVenki.Rajagopalan@Sun.COM 	 * Detach data channel qp from the mcg, leave the group and free
2202*13101SVenki.Rajagopalan@Sun.COM 	 * all associated stuff
2203*13101SVenki.Rajagopalan@Sun.COM 	 */
2204*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_detach_mcg(chan->ch_chan, mcg->mg_mcginfo);
2205*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
2206*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
2207*13101SVenki.Rajagopalan@Sun.COM 		    "eib_rb_vnic_join_data_mcg: "
2208*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_detach_mcg(chan_hdl=0x%llx, mcinfo=0x%llx, "
2209*13101SVenki.Rajagopalan@Sun.COM 		    "mgid=%llx.%llx) failed, ret=%d", chan->ch_chan,
2210*13101SVenki.Rajagopalan@Sun.COM 		    mcg->mg_mcginfo, mcg->mg_mgid.gid_prefix,
2211*13101SVenki.Rajagopalan@Sun.COM 		    mcg->mg_mgid.gid_guid, ret);
2212*13101SVenki.Rajagopalan@Sun.COM 	}
2213*13101SVenki.Rajagopalan@Sun.COM 
2214*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_leave_mcg(mcg->mg_rgid, mcg->mg_mgid, eib_reserved_gid,
2215*13101SVenki.Rajagopalan@Sun.COM 	    mcg->mg_join_state);
2216*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
2217*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance,
2218*13101SVenki.Rajagopalan@Sun.COM 		    "eib_rb_vnic_join_data_mcg: "
2219*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_leave_mcg(mgid=%llx.%llx, jstate=0x%x) "
2220*13101SVenki.Rajagopalan@Sun.COM 		    "failed, ret=%d", mcg->mg_mgid.gid_prefix,
2221*13101SVenki.Rajagopalan@Sun.COM 		    mcg->mg_mgid.gid_guid, mcg->mg_join_state, ret);
2222*13101SVenki.Rajagopalan@Sun.COM 	}
2223*13101SVenki.Rajagopalan@Sun.COM 
2224*13101SVenki.Rajagopalan@Sun.COM 	if (mcg->mg_mcginfo)
2225*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(mcg->mg_mcginfo, sizeof (ibt_mcg_info_t));
2226*13101SVenki.Rajagopalan@Sun.COM 
2227*13101SVenki.Rajagopalan@Sun.COM 	kmem_free(mcg, sizeof (eib_mcg_t));
2228*13101SVenki.Rajagopalan@Sun.COM }
2229