xref: /onnv-gate/usr/src/uts/common/io/ib/clients/eoib/eib_fip.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/ddi.h>
28*13101SVenki.Rajagopalan@Sun.COM #include <sys/sunddi.h>
29*13101SVenki.Rajagopalan@Sun.COM #include <sys/ksynch.h>
30*13101SVenki.Rajagopalan@Sun.COM #include <sys/byteorder.h>
31*13101SVenki.Rajagopalan@Sun.COM 
32*13101SVenki.Rajagopalan@Sun.COM #include <sys/ib/clients/eoib/eib_impl.h>
33*13101SVenki.Rajagopalan@Sun.COM 
34*13101SVenki.Rajagopalan@Sun.COM /*
35*13101SVenki.Rajagopalan@Sun.COM  * Declarations private to this file
36*13101SVenki.Rajagopalan@Sun.COM  */
37*13101SVenki.Rajagopalan@Sun.COM static int eib_fip_make_login(eib_t *, eib_vnic_t *, eib_wqe_t *, int *);
38*13101SVenki.Rajagopalan@Sun.COM static int eib_fip_make_update(eib_t *, eib_vnic_t *, eib_wqe_t *, int, int *);
39*13101SVenki.Rajagopalan@Sun.COM static int eib_fip_make_table(eib_t *, eib_vnic_t *, eib_wqe_t *, int *);
40*13101SVenki.Rajagopalan@Sun.COM static int eib_fip_make_ka(eib_t *, eib_vnic_t *, eib_wqe_t *, int *);
41*13101SVenki.Rajagopalan@Sun.COM static int eib_fip_make_logout(eib_t *, eib_vnic_t *, eib_wqe_t *, int *);
42*13101SVenki.Rajagopalan@Sun.COM 
43*13101SVenki.Rajagopalan@Sun.COM static int eib_fip_send_login(eib_t *, eib_vnic_t *, eib_wqe_t *, int *);
44*13101SVenki.Rajagopalan@Sun.COM static int eib_fip_send_update(eib_t *, eib_vnic_t *, eib_wqe_t *,
45*13101SVenki.Rajagopalan@Sun.COM     uint_t, int *);
46*13101SVenki.Rajagopalan@Sun.COM static int eib_fip_send_table(eib_t *, eib_vnic_t *, eib_wqe_t *, int *);
47*13101SVenki.Rajagopalan@Sun.COM static int eib_fip_send_ka(eib_t *, eib_vnic_t *, eib_wqe_t *, int *);
48*13101SVenki.Rajagopalan@Sun.COM static int eib_fip_send_logout(eib_t *, eib_vnic_t *, eib_wqe_t *, int *);
49*13101SVenki.Rajagopalan@Sun.COM 
50*13101SVenki.Rajagopalan@Sun.COM static int eib_fip_parse_vhub_table(uint8_t *, eib_vnic_t *);
51*13101SVenki.Rajagopalan@Sun.COM static int eib_fip_parse_vhub_update(uint8_t *, eib_vnic_t *);
52*13101SVenki.Rajagopalan@Sun.COM static void eib_fip_update_eport_state(eib_t *, eib_vhub_table_t *,
53*13101SVenki.Rajagopalan@Sun.COM     eib_vhub_update_t *, boolean_t, uint8_t);
54*13101SVenki.Rajagopalan@Sun.COM static void eib_fip_queue_tbl_entry(eib_vhub_table_t *, eib_vhub_map_t *,
55*13101SVenki.Rajagopalan@Sun.COM     uint32_t, uint8_t);
56*13101SVenki.Rajagopalan@Sun.COM static void eib_fip_queue_upd_entry(eib_vhub_update_t *, eib_vhub_map_t *,
57*13101SVenki.Rajagopalan@Sun.COM     uint32_t, uint8_t);
58*13101SVenki.Rajagopalan@Sun.COM static void eib_fip_queue_gw_entry(eib_vnic_t *, eib_vhub_table_t *, uint32_t,
59*13101SVenki.Rajagopalan@Sun.COM     uint8_t);
60*13101SVenki.Rajagopalan@Sun.COM static int eib_fip_apply_updates(eib_t *, eib_vhub_table_t *,
61*13101SVenki.Rajagopalan@Sun.COM     eib_vhub_update_t *);
62*13101SVenki.Rajagopalan@Sun.COM static void eib_fip_dequeue_tbl_entry(eib_vhub_table_t *, uint8_t *, uint32_t,
63*13101SVenki.Rajagopalan@Sun.COM     uint8_t);
64*13101SVenki.Rajagopalan@Sun.COM static eib_vhub_map_t *eib_fip_get_vhub_map(void);
65*13101SVenki.Rajagopalan@Sun.COM 
66*13101SVenki.Rajagopalan@Sun.COM /*
67*13101SVenki.Rajagopalan@Sun.COM  * Definitions private to this file
68*13101SVenki.Rajagopalan@Sun.COM  */
69*13101SVenki.Rajagopalan@Sun.COM const char eib_vendor_mellanox[] = {
70*13101SVenki.Rajagopalan@Sun.COM 	0x4d, 0x65, 0x6c, 0x6c, 0x61, 0x6e, 0x6f, 0x78
71*13101SVenki.Rajagopalan@Sun.COM };
72*13101SVenki.Rajagopalan@Sun.COM 
73*13101SVenki.Rajagopalan@Sun.COM /*
74*13101SVenki.Rajagopalan@Sun.COM  * The three requests to the gateway - request a vHUB table, request a
75*13101SVenki.Rajagopalan@Sun.COM  * vHUB update (aka keepalive) and vNIC logout - all need the same
76*13101SVenki.Rajagopalan@Sun.COM  * vnic identity descriptor to be sent with different flag settings.
77*13101SVenki.Rajagopalan@Sun.COM  *
78*13101SVenki.Rajagopalan@Sun.COM  *      vHUB table: R=1, U=0, TUSN=last, subcode=KEEPALIVE
79*13101SVenki.Rajagopalan@Sun.COM  *      keepalive/vHUB update: R=0, U=1, TUSN=last, subcode=KEEPALIVE
80*13101SVenki.Rajagopalan@Sun.COM  *      vNIC logout: R=0, U=0, TUSN=0, subcode=LOGOUT
81*13101SVenki.Rajagopalan@Sun.COM  */
82*13101SVenki.Rajagopalan@Sun.COM #define	EIB_UPD_REQ_TABLE	1
83*13101SVenki.Rajagopalan@Sun.COM #define	EIB_UPD_REQ_KA		2
84*13101SVenki.Rajagopalan@Sun.COM #define	EIB_UPD_REQ_LOGOUT	3
85*13101SVenki.Rajagopalan@Sun.COM 
86*13101SVenki.Rajagopalan@Sun.COM int
eib_fip_login(eib_t * ss,eib_vnic_t * vnic,int * err)87*13101SVenki.Rajagopalan@Sun.COM eib_fip_login(eib_t *ss, eib_vnic_t *vnic, int *err)
88*13101SVenki.Rajagopalan@Sun.COM {
89*13101SVenki.Rajagopalan@Sun.COM 	eib_wqe_t *swqe;
90*13101SVenki.Rajagopalan@Sun.COM 	int ret;
91*13101SVenki.Rajagopalan@Sun.COM 	int ntries = 0;
92*13101SVenki.Rajagopalan@Sun.COM 
93*13101SVenki.Rajagopalan@Sun.COM 	do {
94*13101SVenki.Rajagopalan@Sun.COM 		if ((swqe = eib_rsrc_grab_swqe(ss, EIB_WPRI_LO)) == NULL) {
95*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_login: "
96*13101SVenki.Rajagopalan@Sun.COM 			    "no swqe available, not sending "
97*13101SVenki.Rajagopalan@Sun.COM 			    "vnic login request");
98*13101SVenki.Rajagopalan@Sun.COM 			*err = ENOMEM;
99*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_FAILURE);
100*13101SVenki.Rajagopalan@Sun.COM 		}
101*13101SVenki.Rajagopalan@Sun.COM 
102*13101SVenki.Rajagopalan@Sun.COM 		ret = eib_fip_make_login(ss, vnic, swqe, err);
103*13101SVenki.Rajagopalan@Sun.COM 		if (ret != EIB_E_SUCCESS) {
104*13101SVenki.Rajagopalan@Sun.COM 			eib_rsrc_return_swqe(ss, swqe, NULL);
105*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_FAILURE);
106*13101SVenki.Rajagopalan@Sun.COM 		}
107*13101SVenki.Rajagopalan@Sun.COM 
108*13101SVenki.Rajagopalan@Sun.COM 		ret = eib_fip_send_login(ss, vnic, swqe, err);
109*13101SVenki.Rajagopalan@Sun.COM 		if (ret != EIB_E_SUCCESS) {
110*13101SVenki.Rajagopalan@Sun.COM 			eib_rsrc_return_swqe(ss, swqe, NULL);
111*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_FAILURE);
112*13101SVenki.Rajagopalan@Sun.COM 		}
113*13101SVenki.Rajagopalan@Sun.COM 
114*13101SVenki.Rajagopalan@Sun.COM 		ret = eib_vnic_wait_for_login_ack(ss, vnic, err);
115*13101SVenki.Rajagopalan@Sun.COM 		if (ret == EIB_E_SUCCESS)
116*13101SVenki.Rajagopalan@Sun.COM 			break;
117*13101SVenki.Rajagopalan@Sun.COM 
118*13101SVenki.Rajagopalan@Sun.COM 	} while ((*err == ETIME) && (ntries++ < EIB_MAX_LOGIN_ATTEMPTS));
119*13101SVenki.Rajagopalan@Sun.COM 
120*13101SVenki.Rajagopalan@Sun.COM 	return (ret);
121*13101SVenki.Rajagopalan@Sun.COM }
122*13101SVenki.Rajagopalan@Sun.COM 
123*13101SVenki.Rajagopalan@Sun.COM int
eib_fip_vhub_table(eib_t * ss,eib_vnic_t * vnic,int * err)124*13101SVenki.Rajagopalan@Sun.COM eib_fip_vhub_table(eib_t *ss, eib_vnic_t *vnic, int *err)
125*13101SVenki.Rajagopalan@Sun.COM {
126*13101SVenki.Rajagopalan@Sun.COM 	eib_wqe_t *swqe;
127*13101SVenki.Rajagopalan@Sun.COM 	int ret;
128*13101SVenki.Rajagopalan@Sun.COM 	int ntries = 0;
129*13101SVenki.Rajagopalan@Sun.COM 
130*13101SVenki.Rajagopalan@Sun.COM 	do {
131*13101SVenki.Rajagopalan@Sun.COM 		if ((swqe = eib_rsrc_grab_swqe(ss, EIB_WPRI_LO)) == NULL) {
132*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_vhub_table: "
133*13101SVenki.Rajagopalan@Sun.COM 			    "no swqe available, not sending "
134*13101SVenki.Rajagopalan@Sun.COM 			    "vhub table request");
135*13101SVenki.Rajagopalan@Sun.COM 			*err = ENOMEM;
136*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_FAILURE);
137*13101SVenki.Rajagopalan@Sun.COM 		}
138*13101SVenki.Rajagopalan@Sun.COM 
139*13101SVenki.Rajagopalan@Sun.COM 		ret = eib_fip_make_table(ss, vnic, swqe, err);
140*13101SVenki.Rajagopalan@Sun.COM 		if (ret != EIB_E_SUCCESS) {
141*13101SVenki.Rajagopalan@Sun.COM 			eib_rsrc_return_swqe(ss, swqe, NULL);
142*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_FAILURE);
143*13101SVenki.Rajagopalan@Sun.COM 		}
144*13101SVenki.Rajagopalan@Sun.COM 
145*13101SVenki.Rajagopalan@Sun.COM 		ret = eib_fip_send_table(ss, vnic, swqe, err);
146*13101SVenki.Rajagopalan@Sun.COM 		if (ret != EIB_E_SUCCESS) {
147*13101SVenki.Rajagopalan@Sun.COM 			eib_rsrc_return_swqe(ss, swqe, NULL);
148*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_FAILURE);
149*13101SVenki.Rajagopalan@Sun.COM 		}
150*13101SVenki.Rajagopalan@Sun.COM 
151*13101SVenki.Rajagopalan@Sun.COM 		ret = eib_vnic_wait_for_table(ss, vnic, err);
152*13101SVenki.Rajagopalan@Sun.COM 		if (ret == EIB_E_SUCCESS) {
153*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_SUCCESS);
154*13101SVenki.Rajagopalan@Sun.COM 		}
155*13101SVenki.Rajagopalan@Sun.COM 
156*13101SVenki.Rajagopalan@Sun.COM 		/*
157*13101SVenki.Rajagopalan@Sun.COM 		 * If we'd failed in constructing a proper vhub table above,
158*13101SVenki.Rajagopalan@Sun.COM 		 * the vnic login state would be set to EIB_LOGIN_TBL_FAILED.
159*13101SVenki.Rajagopalan@Sun.COM 		 * We need to clean up any pending entries from the vhub
160*13101SVenki.Rajagopalan@Sun.COM 		 * table and vhub update structures and reset the vnic state
161*13101SVenki.Rajagopalan@Sun.COM 		 * to EIB_LOGIN_ACK_RCVD before we can try again.
162*13101SVenki.Rajagopalan@Sun.COM 		 */
163*13101SVenki.Rajagopalan@Sun.COM 		eib_vnic_fini_tables(ss, vnic, B_FALSE);
164*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&vnic->vn_lock);
165*13101SVenki.Rajagopalan@Sun.COM 		vnic->vn_state = EIB_LOGIN_ACK_RCVD;
166*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&vnic->vn_lock);
167*13101SVenki.Rajagopalan@Sun.COM 
168*13101SVenki.Rajagopalan@Sun.COM 	} while ((*err == ETIME) && (ntries++ < EIB_MAX_VHUB_TBL_ATTEMPTS));
169*13101SVenki.Rajagopalan@Sun.COM 
170*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_FAILURE);
171*13101SVenki.Rajagopalan@Sun.COM }
172*13101SVenki.Rajagopalan@Sun.COM 
173*13101SVenki.Rajagopalan@Sun.COM int
eib_fip_heartbeat(eib_t * ss,eib_vnic_t * vnic,int * err)174*13101SVenki.Rajagopalan@Sun.COM eib_fip_heartbeat(eib_t *ss, eib_vnic_t *vnic, int *err)
175*13101SVenki.Rajagopalan@Sun.COM {
176*13101SVenki.Rajagopalan@Sun.COM 	eib_wqe_t *swqe;
177*13101SVenki.Rajagopalan@Sun.COM 	int ntries = 0;
178*13101SVenki.Rajagopalan@Sun.COM 	int ret;
179*13101SVenki.Rajagopalan@Sun.COM 
180*13101SVenki.Rajagopalan@Sun.COM 	/*
181*13101SVenki.Rajagopalan@Sun.COM 	 * Even if we're running low on the wqe resource, we want to be
182*13101SVenki.Rajagopalan@Sun.COM 	 * able to grab a wqe to send the keepalive, to avoid getting
183*13101SVenki.Rajagopalan@Sun.COM 	 * logged out by the gateway, so we use EIB_WPRI_HI.
184*13101SVenki.Rajagopalan@Sun.COM 	 */
185*13101SVenki.Rajagopalan@Sun.COM 	if ((swqe = eib_rsrc_grab_swqe(ss, EIB_WPRI_HI)) == NULL) {
186*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_heartbeat: "
187*13101SVenki.Rajagopalan@Sun.COM 		    "no swqe available, not sending heartbeat");
188*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
189*13101SVenki.Rajagopalan@Sun.COM 	}
190*13101SVenki.Rajagopalan@Sun.COM 
191*13101SVenki.Rajagopalan@Sun.COM 	while (ntries++ < EIB_MAX_KA_ATTEMPTS) {
192*13101SVenki.Rajagopalan@Sun.COM 		ret = eib_fip_make_ka(ss, vnic, swqe, err);
193*13101SVenki.Rajagopalan@Sun.COM 		if (ret != EIB_E_SUCCESS)
194*13101SVenki.Rajagopalan@Sun.COM 			continue;
195*13101SVenki.Rajagopalan@Sun.COM 
196*13101SVenki.Rajagopalan@Sun.COM 		ret = eib_fip_send_ka(ss, vnic, swqe, err);
197*13101SVenki.Rajagopalan@Sun.COM 		if (ret == EIB_E_SUCCESS)
198*13101SVenki.Rajagopalan@Sun.COM 			break;
199*13101SVenki.Rajagopalan@Sun.COM 	}
200*13101SVenki.Rajagopalan@Sun.COM 
201*13101SVenki.Rajagopalan@Sun.COM 	if (ret != EIB_E_SUCCESS)
202*13101SVenki.Rajagopalan@Sun.COM 		eib_rsrc_return_swqe(ss, swqe, NULL);
203*13101SVenki.Rajagopalan@Sun.COM 
204*13101SVenki.Rajagopalan@Sun.COM 	return (ret);
205*13101SVenki.Rajagopalan@Sun.COM }
206*13101SVenki.Rajagopalan@Sun.COM 
207*13101SVenki.Rajagopalan@Sun.COM int
eib_fip_logout(eib_t * ss,eib_vnic_t * vnic,int * err)208*13101SVenki.Rajagopalan@Sun.COM eib_fip_logout(eib_t *ss, eib_vnic_t *vnic, int *err)
209*13101SVenki.Rajagopalan@Sun.COM {
210*13101SVenki.Rajagopalan@Sun.COM 	eib_wqe_t *swqe;
211*13101SVenki.Rajagopalan@Sun.COM 	int ret;
212*13101SVenki.Rajagopalan@Sun.COM 
213*13101SVenki.Rajagopalan@Sun.COM 	/*
214*13101SVenki.Rajagopalan@Sun.COM 	 * This routine is only called after the vnic has successfully
215*13101SVenki.Rajagopalan@Sun.COM 	 * logged in to the gateway. If that's really the case, there
216*13101SVenki.Rajagopalan@Sun.COM 	 * is nothing in terms of resources we need to release: the swqe
217*13101SVenki.Rajagopalan@Sun.COM 	 * that was acquired during login has already been posted, the
218*13101SVenki.Rajagopalan@Sun.COM 	 * work has been completed and the swqe has also been reaped back
219*13101SVenki.Rajagopalan@Sun.COM 	 * into the free pool. The only thing we need to rollback is the
220*13101SVenki.Rajagopalan@Sun.COM 	 * fact that we're logged in to the gateway at all -- and the way
221*13101SVenki.Rajagopalan@Sun.COM 	 * to do this is to send a logout request.
222*13101SVenki.Rajagopalan@Sun.COM 	 */
223*13101SVenki.Rajagopalan@Sun.COM 	if ((swqe = eib_rsrc_grab_swqe(ss, EIB_WPRI_LO)) == NULL) {
224*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_logout: "
225*13101SVenki.Rajagopalan@Sun.COM 		    "no swqe available, not sending logout");
226*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
227*13101SVenki.Rajagopalan@Sun.COM 	}
228*13101SVenki.Rajagopalan@Sun.COM 
229*13101SVenki.Rajagopalan@Sun.COM 	ret = eib_fip_make_logout(ss, vnic, swqe, err);
230*13101SVenki.Rajagopalan@Sun.COM 	if (ret != EIB_E_SUCCESS) {
231*13101SVenki.Rajagopalan@Sun.COM 		eib_rsrc_return_swqe(ss, swqe, NULL);
232*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
233*13101SVenki.Rajagopalan@Sun.COM 	}
234*13101SVenki.Rajagopalan@Sun.COM 
235*13101SVenki.Rajagopalan@Sun.COM 	ret = eib_fip_send_logout(ss, vnic, swqe, err);
236*13101SVenki.Rajagopalan@Sun.COM 	if (ret != EIB_E_SUCCESS) {
237*13101SVenki.Rajagopalan@Sun.COM 		eib_rsrc_return_swqe(ss, swqe, NULL);
238*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
239*13101SVenki.Rajagopalan@Sun.COM 	}
240*13101SVenki.Rajagopalan@Sun.COM 
241*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
242*13101SVenki.Rajagopalan@Sun.COM }
243*13101SVenki.Rajagopalan@Sun.COM 
244*13101SVenki.Rajagopalan@Sun.COM int
eib_fip_parse_login_ack(eib_t * ss,uint8_t * pkt,eib_login_data_t * ld)245*13101SVenki.Rajagopalan@Sun.COM eib_fip_parse_login_ack(eib_t *ss, uint8_t *pkt, eib_login_data_t *ld)
246*13101SVenki.Rajagopalan@Sun.COM {
247*13101SVenki.Rajagopalan@Sun.COM 	fip_login_ack_t *ack;
248*13101SVenki.Rajagopalan@Sun.COM 	fip_basic_hdr_t *hdr;
249*13101SVenki.Rajagopalan@Sun.COM 	fip_desc_iba_t *iba;
250*13101SVenki.Rajagopalan@Sun.COM 	fip_desc_vnic_login_t *login;
251*13101SVenki.Rajagopalan@Sun.COM 	fip_desc_partition_t *partition;
252*13101SVenki.Rajagopalan@Sun.COM 	ib_guid_t guid;
253*13101SVenki.Rajagopalan@Sun.COM 	uint32_t syn_ctl_qpn;
254*13101SVenki.Rajagopalan@Sun.COM 	uint16_t sl_portid;
255*13101SVenki.Rajagopalan@Sun.COM 	uint16_t flags_vlan;
256*13101SVenki.Rajagopalan@Sun.COM 	uint16_t opcode;
257*13101SVenki.Rajagopalan@Sun.COM 	uint8_t subcode;
258*13101SVenki.Rajagopalan@Sun.COM 
259*13101SVenki.Rajagopalan@Sun.COM 	/*
260*13101SVenki.Rajagopalan@Sun.COM 	 * Note that 'pkt' is always atleast double-word aligned
261*13101SVenki.Rajagopalan@Sun.COM 	 * when it is passed to us, so we can cast it without any
262*13101SVenki.Rajagopalan@Sun.COM 	 * problems.
263*13101SVenki.Rajagopalan@Sun.COM 	 */
264*13101SVenki.Rajagopalan@Sun.COM 	ack = (fip_login_ack_t *)(void *)pkt;
265*13101SVenki.Rajagopalan@Sun.COM 	hdr = &(ack->ak_fip_header);
266*13101SVenki.Rajagopalan@Sun.COM 
267*13101SVenki.Rajagopalan@Sun.COM 	/*
268*13101SVenki.Rajagopalan@Sun.COM 	 * Verify that the opcode is EoIB
269*13101SVenki.Rajagopalan@Sun.COM 	 */
270*13101SVenki.Rajagopalan@Sun.COM 	if ((opcode = ntohs(hdr->hd_opcode)) != FIP_OPCODE_EOIB) {
271*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_login_ack: "
272*13101SVenki.Rajagopalan@Sun.COM 		    "unsupported opcode 0x%x in login ack, ignoring",
273*13101SVenki.Rajagopalan@Sun.COM 		    opcode);
274*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
275*13101SVenki.Rajagopalan@Sun.COM 	}
276*13101SVenki.Rajagopalan@Sun.COM 
277*13101SVenki.Rajagopalan@Sun.COM 	/*
278*13101SVenki.Rajagopalan@Sun.COM 	 * The admin qp in the EoIB driver should receive only the login
279*13101SVenki.Rajagopalan@Sun.COM 	 * acknowledgements
280*13101SVenki.Rajagopalan@Sun.COM 	 */
281*13101SVenki.Rajagopalan@Sun.COM 	subcode = hdr->hd_subcode;
282*13101SVenki.Rajagopalan@Sun.COM 	if (subcode != FIP_SUBCODE_G_VNIC_LOGIN_ACK) {
283*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_login_ack: "
284*13101SVenki.Rajagopalan@Sun.COM 		    "unexpected subcode 0x%x received by adm qp, ignoring",
285*13101SVenki.Rajagopalan@Sun.COM 		    subcode);
286*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
287*13101SVenki.Rajagopalan@Sun.COM 	}
288*13101SVenki.Rajagopalan@Sun.COM 
289*13101SVenki.Rajagopalan@Sun.COM 	/*
290*13101SVenki.Rajagopalan@Sun.COM 	 * Verify if the descriptor list length in the received packet is
291*13101SVenki.Rajagopalan@Sun.COM 	 * valid if the workaround to disable it explicitly is absent.
292*13101SVenki.Rajagopalan@Sun.COM 	 */
293*13101SVenki.Rajagopalan@Sun.COM 	if (!eib_wa_no_desc_list_len) {
294*13101SVenki.Rajagopalan@Sun.COM 		uint_t pkt_data_sz;
295*13101SVenki.Rajagopalan@Sun.COM 
296*13101SVenki.Rajagopalan@Sun.COM 		pkt_data_sz = (ntohs(hdr->hd_desc_list_len) + 2) << 2;
297*13101SVenki.Rajagopalan@Sun.COM 		if (pkt_data_sz < sizeof (fip_login_ack_t)) {
298*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
299*13101SVenki.Rajagopalan@Sun.COM 			    "eib_fip_parse_login_ack: "
300*13101SVenki.Rajagopalan@Sun.COM 			    "login ack desc list len (0x%lx) too small "
301*13101SVenki.Rajagopalan@Sun.COM 			    "(min 0x%lx)",
302*13101SVenki.Rajagopalan@Sun.COM 			    pkt_data_sz, sizeof (fip_login_ack_t));
303*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_FAILURE);
304*13101SVenki.Rajagopalan@Sun.COM 		}
305*13101SVenki.Rajagopalan@Sun.COM 	}
306*13101SVenki.Rajagopalan@Sun.COM 
307*13101SVenki.Rajagopalan@Sun.COM 	/*
308*13101SVenki.Rajagopalan@Sun.COM 	 * Validate all the header and descriptor types and lengths
309*13101SVenki.Rajagopalan@Sun.COM 	 */
310*13101SVenki.Rajagopalan@Sun.COM 	if (hdr->hd_type != FIP_DESC_TYPE_VENDOR_ID ||
311*13101SVenki.Rajagopalan@Sun.COM 	    hdr->hd_len != FIP_DESC_LEN_VENDOR_ID) {
312*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_login_ack: "
313*13101SVenki.Rajagopalan@Sun.COM 		    "invalid type/len in basic hdr: expected (0x%x,0x%x), "
314*13101SVenki.Rajagopalan@Sun.COM 		    "got (0x%x,0x%x)", FIP_DESC_TYPE_VENDOR_ID,
315*13101SVenki.Rajagopalan@Sun.COM 		    FIP_DESC_LEN_VENDOR_ID, hdr->hd_type, hdr->hd_len);
316*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
317*13101SVenki.Rajagopalan@Sun.COM 	}
318*13101SVenki.Rajagopalan@Sun.COM 	iba = &(ack->ak_iba);
319*13101SVenki.Rajagopalan@Sun.COM 	if (iba->ia_type != FIP_DESC_TYPE_IBA ||
320*13101SVenki.Rajagopalan@Sun.COM 	    iba->ia_len != FIP_DESC_LEN_IBA) {
321*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_login_ack: "
322*13101SVenki.Rajagopalan@Sun.COM 		    "invalid type/len in iba desc: expected (0x%x,0x%x), "
323*13101SVenki.Rajagopalan@Sun.COM 		    "got (0x%x,0x%x)", FIP_DESC_TYPE_IBA, FIP_DESC_LEN_IBA,
324*13101SVenki.Rajagopalan@Sun.COM 		    iba->ia_type, iba->ia_len);
325*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
326*13101SVenki.Rajagopalan@Sun.COM 	}
327*13101SVenki.Rajagopalan@Sun.COM 	login = &(ack->ak_vnic_login);
328*13101SVenki.Rajagopalan@Sun.COM 	if (login->vl_type != FIP_DESC_TYPE_VNIC_LOGIN ||
329*13101SVenki.Rajagopalan@Sun.COM 	    login->vl_len != FIP_DESC_LEN_VNIC_LOGIN) {
330*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_login_ack: "
331*13101SVenki.Rajagopalan@Sun.COM 		    "invalid type/len in login desc: expected (0x%x,0x%x), "
332*13101SVenki.Rajagopalan@Sun.COM 		    "got (0x%x,0x%x)", FIP_DESC_TYPE_VNIC_LOGIN,
333*13101SVenki.Rajagopalan@Sun.COM 		    FIP_DESC_LEN_VNIC_LOGIN, login->vl_type, login->vl_len);
334*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
335*13101SVenki.Rajagopalan@Sun.COM 	}
336*13101SVenki.Rajagopalan@Sun.COM 	partition = &(ack->ak_vhub_partition);
337*13101SVenki.Rajagopalan@Sun.COM 	if (partition->pn_type != FIP_DESC_TYPE_PARTITION ||
338*13101SVenki.Rajagopalan@Sun.COM 	    partition->pn_len != FIP_DESC_LEN_PARTITION) {
339*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_login_ack: "
340*13101SVenki.Rajagopalan@Sun.COM 		    "invalid type/len in partition desc: expected (0x%x,0x%x), "
341*13101SVenki.Rajagopalan@Sun.COM 		    "got (0x%x,0x%x)", FIP_DESC_TYPE_PARTITION,
342*13101SVenki.Rajagopalan@Sun.COM 		    FIP_DESC_LEN_PARTITION, partition->pn_type,
343*13101SVenki.Rajagopalan@Sun.COM 		    partition->pn_len);
344*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
345*13101SVenki.Rajagopalan@Sun.COM 	}
346*13101SVenki.Rajagopalan@Sun.COM 
347*13101SVenki.Rajagopalan@Sun.COM 	/*
348*13101SVenki.Rajagopalan@Sun.COM 	 * Note that we'll return the vnic id as-is.  The msb is not actually
349*13101SVenki.Rajagopalan@Sun.COM 	 * part of the vnic id in our internal records, so we'll mask it out
350*13101SVenki.Rajagopalan@Sun.COM 	 * later before we do our searches.
351*13101SVenki.Rajagopalan@Sun.COM 	 */
352*13101SVenki.Rajagopalan@Sun.COM 	ld->ld_vnic_id = ntohs(login->vl_vnic_id);
353*13101SVenki.Rajagopalan@Sun.COM 
354*13101SVenki.Rajagopalan@Sun.COM 	syn_ctl_qpn = ntohl(login->vl_syndrome_ctl_qpn);
355*13101SVenki.Rajagopalan@Sun.COM 
356*13101SVenki.Rajagopalan@Sun.COM 	/*
357*13101SVenki.Rajagopalan@Sun.COM 	 * If the syndrome indicates a nack, we're done.  No need to collect
358*13101SVenki.Rajagopalan@Sun.COM 	 * any more information
359*13101SVenki.Rajagopalan@Sun.COM 	 */
360*13101SVenki.Rajagopalan@Sun.COM 	ld->ld_syndrome = (uint8_t)((syn_ctl_qpn & FIP_VL_SYN_MASK) >>
361*13101SVenki.Rajagopalan@Sun.COM 	    FIP_VL_SYN_SHIFT);
362*13101SVenki.Rajagopalan@Sun.COM 	if (ld->ld_syndrome) {
363*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_SUCCESS);
364*13101SVenki.Rajagopalan@Sun.COM 	}
365*13101SVenki.Rajagopalan@Sun.COM 
366*13101SVenki.Rajagopalan@Sun.COM 	/*
367*13101SVenki.Rajagopalan@Sun.COM 	 * Let's get the rest of the information out of the login ack
368*13101SVenki.Rajagopalan@Sun.COM 	 */
369*13101SVenki.Rajagopalan@Sun.COM 	sl_portid = ntohs(iba->ia_sl_portid);
370*13101SVenki.Rajagopalan@Sun.COM 	ld->ld_gw_port_id = sl_portid & FIP_IBA_PORTID_MASK;
371*13101SVenki.Rajagopalan@Sun.COM 	ld->ld_gw_sl = (sl_portid & FIP_IBA_SL_MASK) >> FIP_IBA_SL_SHIFT;
372*13101SVenki.Rajagopalan@Sun.COM 
373*13101SVenki.Rajagopalan@Sun.COM 	ld->ld_gw_data_qpn = ntohl(iba->ia_qpn) & FIP_IBA_QPN_MASK;
374*13101SVenki.Rajagopalan@Sun.COM 	ld->ld_gw_lid = ntohs(iba->ia_lid);
375*13101SVenki.Rajagopalan@Sun.COM 
376*13101SVenki.Rajagopalan@Sun.COM 	bcopy(iba->ia_guid, &guid, sizeof (ib_guid_t));
377*13101SVenki.Rajagopalan@Sun.COM 	ld->ld_gw_guid = ntohll(guid);
378*13101SVenki.Rajagopalan@Sun.COM 	ld->ld_vhub_mtu = ntohs(login->vl_mtu);
379*13101SVenki.Rajagopalan@Sun.COM 	bcopy(login->vl_mac, ld->ld_assigned_mac, ETHERADDRL);
380*13101SVenki.Rajagopalan@Sun.COM 	bcopy(login->vl_gw_mgid_prefix, ld->ld_gw_mgid_prefix,
381*13101SVenki.Rajagopalan@Sun.COM 	    FIP_MGID_PREFIX_LEN);
382*13101SVenki.Rajagopalan@Sun.COM 	ld->ld_n_rss_mcgid = login->vl_flags_rss & FIP_VL_N_RSS_MCGID_MASK;
383*13101SVenki.Rajagopalan@Sun.COM 	ld->ld_n_mac_mcgid = login->vl_n_mac_mcgid & FIP_VL_N_MAC_MCGID_MASK;
384*13101SVenki.Rajagopalan@Sun.COM 	ld->ld_gw_ctl_qpn = (syn_ctl_qpn & FIP_VL_CTL_QPN_MASK);
385*13101SVenki.Rajagopalan@Sun.COM 
386*13101SVenki.Rajagopalan@Sun.COM 	flags_vlan = ntohs(login->vl_flags_vlan);
387*13101SVenki.Rajagopalan@Sun.COM 	ld->ld_assigned_vlan = flags_vlan & FIP_VL_VLAN_MASK;
388*13101SVenki.Rajagopalan@Sun.COM 	ld->ld_vlan_in_packets = (flags_vlan & FIP_VL_FLAGS_VP) ? 1 : 0;
389*13101SVenki.Rajagopalan@Sun.COM 	bcopy(login->vl_vnic_name, ld->ld_vnic_name, FIP_VNIC_NAME_LEN);
390*13101SVenki.Rajagopalan@Sun.COM 
391*13101SVenki.Rajagopalan@Sun.COM 	ld->ld_vhub_pkey = ntohs(partition->pn_pkey);
392*13101SVenki.Rajagopalan@Sun.COM 
393*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
394*13101SVenki.Rajagopalan@Sun.COM }
395*13101SVenki.Rajagopalan@Sun.COM 
396*13101SVenki.Rajagopalan@Sun.COM int
eib_fip_parse_ctl_pkt(uint8_t * pkt,eib_vnic_t * vnic)397*13101SVenki.Rajagopalan@Sun.COM eib_fip_parse_ctl_pkt(uint8_t *pkt, eib_vnic_t *vnic)
398*13101SVenki.Rajagopalan@Sun.COM {
399*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = vnic->vn_ss;
400*13101SVenki.Rajagopalan@Sun.COM 	fip_vhub_pkt_t *vhb;
401*13101SVenki.Rajagopalan@Sun.COM 	fip_basic_hdr_t *hdr;
402*13101SVenki.Rajagopalan@Sun.COM 	uint16_t opcode;
403*13101SVenki.Rajagopalan@Sun.COM 	uint8_t subcode;
404*13101SVenki.Rajagopalan@Sun.COM 	uint_t vnic_state;
405*13101SVenki.Rajagopalan@Sun.COM 	int ret = EIB_E_FAILURE;
406*13101SVenki.Rajagopalan@Sun.COM 
407*13101SVenki.Rajagopalan@Sun.COM 	/*
408*13101SVenki.Rajagopalan@Sun.COM 	 * Note that 'pkt' is always atleast double-word aligned when it is
409*13101SVenki.Rajagopalan@Sun.COM 	 * passed to us, so we can cast it without any problems.
410*13101SVenki.Rajagopalan@Sun.COM 	 */
411*13101SVenki.Rajagopalan@Sun.COM 	vhb = (fip_vhub_pkt_t *)(void *)pkt;
412*13101SVenki.Rajagopalan@Sun.COM 	hdr = &(vhb->hb_fip_header);
413*13101SVenki.Rajagopalan@Sun.COM 
414*13101SVenki.Rajagopalan@Sun.COM 	/*
415*13101SVenki.Rajagopalan@Sun.COM 	 * Verify that the opcode is EoIB
416*13101SVenki.Rajagopalan@Sun.COM 	 */
417*13101SVenki.Rajagopalan@Sun.COM 	if ((opcode = ntohs(hdr->hd_opcode)) != FIP_OPCODE_EOIB) {
418*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_ctl_pkt: "
419*13101SVenki.Rajagopalan@Sun.COM 		    "unsupported opcode 0x%x in ctl pkt, ignoring",
420*13101SVenki.Rajagopalan@Sun.COM 		    opcode);
421*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
422*13101SVenki.Rajagopalan@Sun.COM 	}
423*13101SVenki.Rajagopalan@Sun.COM 
424*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&vnic->vn_lock);
425*13101SVenki.Rajagopalan@Sun.COM 	vnic_state = vnic->vn_state;
426*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&vnic->vn_lock);
427*13101SVenki.Rajagopalan@Sun.COM 
428*13101SVenki.Rajagopalan@Sun.COM 	/*
429*13101SVenki.Rajagopalan@Sun.COM 	 * The ctl qp in the EoIB driver should receive only vHUB messages
430*13101SVenki.Rajagopalan@Sun.COM 	 */
431*13101SVenki.Rajagopalan@Sun.COM 	subcode = hdr->hd_subcode;
432*13101SVenki.Rajagopalan@Sun.COM 	if (subcode == FIP_SUBCODE_G_VHUB_UPDATE) {
433*13101SVenki.Rajagopalan@Sun.COM 		if (vnic_state != EIB_LOGIN_TBL_WAIT &&
434*13101SVenki.Rajagopalan@Sun.COM 		    vnic_state != EIB_LOGIN_TBL_INPROG &&
435*13101SVenki.Rajagopalan@Sun.COM 		    vnic_state != EIB_LOGIN_TBL_DONE &&
436*13101SVenki.Rajagopalan@Sun.COM 		    vnic_state != EIB_LOGIN_DONE) {
437*13101SVenki.Rajagopalan@Sun.COM 
438*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
439*13101SVenki.Rajagopalan@Sun.COM 			    "eib_fip_parse_ctl_pkt: unexpected vnic state "
440*13101SVenki.Rajagopalan@Sun.COM 			    "(0x%lx) for subcode (VHUB_UPDATE 0x%x)",
441*13101SVenki.Rajagopalan@Sun.COM 			    vnic_state, subcode);
442*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_FAILURE);
443*13101SVenki.Rajagopalan@Sun.COM 		}
444*13101SVenki.Rajagopalan@Sun.COM 
445*13101SVenki.Rajagopalan@Sun.COM 		ret = eib_fip_parse_vhub_update(pkt, vnic);
446*13101SVenki.Rajagopalan@Sun.COM 
447*13101SVenki.Rajagopalan@Sun.COM 	} else if (subcode == FIP_SUBCODE_G_VHUB_TABLE) {
448*13101SVenki.Rajagopalan@Sun.COM 		if ((vnic_state != EIB_LOGIN_TBL_WAIT) &&
449*13101SVenki.Rajagopalan@Sun.COM 		    (vnic_state != EIB_LOGIN_TBL_INPROG)) {
450*13101SVenki.Rajagopalan@Sun.COM 
451*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
452*13101SVenki.Rajagopalan@Sun.COM 			    "eib_fip_parse_ctl_pkt: unexpected vnic state "
453*13101SVenki.Rajagopalan@Sun.COM 			    "(0x%lx) for subcode (VHUB_TABLE 0x%x)",
454*13101SVenki.Rajagopalan@Sun.COM 			    vnic_state, subcode);
455*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_FAILURE);
456*13101SVenki.Rajagopalan@Sun.COM 		}
457*13101SVenki.Rajagopalan@Sun.COM 
458*13101SVenki.Rajagopalan@Sun.COM 		ret = eib_fip_parse_vhub_table(pkt, vnic);
459*13101SVenki.Rajagopalan@Sun.COM 
460*13101SVenki.Rajagopalan@Sun.COM 	} else {
461*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_ctl_pkt: "
462*13101SVenki.Rajagopalan@Sun.COM 		    "unexpected subcode 0x%x for ctl pkt", subcode);
463*13101SVenki.Rajagopalan@Sun.COM 	}
464*13101SVenki.Rajagopalan@Sun.COM 
465*13101SVenki.Rajagopalan@Sun.COM 	if (ret == EIB_E_SUCCESS) {
466*13101SVenki.Rajagopalan@Sun.COM 		/*
467*13101SVenki.Rajagopalan@Sun.COM 		 * Update last gateway heartbeat received time and
468*13101SVenki.Rajagopalan@Sun.COM 		 * gateway eport state.  The eport state should only
469*13101SVenki.Rajagopalan@Sun.COM 		 * be updated if the vnic's vhub table has been fully
470*13101SVenki.Rajagopalan@Sun.COM 		 * constructed.
471*13101SVenki.Rajagopalan@Sun.COM 		 */
472*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&ss->ei_vnic_lock);
473*13101SVenki.Rajagopalan@Sun.COM 		ss->ei_gw_last_heartbeat = ddi_get_lbolt64();
474*13101SVenki.Rajagopalan@Sun.COM 		if (vnic_state == EIB_LOGIN_TBL_DONE ||
475*13101SVenki.Rajagopalan@Sun.COM 		    vnic_state == EIB_LOGIN_DONE) {
476*13101SVenki.Rajagopalan@Sun.COM 			ss->ei_gw_eport_state =
477*13101SVenki.Rajagopalan@Sun.COM 			    vnic->vn_vhub_table->tb_eport_state;
478*13101SVenki.Rajagopalan@Sun.COM 		}
479*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&ss->ei_vnic_lock);
480*13101SVenki.Rajagopalan@Sun.COM 	}
481*13101SVenki.Rajagopalan@Sun.COM 
482*13101SVenki.Rajagopalan@Sun.COM 	return (ret);
483*13101SVenki.Rajagopalan@Sun.COM }
484*13101SVenki.Rajagopalan@Sun.COM 
485*13101SVenki.Rajagopalan@Sun.COM static int
eib_fip_make_login(eib_t * ss,eib_vnic_t * vnic,eib_wqe_t * swqe,int * err)486*13101SVenki.Rajagopalan@Sun.COM eib_fip_make_login(eib_t *ss, eib_vnic_t *vnic, eib_wqe_t *swqe, int *err)
487*13101SVenki.Rajagopalan@Sun.COM {
488*13101SVenki.Rajagopalan@Sun.COM 	fip_login_t *login;
489*13101SVenki.Rajagopalan@Sun.COM 	fip_proto_t *proto;
490*13101SVenki.Rajagopalan@Sun.COM 	fip_basic_hdr_t *hdr;
491*13101SVenki.Rajagopalan@Sun.COM 	fip_desc_iba_t *iba;
492*13101SVenki.Rajagopalan@Sun.COM 	fip_desc_vnic_login_t *vlg;
493*13101SVenki.Rajagopalan@Sun.COM 	ib_gid_t port_gid;
494*13101SVenki.Rajagopalan@Sun.COM 	ib_guid_t port_guid;
495*13101SVenki.Rajagopalan@Sun.COM 	uint16_t sl_portid;
496*13101SVenki.Rajagopalan@Sun.COM 	uint16_t flags_vlan;
497*13101SVenki.Rajagopalan@Sun.COM 
498*13101SVenki.Rajagopalan@Sun.COM 	uint16_t gw_portid = ss->ei_gw_props->pp_gw_portid;
499*13101SVenki.Rajagopalan@Sun.COM 	uint16_t sl = ss->ei_gw_props->pp_gw_sl;
500*13101SVenki.Rajagopalan@Sun.COM 	uint8_t *pkt = (uint8_t *)(uintptr_t)(swqe->qe_sgl.ds_va);
501*13101SVenki.Rajagopalan@Sun.COM 	uint_t pktsz = swqe->qe_sgl.ds_len;
502*13101SVenki.Rajagopalan@Sun.COM 	uint_t login_sz = sizeof (fip_login_t);
503*13101SVenki.Rajagopalan@Sun.COM 
504*13101SVenki.Rajagopalan@Sun.COM 	if (pktsz < login_sz) {
505*13101SVenki.Rajagopalan@Sun.COM 		*err = EINVAL;
506*13101SVenki.Rajagopalan@Sun.COM 
507*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_make_login: "
508*13101SVenki.Rajagopalan@Sun.COM 		    "send buffer size (0x%lx) too small to send"
509*13101SVenki.Rajagopalan@Sun.COM 		    "login request (min 0x%lx)",
510*13101SVenki.Rajagopalan@Sun.COM 		    pktsz, login_sz);
511*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
512*13101SVenki.Rajagopalan@Sun.COM 	}
513*13101SVenki.Rajagopalan@Sun.COM 
514*13101SVenki.Rajagopalan@Sun.COM 	/*
515*13101SVenki.Rajagopalan@Sun.COM 	 * Lint complains that there may be an alignment issue here,
516*13101SVenki.Rajagopalan@Sun.COM 	 * but we know that the "pkt" is atleast double-word aligned,
517*13101SVenki.Rajagopalan@Sun.COM 	 * so it's ok.
518*13101SVenki.Rajagopalan@Sun.COM 	 */
519*13101SVenki.Rajagopalan@Sun.COM 	login = (fip_login_t *)(void *)pkt;
520*13101SVenki.Rajagopalan@Sun.COM 	bzero(pkt, login_sz);
521*13101SVenki.Rajagopalan@Sun.COM 
522*13101SVenki.Rajagopalan@Sun.COM 	/*
523*13101SVenki.Rajagopalan@Sun.COM 	 * Fill in the FIP protocol version
524*13101SVenki.Rajagopalan@Sun.COM 	 */
525*13101SVenki.Rajagopalan@Sun.COM 	proto = &login->lg_proto_version;
526*13101SVenki.Rajagopalan@Sun.COM 	proto->pr_version = FIP_PROTO_VERSION;
527*13101SVenki.Rajagopalan@Sun.COM 
528*13101SVenki.Rajagopalan@Sun.COM 	/*
529*13101SVenki.Rajagopalan@Sun.COM 	 * Fill in the basic header
530*13101SVenki.Rajagopalan@Sun.COM 	 */
531*13101SVenki.Rajagopalan@Sun.COM 	hdr = &login->lg_fip_header;
532*13101SVenki.Rajagopalan@Sun.COM 	hdr->hd_opcode = htons(FIP_OPCODE_EOIB);
533*13101SVenki.Rajagopalan@Sun.COM 	hdr->hd_subcode = FIP_SUBCODE_H_VNIC_LOGIN;
534*13101SVenki.Rajagopalan@Sun.COM 	hdr->hd_desc_list_len = htons((login_sz >> 2) - 2);
535*13101SVenki.Rajagopalan@Sun.COM 	hdr->hd_flags = 0;
536*13101SVenki.Rajagopalan@Sun.COM 	hdr->hd_type = FIP_DESC_TYPE_VENDOR_ID;
537*13101SVenki.Rajagopalan@Sun.COM 	hdr->hd_len = FIP_DESC_LEN_VENDOR_ID;
538*13101SVenki.Rajagopalan@Sun.COM 	bcopy(eib_vendor_mellanox, hdr->hd_vendor_id, FIP_VENDOR_LEN);
539*13101SVenki.Rajagopalan@Sun.COM 
540*13101SVenki.Rajagopalan@Sun.COM 	/*
541*13101SVenki.Rajagopalan@Sun.COM 	 * Fill in the Infiniband Address descriptor
542*13101SVenki.Rajagopalan@Sun.COM 	 */
543*13101SVenki.Rajagopalan@Sun.COM 	iba = &login->lg_iba;
544*13101SVenki.Rajagopalan@Sun.COM 	iba->ia_type = FIP_DESC_TYPE_IBA;
545*13101SVenki.Rajagopalan@Sun.COM 	iba->ia_len = FIP_DESC_LEN_IBA;
546*13101SVenki.Rajagopalan@Sun.COM 	bcopy(eib_vendor_mellanox, iba->ia_vendor_id, FIP_VENDOR_LEN);
547*13101SVenki.Rajagopalan@Sun.COM 	iba->ia_qpn = htonl(vnic->vn_data_chan->ch_qpn);
548*13101SVenki.Rajagopalan@Sun.COM 
549*13101SVenki.Rajagopalan@Sun.COM 	sl_portid = (gw_portid & FIP_IBA_PORTID_MASK) |
550*13101SVenki.Rajagopalan@Sun.COM 	    ((sl << FIP_IBA_SL_SHIFT) & FIP_IBA_SL_MASK);
551*13101SVenki.Rajagopalan@Sun.COM 	iba->ia_sl_portid = htons(sl_portid);
552*13101SVenki.Rajagopalan@Sun.COM 
553*13101SVenki.Rajagopalan@Sun.COM 	iba->ia_lid = htons(ss->ei_props->ep_blid);
554*13101SVenki.Rajagopalan@Sun.COM 
555*13101SVenki.Rajagopalan@Sun.COM 	port_gid = ss->ei_props->ep_sgid;
556*13101SVenki.Rajagopalan@Sun.COM 	port_guid = htonll(port_gid.gid_guid);
557*13101SVenki.Rajagopalan@Sun.COM 	bcopy(&port_guid, iba->ia_guid, FIP_GUID_LEN);
558*13101SVenki.Rajagopalan@Sun.COM 
559*13101SVenki.Rajagopalan@Sun.COM 	/*
560*13101SVenki.Rajagopalan@Sun.COM 	 * Now, fill in the vNIC Login descriptor
561*13101SVenki.Rajagopalan@Sun.COM 	 */
562*13101SVenki.Rajagopalan@Sun.COM 
563*13101SVenki.Rajagopalan@Sun.COM 	vlg = &login->lg_vnic_login;
564*13101SVenki.Rajagopalan@Sun.COM 	vlg->vl_type = FIP_DESC_TYPE_VNIC_LOGIN;
565*13101SVenki.Rajagopalan@Sun.COM 	vlg->vl_len = FIP_DESC_LEN_VNIC_LOGIN;
566*13101SVenki.Rajagopalan@Sun.COM 	bcopy(eib_vendor_mellanox, vlg->vl_vendor_id, FIP_VENDOR_LEN);
567*13101SVenki.Rajagopalan@Sun.COM 
568*13101SVenki.Rajagopalan@Sun.COM 	/*
569*13101SVenki.Rajagopalan@Sun.COM 	 * Only for the physlink instance 0, we ask the gateway to assign
570*13101SVenki.Rajagopalan@Sun.COM 	 * the mac address and a VLAN (tagless, actually).  For this vnic
571*13101SVenki.Rajagopalan@Sun.COM 	 * only, we do not set the H bit. All other vnics are created by
572*13101SVenki.Rajagopalan@Sun.COM 	 * Solaris admin and will have the H bit set. Note also that we
573*13101SVenki.Rajagopalan@Sun.COM 	 * need to clear the vnic id's most significant bit for those that
574*13101SVenki.Rajagopalan@Sun.COM 	 * are administered by the gateway, so vnic0's vnic_id's msb should
575*13101SVenki.Rajagopalan@Sun.COM 	 * be 0 as well.
576*13101SVenki.Rajagopalan@Sun.COM 	 */
577*13101SVenki.Rajagopalan@Sun.COM 	if (vnic->vn_instance == 0) {
578*13101SVenki.Rajagopalan@Sun.COM 		vlg->vl_vnic_id = htons(vnic->vn_id);
579*13101SVenki.Rajagopalan@Sun.COM 		flags_vlan = vnic->vn_vlan & FIP_VL_VLAN_MASK;
580*13101SVenki.Rajagopalan@Sun.COM 	} else {
581*13101SVenki.Rajagopalan@Sun.COM 		vlg->vl_vnic_id = htons(vnic->vn_id | FIP_VL_VNIC_ID_MSBIT);
582*13101SVenki.Rajagopalan@Sun.COM 		flags_vlan = (vnic->vn_vlan & FIP_VL_VLAN_MASK) |
583*13101SVenki.Rajagopalan@Sun.COM 		    FIP_VL_FLAGS_H | FIP_VL_FLAGS_M;
584*13101SVenki.Rajagopalan@Sun.COM 
585*13101SVenki.Rajagopalan@Sun.COM 		if (vnic->vn_vlan & FIP_VL_VLAN_MASK)
586*13101SVenki.Rajagopalan@Sun.COM 			flags_vlan |= (FIP_VL_FLAGS_V | FIP_VL_FLAGS_VP);
587*13101SVenki.Rajagopalan@Sun.COM 	}
588*13101SVenki.Rajagopalan@Sun.COM 
589*13101SVenki.Rajagopalan@Sun.COM 	vlg->vl_flags_vlan = htons(flags_vlan);
590*13101SVenki.Rajagopalan@Sun.COM 	bcopy(vnic->vn_macaddr, vlg->vl_mac, ETHERADDRL);
591*13101SVenki.Rajagopalan@Sun.COM 
592*13101SVenki.Rajagopalan@Sun.COM 	/*
593*13101SVenki.Rajagopalan@Sun.COM 	 * We aren't ready to enable rss, so we set the RSS bit and
594*13101SVenki.Rajagopalan@Sun.COM 	 * the n_rss_mcgid field to 0.  Set the mac mcgid to 0 as well.
595*13101SVenki.Rajagopalan@Sun.COM 	 */
596*13101SVenki.Rajagopalan@Sun.COM 	vlg->vl_flags_rss = 0;
597*13101SVenki.Rajagopalan@Sun.COM 	vlg->vl_n_mac_mcgid = 0;
598*13101SVenki.Rajagopalan@Sun.COM 
599*13101SVenki.Rajagopalan@Sun.COM 	/*
600*13101SVenki.Rajagopalan@Sun.COM 	 * Set the syndrome to 0 and pass the control qpn
601*13101SVenki.Rajagopalan@Sun.COM 	 */
602*13101SVenki.Rajagopalan@Sun.COM 	vlg->vl_syndrome_ctl_qpn =
603*13101SVenki.Rajagopalan@Sun.COM 	    htonl(vnic->vn_ctl_chan->ch_qpn & FIP_VL_CTL_QPN_MASK);
604*13101SVenki.Rajagopalan@Sun.COM 
605*13101SVenki.Rajagopalan@Sun.COM 	/*
606*13101SVenki.Rajagopalan@Sun.COM 	 * Try to set as unique a name as possible for this vnic
607*13101SVenki.Rajagopalan@Sun.COM 	 */
608*13101SVenki.Rajagopalan@Sun.COM 	(void) snprintf((char *)(vlg->vl_vnic_name), FIP_VNIC_NAME_LEN,
609*13101SVenki.Rajagopalan@Sun.COM 	    "eoib_%02x_%02x", ss->ei_instance, vnic->vn_instance);
610*13101SVenki.Rajagopalan@Sun.COM 
611*13101SVenki.Rajagopalan@Sun.COM 	/*
612*13101SVenki.Rajagopalan@Sun.COM 	 * Adjust the ds_len in the sgl to indicate the size of this
613*13101SVenki.Rajagopalan@Sun.COM 	 * request before returning
614*13101SVenki.Rajagopalan@Sun.COM 	 */
615*13101SVenki.Rajagopalan@Sun.COM 	swqe->qe_sgl.ds_len = login_sz;
616*13101SVenki.Rajagopalan@Sun.COM 
617*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
618*13101SVenki.Rajagopalan@Sun.COM }
619*13101SVenki.Rajagopalan@Sun.COM 
620*13101SVenki.Rajagopalan@Sun.COM static int
eib_fip_make_update(eib_t * ss,eib_vnic_t * vnic,eib_wqe_t * swqe,int req,int * err)621*13101SVenki.Rajagopalan@Sun.COM eib_fip_make_update(eib_t *ss, eib_vnic_t *vnic, eib_wqe_t *swqe, int req,
622*13101SVenki.Rajagopalan@Sun.COM     int *err)
623*13101SVenki.Rajagopalan@Sun.COM {
624*13101SVenki.Rajagopalan@Sun.COM 	fip_keep_alive_t *ka;
625*13101SVenki.Rajagopalan@Sun.COM 	fip_proto_t *proto;
626*13101SVenki.Rajagopalan@Sun.COM 	fip_basic_hdr_t *hdr;
627*13101SVenki.Rajagopalan@Sun.COM 	fip_desc_vnic_identity_t *vid;
628*13101SVenki.Rajagopalan@Sun.COM 	ib_gid_t port_gid;
629*13101SVenki.Rajagopalan@Sun.COM 	ib_guid_t port_guid;
630*13101SVenki.Rajagopalan@Sun.COM 	uint32_t flags_vhub_id;
631*13101SVenki.Rajagopalan@Sun.COM 
632*13101SVenki.Rajagopalan@Sun.COM 	uint8_t *pkt = (uint8_t *)(uintptr_t)(swqe->qe_sgl.ds_va);
633*13101SVenki.Rajagopalan@Sun.COM 	uint_t pktsz = swqe->qe_sgl.ds_len;
634*13101SVenki.Rajagopalan@Sun.COM 	uint_t ka_sz = sizeof (fip_keep_alive_t);
635*13101SVenki.Rajagopalan@Sun.COM 
636*13101SVenki.Rajagopalan@Sun.COM 	if (pktsz < ka_sz) {
637*13101SVenki.Rajagopalan@Sun.COM 		*err = EINVAL;
638*13101SVenki.Rajagopalan@Sun.COM 
639*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_make_update: "
640*13101SVenki.Rajagopalan@Sun.COM 		    "send buffer size (0x%lx) too small to send"
641*13101SVenki.Rajagopalan@Sun.COM 		    "keepalive/update request (min 0x%lx)",
642*13101SVenki.Rajagopalan@Sun.COM 		    pktsz, ka_sz);
643*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
644*13101SVenki.Rajagopalan@Sun.COM 	}
645*13101SVenki.Rajagopalan@Sun.COM 
646*13101SVenki.Rajagopalan@Sun.COM 	/*
647*13101SVenki.Rajagopalan@Sun.COM 	 * Lint complains that there may be an alignment issue here,
648*13101SVenki.Rajagopalan@Sun.COM 	 * but we know that the "pkt" is atleast double-word aligned,
649*13101SVenki.Rajagopalan@Sun.COM 	 * so it's ok.
650*13101SVenki.Rajagopalan@Sun.COM 	 */
651*13101SVenki.Rajagopalan@Sun.COM 	ka = (fip_keep_alive_t *)(void *)pkt;
652*13101SVenki.Rajagopalan@Sun.COM 	bzero(pkt, ka_sz);
653*13101SVenki.Rajagopalan@Sun.COM 
654*13101SVenki.Rajagopalan@Sun.COM 	/*
655*13101SVenki.Rajagopalan@Sun.COM 	 * Fill in the FIP protocol version
656*13101SVenki.Rajagopalan@Sun.COM 	 */
657*13101SVenki.Rajagopalan@Sun.COM 	proto = &ka->ka_proto_version;
658*13101SVenki.Rajagopalan@Sun.COM 	proto->pr_version = FIP_PROTO_VERSION;
659*13101SVenki.Rajagopalan@Sun.COM 
660*13101SVenki.Rajagopalan@Sun.COM 	/*
661*13101SVenki.Rajagopalan@Sun.COM 	 * Fill in the basic header
662*13101SVenki.Rajagopalan@Sun.COM 	 */
663*13101SVenki.Rajagopalan@Sun.COM 	hdr = &ka->ka_fip_header;
664*13101SVenki.Rajagopalan@Sun.COM 	hdr->hd_opcode = htons(FIP_OPCODE_EOIB);
665*13101SVenki.Rajagopalan@Sun.COM 	hdr->hd_subcode = (req == EIB_UPD_REQ_LOGOUT) ?
666*13101SVenki.Rajagopalan@Sun.COM 	    FIP_SUBCODE_H_VNIC_LOGOUT : FIP_SUBCODE_H_KEEP_ALIVE;
667*13101SVenki.Rajagopalan@Sun.COM 	hdr->hd_desc_list_len = htons((ka_sz >> 2) - 2);
668*13101SVenki.Rajagopalan@Sun.COM 	hdr->hd_flags = 0;
669*13101SVenki.Rajagopalan@Sun.COM 	hdr->hd_type = FIP_DESC_TYPE_VENDOR_ID;
670*13101SVenki.Rajagopalan@Sun.COM 	hdr->hd_len = FIP_DESC_LEN_VENDOR_ID;
671*13101SVenki.Rajagopalan@Sun.COM 	bcopy(eib_vendor_mellanox, hdr->hd_vendor_id, FIP_VENDOR_LEN);
672*13101SVenki.Rajagopalan@Sun.COM 
673*13101SVenki.Rajagopalan@Sun.COM 	/*
674*13101SVenki.Rajagopalan@Sun.COM 	 * Fill in the vNIC Identity descriptor
675*13101SVenki.Rajagopalan@Sun.COM 	 */
676*13101SVenki.Rajagopalan@Sun.COM 	vid = &ka->ka_vnic_identity;
677*13101SVenki.Rajagopalan@Sun.COM 
678*13101SVenki.Rajagopalan@Sun.COM 	vid->vi_type = FIP_DESC_TYPE_VNIC_IDENTITY;
679*13101SVenki.Rajagopalan@Sun.COM 	vid->vi_len = FIP_DESC_LEN_VNIC_IDENTITY;
680*13101SVenki.Rajagopalan@Sun.COM 	bcopy(eib_vendor_mellanox, vid->vi_vendor_id, FIP_VENDOR_LEN);
681*13101SVenki.Rajagopalan@Sun.COM 
682*13101SVenki.Rajagopalan@Sun.COM 	flags_vhub_id = vnic->vn_login_data.ld_vhub_id;
683*13101SVenki.Rajagopalan@Sun.COM 	if (vnic->vn_login_data.ld_vlan_in_packets) {
684*13101SVenki.Rajagopalan@Sun.COM 		flags_vhub_id |= FIP_VI_FLAG_VP;
685*13101SVenki.Rajagopalan@Sun.COM 	}
686*13101SVenki.Rajagopalan@Sun.COM 	if (req == EIB_UPD_REQ_TABLE) {
687*13101SVenki.Rajagopalan@Sun.COM 		flags_vhub_id |= FIP_VI_FLAG_R;
688*13101SVenki.Rajagopalan@Sun.COM 	} else if (req == EIB_UPD_REQ_KA) {
689*13101SVenki.Rajagopalan@Sun.COM 		flags_vhub_id |= FIP_VI_FLAG_U;
690*13101SVenki.Rajagopalan@Sun.COM 	}
691*13101SVenki.Rajagopalan@Sun.COM 	vid->vi_flags_vhub_id = htonl(flags_vhub_id);
692*13101SVenki.Rajagopalan@Sun.COM 
693*13101SVenki.Rajagopalan@Sun.COM 	vid->vi_tusn = (req != EIB_UPD_REQ_LOGOUT) ?
694*13101SVenki.Rajagopalan@Sun.COM 	    htonl(vnic->vn_vhub_table->tb_tusn) : 0;
695*13101SVenki.Rajagopalan@Sun.COM 
696*13101SVenki.Rajagopalan@Sun.COM 	vid->vi_vnic_id = htons(vnic->vn_login_data.ld_vnic_id);
697*13101SVenki.Rajagopalan@Sun.COM 	bcopy(vnic->vn_login_data.ld_assigned_mac, vid->vi_mac, ETHERADDRL);
698*13101SVenki.Rajagopalan@Sun.COM 
699*13101SVenki.Rajagopalan@Sun.COM 	port_gid = ss->ei_props->ep_sgid;
700*13101SVenki.Rajagopalan@Sun.COM 	port_guid = htonll(port_gid.gid_guid);
701*13101SVenki.Rajagopalan@Sun.COM 	bcopy(&port_guid, vid->vi_port_guid, FIP_GUID_LEN);
702*13101SVenki.Rajagopalan@Sun.COM 	bcopy(vnic->vn_login_data.ld_vnic_name, vid->vi_vnic_name,
703*13101SVenki.Rajagopalan@Sun.COM 	    FIP_VNIC_NAME_LEN);
704*13101SVenki.Rajagopalan@Sun.COM 
705*13101SVenki.Rajagopalan@Sun.COM 	/*
706*13101SVenki.Rajagopalan@Sun.COM 	 * Adjust the ds_len in the sgl to indicate the size of this
707*13101SVenki.Rajagopalan@Sun.COM 	 * request before returning
708*13101SVenki.Rajagopalan@Sun.COM 	 */
709*13101SVenki.Rajagopalan@Sun.COM 	swqe->qe_sgl.ds_len = ka_sz;
710*13101SVenki.Rajagopalan@Sun.COM 
711*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
712*13101SVenki.Rajagopalan@Sun.COM }
713*13101SVenki.Rajagopalan@Sun.COM 
714*13101SVenki.Rajagopalan@Sun.COM static int
eib_fip_make_table(eib_t * ss,eib_vnic_t * vnic,eib_wqe_t * swqe,int * err)715*13101SVenki.Rajagopalan@Sun.COM eib_fip_make_table(eib_t *ss, eib_vnic_t *vnic, eib_wqe_t *swqe, int *err)
716*13101SVenki.Rajagopalan@Sun.COM {
717*13101SVenki.Rajagopalan@Sun.COM 	return (eib_fip_make_update(ss, vnic, swqe, EIB_UPD_REQ_TABLE, err));
718*13101SVenki.Rajagopalan@Sun.COM }
719*13101SVenki.Rajagopalan@Sun.COM 
720*13101SVenki.Rajagopalan@Sun.COM static int
eib_fip_make_ka(eib_t * ss,eib_vnic_t * vnic,eib_wqe_t * swqe,int * err)721*13101SVenki.Rajagopalan@Sun.COM eib_fip_make_ka(eib_t *ss, eib_vnic_t *vnic, eib_wqe_t *swqe, int *err)
722*13101SVenki.Rajagopalan@Sun.COM {
723*13101SVenki.Rajagopalan@Sun.COM 	return (eib_fip_make_update(ss, vnic, swqe, EIB_UPD_REQ_KA, err));
724*13101SVenki.Rajagopalan@Sun.COM }
725*13101SVenki.Rajagopalan@Sun.COM 
726*13101SVenki.Rajagopalan@Sun.COM static int
eib_fip_make_logout(eib_t * ss,eib_vnic_t * vnic,eib_wqe_t * swqe,int * err)727*13101SVenki.Rajagopalan@Sun.COM eib_fip_make_logout(eib_t *ss, eib_vnic_t *vnic, eib_wqe_t *swqe, int *err)
728*13101SVenki.Rajagopalan@Sun.COM {
729*13101SVenki.Rajagopalan@Sun.COM 	return (eib_fip_make_update(ss, vnic, swqe, EIB_UPD_REQ_LOGOUT, err));
730*13101SVenki.Rajagopalan@Sun.COM }
731*13101SVenki.Rajagopalan@Sun.COM 
732*13101SVenki.Rajagopalan@Sun.COM static int
eib_fip_send_login(eib_t * ss,eib_vnic_t * vnic,eib_wqe_t * swqe,int * err)733*13101SVenki.Rajagopalan@Sun.COM eib_fip_send_login(eib_t *ss, eib_vnic_t *vnic, eib_wqe_t *swqe, int *err)
734*13101SVenki.Rajagopalan@Sun.COM {
735*13101SVenki.Rajagopalan@Sun.COM 	eib_avect_t *av;
736*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = ss->ei_admin_chan;
737*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
738*13101SVenki.Rajagopalan@Sun.COM 
739*13101SVenki.Rajagopalan@Sun.COM 	/*
740*13101SVenki.Rajagopalan@Sun.COM 	 * Get an address vector for this destination
741*13101SVenki.Rajagopalan@Sun.COM 	 */
742*13101SVenki.Rajagopalan@Sun.COM 	if ((av = eib_ibt_hold_avect(ss, ss->ei_gw_props->pp_gw_lid,
743*13101SVenki.Rajagopalan@Sun.COM 	    ss->ei_gw_props->pp_gw_sl)) == NULL) {
744*13101SVenki.Rajagopalan@Sun.COM 		*err = ENOMEM;
745*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_send_login: "
746*13101SVenki.Rajagopalan@Sun.COM 		    "eib_ibt_hold_avect(gw_lid=0x%x, sl=0x%x) failed",
747*13101SVenki.Rajagopalan@Sun.COM 		    ss->ei_gw_props->pp_gw_lid, ss->ei_gw_props->pp_gw_sl);
748*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
749*13101SVenki.Rajagopalan@Sun.COM 	}
750*13101SVenki.Rajagopalan@Sun.COM 
751*13101SVenki.Rajagopalan@Sun.COM 	/*
752*13101SVenki.Rajagopalan@Sun.COM 	 * Modify the UD destination handle to the gateway
753*13101SVenki.Rajagopalan@Sun.COM 	 */
754*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_modify_ud_dest(swqe->qe_dest, EIB_FIP_QKEY,
755*13101SVenki.Rajagopalan@Sun.COM 	    ss->ei_gw_props->pp_gw_ctrl_qpn, &av->av_vect);
756*13101SVenki.Rajagopalan@Sun.COM 
757*13101SVenki.Rajagopalan@Sun.COM 	eib_ibt_release_avect(ss, av);
758*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
759*13101SVenki.Rajagopalan@Sun.COM 		*err = EINVAL;
760*13101SVenki.Rajagopalan@Sun.COM 
761*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_send_login: "
762*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_modify_ud_dest(gw_ctl_qpn=0x%lx, qkey=0x%lx) failed, "
763*13101SVenki.Rajagopalan@Sun.COM 		    "ret=%d", ss->ei_gw_props->pp_gw_ctrl_qpn,
764*13101SVenki.Rajagopalan@Sun.COM 		    EIB_FIP_QKEY, ret);
765*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
766*13101SVenki.Rajagopalan@Sun.COM 	}
767*13101SVenki.Rajagopalan@Sun.COM 
768*13101SVenki.Rajagopalan@Sun.COM 	/*
769*13101SVenki.Rajagopalan@Sun.COM 	 * Send the login packet to the destination gateway. Posting
770*13101SVenki.Rajagopalan@Sun.COM 	 * the login and setting the login state to wait-for-ack should
771*13101SVenki.Rajagopalan@Sun.COM 	 * ideally be atomic to avoid race.
772*13101SVenki.Rajagopalan@Sun.COM 	 */
773*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&vnic->vn_lock);
774*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_post_send(chan->ch_chan, &(swqe->qe_wr.send), 1, NULL);
775*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
776*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&vnic->vn_lock);
777*13101SVenki.Rajagopalan@Sun.COM 		*err = EINVAL;
778*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_send_login: "
779*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_post_send() failed for vnic id 0x%x, ret=%d",
780*13101SVenki.Rajagopalan@Sun.COM 		    vnic->vn_id, ret);
781*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
782*13101SVenki.Rajagopalan@Sun.COM 	}
783*13101SVenki.Rajagopalan@Sun.COM 	vnic->vn_state = EIB_LOGIN_ACK_WAIT;
784*13101SVenki.Rajagopalan@Sun.COM 
785*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&chan->ch_tx_lock);
786*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_tx_posted++;
787*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&chan->ch_tx_lock);
788*13101SVenki.Rajagopalan@Sun.COM 
789*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&vnic->vn_lock);
790*13101SVenki.Rajagopalan@Sun.COM 
791*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
792*13101SVenki.Rajagopalan@Sun.COM }
793*13101SVenki.Rajagopalan@Sun.COM 
794*13101SVenki.Rajagopalan@Sun.COM static int
eib_fip_send_update(eib_t * ss,eib_vnic_t * vnic,eib_wqe_t * swqe,uint_t nxt_state,int * err)795*13101SVenki.Rajagopalan@Sun.COM eib_fip_send_update(eib_t *ss, eib_vnic_t *vnic, eib_wqe_t *swqe,
796*13101SVenki.Rajagopalan@Sun.COM     uint_t nxt_state, int *err)
797*13101SVenki.Rajagopalan@Sun.COM {
798*13101SVenki.Rajagopalan@Sun.COM 	eib_login_data_t *ld = &vnic->vn_login_data;
799*13101SVenki.Rajagopalan@Sun.COM 	eib_chan_t *chan = vnic->vn_ctl_chan;
800*13101SVenki.Rajagopalan@Sun.COM 	eib_avect_t *av;
801*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
802*13101SVenki.Rajagopalan@Sun.COM 
803*13101SVenki.Rajagopalan@Sun.COM 	/*
804*13101SVenki.Rajagopalan@Sun.COM 	 * Get an address vector for this destination
805*13101SVenki.Rajagopalan@Sun.COM 	 */
806*13101SVenki.Rajagopalan@Sun.COM 	if ((av = eib_ibt_hold_avect(ss, ld->ld_gw_lid,
807*13101SVenki.Rajagopalan@Sun.COM 	    ld->ld_gw_sl)) == NULL) {
808*13101SVenki.Rajagopalan@Sun.COM 		*err = ENOMEM;
809*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_send_update: "
810*13101SVenki.Rajagopalan@Sun.COM 		    "eib_ibt_hold_avect(gw_lid=0x%x, sl=0x%x) failed",
811*13101SVenki.Rajagopalan@Sun.COM 		    ld->ld_gw_lid, ld->ld_gw_sl);
812*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
813*13101SVenki.Rajagopalan@Sun.COM 	}
814*13101SVenki.Rajagopalan@Sun.COM 
815*13101SVenki.Rajagopalan@Sun.COM 	/*
816*13101SVenki.Rajagopalan@Sun.COM 	 * Modify the UD destination handle to the destination appropriately
817*13101SVenki.Rajagopalan@Sun.COM 	 */
818*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_modify_ud_dest(swqe->qe_dest, EIB_FIP_QKEY,
819*13101SVenki.Rajagopalan@Sun.COM 	    ld->ld_gw_ctl_qpn, &av->av_vect);
820*13101SVenki.Rajagopalan@Sun.COM 
821*13101SVenki.Rajagopalan@Sun.COM 	eib_ibt_release_avect(ss, av);
822*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
823*13101SVenki.Rajagopalan@Sun.COM 		*err = EINVAL;
824*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_send_update: "
825*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_modify_ud_dest(gw_ctl_qpn=0x%lx, qkey=0x%lx) failed, "
826*13101SVenki.Rajagopalan@Sun.COM 		    "ret=%d", ld->ld_gw_ctl_qpn, EIB_FIP_QKEY, ret);
827*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
828*13101SVenki.Rajagopalan@Sun.COM 	}
829*13101SVenki.Rajagopalan@Sun.COM 
830*13101SVenki.Rajagopalan@Sun.COM 	/*
831*13101SVenki.Rajagopalan@Sun.COM 	 * Send the update packet to the destination. Posting the update request
832*13101SVenki.Rajagopalan@Sun.COM 	 * and setting the login state to wait-for-vhub_table needs to be atomic
833*13101SVenki.Rajagopalan@Sun.COM 	 * to avoid race.
834*13101SVenki.Rajagopalan@Sun.COM 	 */
835*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&vnic->vn_lock);
836*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_post_send(chan->ch_chan, &(swqe->qe_wr.send), 1, NULL);
837*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
838*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&vnic->vn_lock);
839*13101SVenki.Rajagopalan@Sun.COM 		*err = EINVAL;
840*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_send_update: "
841*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_post_send() failed for vnic id 0x%x, ret=%d",
842*13101SVenki.Rajagopalan@Sun.COM 		    vnic->vn_id, ret);
843*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
844*13101SVenki.Rajagopalan@Sun.COM 	}
845*13101SVenki.Rajagopalan@Sun.COM 	vnic->vn_state = nxt_state;
846*13101SVenki.Rajagopalan@Sun.COM 
847*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&chan->ch_tx_lock);
848*13101SVenki.Rajagopalan@Sun.COM 	chan->ch_tx_posted++;
849*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&chan->ch_tx_lock);
850*13101SVenki.Rajagopalan@Sun.COM 
851*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&vnic->vn_lock);
852*13101SVenki.Rajagopalan@Sun.COM 
853*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
854*13101SVenki.Rajagopalan@Sun.COM }
855*13101SVenki.Rajagopalan@Sun.COM 
856*13101SVenki.Rajagopalan@Sun.COM static int
eib_fip_send_table(eib_t * ss,eib_vnic_t * vnic,eib_wqe_t * swqe,int * err)857*13101SVenki.Rajagopalan@Sun.COM eib_fip_send_table(eib_t *ss, eib_vnic_t *vnic, eib_wqe_t *swqe, int *err)
858*13101SVenki.Rajagopalan@Sun.COM {
859*13101SVenki.Rajagopalan@Sun.COM 	return (eib_fip_send_update(ss, vnic, swqe, EIB_LOGIN_TBL_WAIT, err));
860*13101SVenki.Rajagopalan@Sun.COM }
861*13101SVenki.Rajagopalan@Sun.COM 
862*13101SVenki.Rajagopalan@Sun.COM static int
eib_fip_send_ka(eib_t * ss,eib_vnic_t * vnic,eib_wqe_t * swqe,int * err)863*13101SVenki.Rajagopalan@Sun.COM eib_fip_send_ka(eib_t *ss, eib_vnic_t *vnic, eib_wqe_t *swqe, int *err)
864*13101SVenki.Rajagopalan@Sun.COM {
865*13101SVenki.Rajagopalan@Sun.COM 	return (eib_fip_send_update(ss, vnic, swqe, EIB_LOGIN_DONE, err));
866*13101SVenki.Rajagopalan@Sun.COM }
867*13101SVenki.Rajagopalan@Sun.COM 
868*13101SVenki.Rajagopalan@Sun.COM static int
eib_fip_send_logout(eib_t * ss,eib_vnic_t * vnic,eib_wqe_t * swqe,int * err)869*13101SVenki.Rajagopalan@Sun.COM eib_fip_send_logout(eib_t *ss, eib_vnic_t *vnic, eib_wqe_t *swqe, int *err)
870*13101SVenki.Rajagopalan@Sun.COM {
871*13101SVenki.Rajagopalan@Sun.COM 	return (eib_fip_send_update(ss, vnic, swqe, EIB_LOGOUT_DONE, err));
872*13101SVenki.Rajagopalan@Sun.COM }
873*13101SVenki.Rajagopalan@Sun.COM 
874*13101SVenki.Rajagopalan@Sun.COM static int
eib_fip_parse_vhub_table(uint8_t * pkt,eib_vnic_t * vnic)875*13101SVenki.Rajagopalan@Sun.COM eib_fip_parse_vhub_table(uint8_t *pkt, eib_vnic_t *vnic)
876*13101SVenki.Rajagopalan@Sun.COM {
877*13101SVenki.Rajagopalan@Sun.COM 	fip_vhub_table_t *tbl;
878*13101SVenki.Rajagopalan@Sun.COM 	fip_desc_vhub_table_t *desc_tbl;
879*13101SVenki.Rajagopalan@Sun.COM 	fip_vhub_table_entry_t *entry;
880*13101SVenki.Rajagopalan@Sun.COM 	fip_basic_hdr_t *hdr;
881*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = vnic->vn_ss;
882*13101SVenki.Rajagopalan@Sun.COM 	eib_login_data_t *ld = &vnic->vn_login_data;
883*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_table_t *etbl = vnic->vn_vhub_table;
884*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_update_t *eupd = vnic->vn_vhub_update;
885*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_map_t *newmap;
886*13101SVenki.Rajagopalan@Sun.COM 
887*13101SVenki.Rajagopalan@Sun.COM 	uint32_t *ipkt;
888*13101SVenki.Rajagopalan@Sun.COM 	uint32_t init_checksum = 0;
889*13101SVenki.Rajagopalan@Sun.COM 	uint32_t tusn;
890*13101SVenki.Rajagopalan@Sun.COM 	uint32_t vhub_id;
891*13101SVenki.Rajagopalan@Sun.COM 	uint_t entries_in_pkt;
892*13101SVenki.Rajagopalan@Sun.COM 	uint_t ndx;
893*13101SVenki.Rajagopalan@Sun.COM 	uint_t i;
894*13101SVenki.Rajagopalan@Sun.COM 
895*13101SVenki.Rajagopalan@Sun.COM 	/*
896*13101SVenki.Rajagopalan@Sun.COM 	 * If we're here receiving vhub table messages, we certainly should
897*13101SVenki.Rajagopalan@Sun.COM 	 * have the vhub table structure allocated and present at this point.
898*13101SVenki.Rajagopalan@Sun.COM 	 */
899*13101SVenki.Rajagopalan@Sun.COM 	if (etbl == NULL) {
900*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_vhub_table: "
901*13101SVenki.Rajagopalan@Sun.COM 		    "vhub table missing for vnic id 0x%x", vnic->vn_id);
902*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
903*13101SVenki.Rajagopalan@Sun.COM 	}
904*13101SVenki.Rajagopalan@Sun.COM 
905*13101SVenki.Rajagopalan@Sun.COM 	/*
906*13101SVenki.Rajagopalan@Sun.COM 	 * Note that 'pkt' is always atleast double-word aligned when it is
907*13101SVenki.Rajagopalan@Sun.COM 	 * passed to us, so we can cast it without any problems.
908*13101SVenki.Rajagopalan@Sun.COM 	 */
909*13101SVenki.Rajagopalan@Sun.COM 	ipkt = (uint32_t *)(void *)pkt;
910*13101SVenki.Rajagopalan@Sun.COM 	tbl = (fip_vhub_table_t *)(void *)pkt;
911*13101SVenki.Rajagopalan@Sun.COM 	hdr = &(tbl->vt_fip_header);
912*13101SVenki.Rajagopalan@Sun.COM 
913*13101SVenki.Rajagopalan@Sun.COM 	/*
914*13101SVenki.Rajagopalan@Sun.COM 	 * Validate all the header and descriptor types and lengths
915*13101SVenki.Rajagopalan@Sun.COM 	 */
916*13101SVenki.Rajagopalan@Sun.COM 	if (hdr->hd_type != FIP_DESC_TYPE_VENDOR_ID ||
917*13101SVenki.Rajagopalan@Sun.COM 	    hdr->hd_len != FIP_DESC_LEN_VENDOR_ID) {
918*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_vhub_table: "
919*13101SVenki.Rajagopalan@Sun.COM 		    "invalid type/len in fip basic header, "
920*13101SVenki.Rajagopalan@Sun.COM 		    "exp (0x%x,0x%x), got (0x%x,0x%x)",
921*13101SVenki.Rajagopalan@Sun.COM 		    FIP_DESC_TYPE_VENDOR_ID, FIP_DESC_LEN_VENDOR_ID,
922*13101SVenki.Rajagopalan@Sun.COM 		    hdr->hd_type, hdr->hd_len);
923*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
924*13101SVenki.Rajagopalan@Sun.COM 	}
925*13101SVenki.Rajagopalan@Sun.COM 	desc_tbl = &(tbl->vt_vhub_table);
926*13101SVenki.Rajagopalan@Sun.COM 	if (desc_tbl->tb_type != FIP_DESC_TYPE_VHUB_TABLE) {
927*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_vhub_table: "
928*13101SVenki.Rajagopalan@Sun.COM 		    "invalid type in vhub desc, exp 0x%x, got 0x%x",
929*13101SVenki.Rajagopalan@Sun.COM 		    FIP_DESC_TYPE_VHUB_TABLE, desc_tbl->tb_type);
930*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
931*13101SVenki.Rajagopalan@Sun.COM 	}
932*13101SVenki.Rajagopalan@Sun.COM 
933*13101SVenki.Rajagopalan@Sun.COM 	/*
934*13101SVenki.Rajagopalan@Sun.COM 	 * Verify that the vhub id is ok for this vnic
935*13101SVenki.Rajagopalan@Sun.COM 	 */
936*13101SVenki.Rajagopalan@Sun.COM 	vhub_id = ntohl(desc_tbl->tb_flags_vhub_id) & FIP_TB_VHUB_ID_MASK;
937*13101SVenki.Rajagopalan@Sun.COM 	if (vhub_id != ld->ld_vhub_id) {
938*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_vhub_table: "
939*13101SVenki.Rajagopalan@Sun.COM 		    "invalid vhub id in vhub table pkt: exp 0x%x, got 0x%x",
940*13101SVenki.Rajagopalan@Sun.COM 		    ld->ld_vhub_id, vhub_id);
941*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
942*13101SVenki.Rajagopalan@Sun.COM 	}
943*13101SVenki.Rajagopalan@Sun.COM 
944*13101SVenki.Rajagopalan@Sun.COM 	/*
945*13101SVenki.Rajagopalan@Sun.COM 	 * Count the number of vhub table entries in this packet
946*13101SVenki.Rajagopalan@Sun.COM 	 */
947*13101SVenki.Rajagopalan@Sun.COM 	entries_in_pkt = (desc_tbl->tb_len - FIP_DESC_VHUB_TABLE_WORDS) /
948*13101SVenki.Rajagopalan@Sun.COM 	    FIP_VHUB_TABLE_ENTRY_WORDS;
949*13101SVenki.Rajagopalan@Sun.COM 
950*13101SVenki.Rajagopalan@Sun.COM 	/*
951*13101SVenki.Rajagopalan@Sun.COM 	 * While we're here, also compute the 32-bit 2's complement carry-
952*13101SVenki.Rajagopalan@Sun.COM 	 * discarded checksum of the vHUB table descriptor in this packet
953*13101SVenki.Rajagopalan@Sun.COM 	 * till the first vhub table entry.
954*13101SVenki.Rajagopalan@Sun.COM 	 */
955*13101SVenki.Rajagopalan@Sun.COM 	for (i = 0; i < FIP_DESC_VHUB_TABLE_WORDS; i++)
956*13101SVenki.Rajagopalan@Sun.COM 		init_checksum += ipkt[i];
957*13101SVenki.Rajagopalan@Sun.COM 
958*13101SVenki.Rajagopalan@Sun.COM 	/*
959*13101SVenki.Rajagopalan@Sun.COM 	 * Initialize the vhub's Table Update Sequence Number (tusn),
960*13101SVenki.Rajagopalan@Sun.COM 	 * checksum and record the total number of entries in in the table
961*13101SVenki.Rajagopalan@Sun.COM 	 * if this is the first pkt of the table.
962*13101SVenki.Rajagopalan@Sun.COM 	 */
963*13101SVenki.Rajagopalan@Sun.COM 	tusn = ntohl(desc_tbl->tb_tusn);
964*13101SVenki.Rajagopalan@Sun.COM 	if (desc_tbl->tb_hdr & FIP_TB_HDR_FIRST) {
965*13101SVenki.Rajagopalan@Sun.COM 		etbl->tb_entries_in_table = ntohs(desc_tbl->tb_table_size);
966*13101SVenki.Rajagopalan@Sun.COM 		etbl->tb_tusn = tusn;
967*13101SVenki.Rajagopalan@Sun.COM 		etbl->tb_checksum = 0;
968*13101SVenki.Rajagopalan@Sun.COM 
969*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&vnic->vn_lock);
970*13101SVenki.Rajagopalan@Sun.COM 		vnic->vn_state = EIB_LOGIN_TBL_INPROG;
971*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&vnic->vn_lock);
972*13101SVenki.Rajagopalan@Sun.COM 	}
973*13101SVenki.Rajagopalan@Sun.COM 
974*13101SVenki.Rajagopalan@Sun.COM 	/*
975*13101SVenki.Rajagopalan@Sun.COM 	 * First, middle or last, the current table TUSN we have must match this
976*13101SVenki.Rajagopalan@Sun.COM 	 * packet's TUSN.
977*13101SVenki.Rajagopalan@Sun.COM 	 */
978*13101SVenki.Rajagopalan@Sun.COM 	if (etbl->tb_tusn != tusn) {
979*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_vhub_table: "
980*13101SVenki.Rajagopalan@Sun.COM 		    "unexpected TUSN (0x%lx) during vhub table construction, "
981*13101SVenki.Rajagopalan@Sun.COM 		    "expected 0x%lx", etbl->tb_tusn, tusn);
982*13101SVenki.Rajagopalan@Sun.COM 		goto vhub_table_fail;
983*13101SVenki.Rajagopalan@Sun.COM 	}
984*13101SVenki.Rajagopalan@Sun.COM 
985*13101SVenki.Rajagopalan@Sun.COM 	/*
986*13101SVenki.Rajagopalan@Sun.COM 	 * See if we've overrun/underrun our original entries count
987*13101SVenki.Rajagopalan@Sun.COM 	 */
988*13101SVenki.Rajagopalan@Sun.COM 	if ((etbl->tb_entries_seen + entries_in_pkt) >
989*13101SVenki.Rajagopalan@Sun.COM 	    etbl->tb_entries_in_table) {
990*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_vhub_table: "
991*13101SVenki.Rajagopalan@Sun.COM 		    "vhub table overrun, total_exp=%d, so_far=%d, this_pkt=%d",
992*13101SVenki.Rajagopalan@Sun.COM 		    etbl->tb_entries_in_table, etbl->tb_entries_seen,
993*13101SVenki.Rajagopalan@Sun.COM 		    entries_in_pkt);
994*13101SVenki.Rajagopalan@Sun.COM 		goto vhub_table_fail;
995*13101SVenki.Rajagopalan@Sun.COM 	} else if (((etbl->tb_entries_seen + entries_in_pkt) <
996*13101SVenki.Rajagopalan@Sun.COM 	    etbl->tb_entries_in_table) &&
997*13101SVenki.Rajagopalan@Sun.COM 	    (desc_tbl->tb_hdr & FIP_TB_HDR_LAST)) {
998*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_vhub_table: "
999*13101SVenki.Rajagopalan@Sun.COM 		    "vhub table underrun, total_exp=%d, so_far=%d, last_pkt=%d",
1000*13101SVenki.Rajagopalan@Sun.COM 		    etbl->tb_entries_in_table, etbl->tb_entries_seen,
1001*13101SVenki.Rajagopalan@Sun.COM 		    entries_in_pkt);
1002*13101SVenki.Rajagopalan@Sun.COM 		goto vhub_table_fail;
1003*13101SVenki.Rajagopalan@Sun.COM 	}
1004*13101SVenki.Rajagopalan@Sun.COM 
1005*13101SVenki.Rajagopalan@Sun.COM 	/*
1006*13101SVenki.Rajagopalan@Sun.COM 	 * Process and add the entries we have in this packet
1007*13101SVenki.Rajagopalan@Sun.COM 	 */
1008*13101SVenki.Rajagopalan@Sun.COM 	etbl->tb_checksum += init_checksum;
1009*13101SVenki.Rajagopalan@Sun.COM 	entry = (fip_vhub_table_entry_t *)(void *)
1010*13101SVenki.Rajagopalan@Sun.COM 	    ((uint8_t *)desc_tbl + FIP_DESC_VHUB_TABLE_SZ);
1011*13101SVenki.Rajagopalan@Sun.COM 
1012*13101SVenki.Rajagopalan@Sun.COM 	for (ndx = 0; ndx < entries_in_pkt; ndx++, entry++) {
1013*13101SVenki.Rajagopalan@Sun.COM 		/*
1014*13101SVenki.Rajagopalan@Sun.COM 		 * Allocate a eib_vhub_map_t, copy the current entry details
1015*13101SVenki.Rajagopalan@Sun.COM 		 * and chain it to the appropriate queue.
1016*13101SVenki.Rajagopalan@Sun.COM 		 */
1017*13101SVenki.Rajagopalan@Sun.COM 		if ((newmap = eib_fip_get_vhub_map()) == NULL) {
1018*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
1019*13101SVenki.Rajagopalan@Sun.COM 			    "eib_fip_parse_vhub_table: no memory for vhub "
1020*13101SVenki.Rajagopalan@Sun.COM 			    "table entry, ignoring this vhub table packet");
1021*13101SVenki.Rajagopalan@Sun.COM 			goto vhub_table_fail;
1022*13101SVenki.Rajagopalan@Sun.COM 		}
1023*13101SVenki.Rajagopalan@Sun.COM 
1024*13101SVenki.Rajagopalan@Sun.COM 		ASSERT((entry->te_v_rss_type & FIP_TE_VALID) == FIP_TE_VALID);
1025*13101SVenki.Rajagopalan@Sun.COM 		newmap->mp_v_rss_type = entry->te_v_rss_type;
1026*13101SVenki.Rajagopalan@Sun.COM 		bcopy(entry->te_mac, newmap->mp_mac, ETHERADDRL);
1027*13101SVenki.Rajagopalan@Sun.COM 		newmap->mp_qpn = (ntohl(entry->te_qpn) & FIP_TE_QPN_MASK);
1028*13101SVenki.Rajagopalan@Sun.COM 		newmap->mp_sl = (entry->te_sl & FIP_TE_SL_MASK);
1029*13101SVenki.Rajagopalan@Sun.COM 		newmap->mp_lid = ntohs(entry->te_lid);
1030*13101SVenki.Rajagopalan@Sun.COM 		newmap->mp_tusn = tusn;
1031*13101SVenki.Rajagopalan@Sun.COM 		newmap->mp_next = NULL;
1032*13101SVenki.Rajagopalan@Sun.COM 
1033*13101SVenki.Rajagopalan@Sun.COM 		/*
1034*13101SVenki.Rajagopalan@Sun.COM 		 * The vhub table messages do not provide status on eport
1035*13101SVenki.Rajagopalan@Sun.COM 		 * state, so we'll simply assume that the eport is up.
1036*13101SVenki.Rajagopalan@Sun.COM 		 */
1037*13101SVenki.Rajagopalan@Sun.COM 		eib_fip_queue_tbl_entry(etbl, newmap, tusn, FIP_EPORT_UP);
1038*13101SVenki.Rajagopalan@Sun.COM 
1039*13101SVenki.Rajagopalan@Sun.COM 		/*
1040*13101SVenki.Rajagopalan@Sun.COM 		 * Update table checksum with this entry's computed checksum
1041*13101SVenki.Rajagopalan@Sun.COM 		 */
1042*13101SVenki.Rajagopalan@Sun.COM 		ipkt = (uint32_t *)entry;
1043*13101SVenki.Rajagopalan@Sun.COM 		for (i = 0; i < FIP_VHUB_TABLE_ENTRY_WORDS; i++)
1044*13101SVenki.Rajagopalan@Sun.COM 			etbl->tb_checksum += ipkt[i];
1045*13101SVenki.Rajagopalan@Sun.COM 	}
1046*13101SVenki.Rajagopalan@Sun.COM 	etbl->tb_entries_seen += entries_in_pkt;
1047*13101SVenki.Rajagopalan@Sun.COM 
1048*13101SVenki.Rajagopalan@Sun.COM 	/*
1049*13101SVenki.Rajagopalan@Sun.COM 	 * If this is the last packet of this vhub table, complete vhub
1050*13101SVenki.Rajagopalan@Sun.COM 	 * table by verifying checksum and applying all the vhub updates
1051*13101SVenki.Rajagopalan@Sun.COM 	 * that may have come in while we were constructing this table.
1052*13101SVenki.Rajagopalan@Sun.COM 	 */
1053*13101SVenki.Rajagopalan@Sun.COM 	if (desc_tbl->tb_hdr & FIP_TB_HDR_LAST) {
1054*13101SVenki.Rajagopalan@Sun.COM 
1055*13101SVenki.Rajagopalan@Sun.COM 		ipkt = (uint32_t *)entry;
1056*13101SVenki.Rajagopalan@Sun.COM 		if (!eib_wa_no_good_vhub_cksum) {
1057*13101SVenki.Rajagopalan@Sun.COM 			if (*ipkt != etbl->tb_checksum) {
1058*13101SVenki.Rajagopalan@Sun.COM 				EIB_DPRINTF_VERBOSE(ss->ei_instance,
1059*13101SVenki.Rajagopalan@Sun.COM 				    "eib_fip_parse_vhub_table: "
1060*13101SVenki.Rajagopalan@Sun.COM 				    "vhub table checksum invalid, "
1061*13101SVenki.Rajagopalan@Sun.COM 				    "computed=0x%lx, found=0x%lx",
1062*13101SVenki.Rajagopalan@Sun.COM 				    etbl->tb_checksum, *ipkt);
1063*13101SVenki.Rajagopalan@Sun.COM 			}
1064*13101SVenki.Rajagopalan@Sun.COM 		}
1065*13101SVenki.Rajagopalan@Sun.COM 
1066*13101SVenki.Rajagopalan@Sun.COM 		/*
1067*13101SVenki.Rajagopalan@Sun.COM 		 * Per the EoIB specification, the gateway is supposed to
1068*13101SVenki.Rajagopalan@Sun.COM 		 * include its address information for data messages in the
1069*13101SVenki.Rajagopalan@Sun.COM 		 * vhub table.  But we've observed that it doesn't do this
1070*13101SVenki.Rajagopalan@Sun.COM 		 * (with the current version). If this is the case, we'll
1071*13101SVenki.Rajagopalan@Sun.COM 		 * hand-create and add a vhub map for the gateway from the
1072*13101SVenki.Rajagopalan@Sun.COM 		 * information we got in login ack.
1073*13101SVenki.Rajagopalan@Sun.COM 		 */
1074*13101SVenki.Rajagopalan@Sun.COM 		if (etbl->tb_gateway == NULL)
1075*13101SVenki.Rajagopalan@Sun.COM 			eib_fip_queue_gw_entry(vnic, etbl, tusn, FIP_EPORT_UP);
1076*13101SVenki.Rajagopalan@Sun.COM 
1077*13101SVenki.Rajagopalan@Sun.COM 		/*
1078*13101SVenki.Rajagopalan@Sun.COM 		 * Apply pending vhub updates and reset table counters needed
1079*13101SVenki.Rajagopalan@Sun.COM 		 * during table construction.
1080*13101SVenki.Rajagopalan@Sun.COM 		 */
1081*13101SVenki.Rajagopalan@Sun.COM 		if (eib_fip_apply_updates(ss, etbl, eupd) != EIB_E_SUCCESS)
1082*13101SVenki.Rajagopalan@Sun.COM 			goto vhub_table_fail;
1083*13101SVenki.Rajagopalan@Sun.COM 
1084*13101SVenki.Rajagopalan@Sun.COM 		etbl->tb_entries_seen = 0;
1085*13101SVenki.Rajagopalan@Sun.COM 		etbl->tb_entries_in_table = 0;
1086*13101SVenki.Rajagopalan@Sun.COM 
1087*13101SVenki.Rajagopalan@Sun.COM 		eib_vnic_vhub_table_done(vnic, EIB_LOGIN_TBL_DONE);
1088*13101SVenki.Rajagopalan@Sun.COM 	}
1089*13101SVenki.Rajagopalan@Sun.COM 
1090*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
1091*13101SVenki.Rajagopalan@Sun.COM 
1092*13101SVenki.Rajagopalan@Sun.COM vhub_table_fail:
1093*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_vhub_table_done(vnic, EIB_LOGIN_TBL_FAILED);
1094*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_FAILURE);
1095*13101SVenki.Rajagopalan@Sun.COM }
1096*13101SVenki.Rajagopalan@Sun.COM 
1097*13101SVenki.Rajagopalan@Sun.COM static int
eib_fip_parse_vhub_update(uint8_t * pkt,eib_vnic_t * vnic)1098*13101SVenki.Rajagopalan@Sun.COM eib_fip_parse_vhub_update(uint8_t *pkt, eib_vnic_t *vnic)
1099*13101SVenki.Rajagopalan@Sun.COM {
1100*13101SVenki.Rajagopalan@Sun.COM 	fip_vhub_update_t *upd;
1101*13101SVenki.Rajagopalan@Sun.COM 	fip_desc_vhub_update_t *desc_upd;
1102*13101SVenki.Rajagopalan@Sun.COM 	fip_vhub_table_entry_t *entry;
1103*13101SVenki.Rajagopalan@Sun.COM 	fip_basic_hdr_t *hdr;
1104*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = vnic->vn_ss;
1105*13101SVenki.Rajagopalan@Sun.COM 	eib_login_data_t *ld = &vnic->vn_login_data;
1106*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_table_t *etbl = vnic->vn_vhub_table;
1107*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_update_t *eupd = vnic->vn_vhub_update;
1108*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_map_t *newmap;
1109*13101SVenki.Rajagopalan@Sun.COM 	boolean_t vhub_tbl_done;
1110*13101SVenki.Rajagopalan@Sun.COM 	uint32_t eport_vp_vhub_id;
1111*13101SVenki.Rajagopalan@Sun.COM 	uint32_t vhub_id;
1112*13101SVenki.Rajagopalan@Sun.COM 	uint32_t tusn;
1113*13101SVenki.Rajagopalan@Sun.COM 	uint32_t prev_tusn;
1114*13101SVenki.Rajagopalan@Sun.COM 	uint8_t eport_state;
1115*13101SVenki.Rajagopalan@Sun.COM 
1116*13101SVenki.Rajagopalan@Sun.COM 	/*
1117*13101SVenki.Rajagopalan@Sun.COM 	 * We should have the vhub table allocated as long as we're receiving
1118*13101SVenki.Rajagopalan@Sun.COM 	 * vhub control messages.
1119*13101SVenki.Rajagopalan@Sun.COM 	 */
1120*13101SVenki.Rajagopalan@Sun.COM 	if (etbl == NULL) {
1121*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_vhub_update: "
1122*13101SVenki.Rajagopalan@Sun.COM 		    "vhub table missing for vnic id 0x%x", vnic->vn_id);
1123*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1124*13101SVenki.Rajagopalan@Sun.COM 	}
1125*13101SVenki.Rajagopalan@Sun.COM 
1126*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&vnic->vn_lock);
1127*13101SVenki.Rajagopalan@Sun.COM 	vhub_tbl_done = ((vnic->vn_state == EIB_LOGIN_TBL_DONE) ||
1128*13101SVenki.Rajagopalan@Sun.COM 	    (vnic->vn_state == EIB_LOGIN_DONE)) ? B_TRUE : B_FALSE;
1129*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&vnic->vn_lock);
1130*13101SVenki.Rajagopalan@Sun.COM 
1131*13101SVenki.Rajagopalan@Sun.COM 	/*
1132*13101SVenki.Rajagopalan@Sun.COM 	 * Note that 'pkt' is always atleast double-word aligned when it is
1133*13101SVenki.Rajagopalan@Sun.COM 	 * passed to us, so we can cast it without any problems.
1134*13101SVenki.Rajagopalan@Sun.COM 	 */
1135*13101SVenki.Rajagopalan@Sun.COM 	upd = (fip_vhub_update_t *)(void *)pkt;
1136*13101SVenki.Rajagopalan@Sun.COM 	hdr = &(upd->vu_fip_header);
1137*13101SVenki.Rajagopalan@Sun.COM 
1138*13101SVenki.Rajagopalan@Sun.COM 	/*
1139*13101SVenki.Rajagopalan@Sun.COM 	 * Validate all the header and descriptor types and lengths
1140*13101SVenki.Rajagopalan@Sun.COM 	 */
1141*13101SVenki.Rajagopalan@Sun.COM 	if (hdr->hd_type != FIP_DESC_TYPE_VENDOR_ID ||
1142*13101SVenki.Rajagopalan@Sun.COM 	    hdr->hd_len != FIP_DESC_LEN_VENDOR_ID) {
1143*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_vhub_update: "
1144*13101SVenki.Rajagopalan@Sun.COM 		    "invalid type/len in fip basic header, "
1145*13101SVenki.Rajagopalan@Sun.COM 		    "exp (0x%x,0x%x), got (0x%x,0x%x)",
1146*13101SVenki.Rajagopalan@Sun.COM 		    FIP_DESC_TYPE_VENDOR_ID, FIP_DESC_LEN_VENDOR_ID,
1147*13101SVenki.Rajagopalan@Sun.COM 		    hdr->hd_type, hdr->hd_len);
1148*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1149*13101SVenki.Rajagopalan@Sun.COM 	}
1150*13101SVenki.Rajagopalan@Sun.COM 	desc_upd = &(upd->vu_vhub_update);
1151*13101SVenki.Rajagopalan@Sun.COM 	if (desc_upd->up_type != FIP_DESC_TYPE_VHUB_UPDATE ||
1152*13101SVenki.Rajagopalan@Sun.COM 	    desc_upd->up_len != FIP_DESC_LEN_VHUB_UPDATE) {
1153*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_vhub_update: "
1154*13101SVenki.Rajagopalan@Sun.COM 		    "invalid type/len in vhub update desc: "
1155*13101SVenki.Rajagopalan@Sun.COM 		    "exp (0x%x,0x%x), got (0x%x,0x%x)",
1156*13101SVenki.Rajagopalan@Sun.COM 		    FIP_DESC_TYPE_VHUB_UPDATE, FIP_DESC_LEN_VHUB_UPDATE,
1157*13101SVenki.Rajagopalan@Sun.COM 		    desc_upd->up_type, desc_upd->up_len);
1158*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1159*13101SVenki.Rajagopalan@Sun.COM 	}
1160*13101SVenki.Rajagopalan@Sun.COM 
1161*13101SVenki.Rajagopalan@Sun.COM 	/*
1162*13101SVenki.Rajagopalan@Sun.COM 	 * Verify that the vhub id is ok for this vnic and save the eport state
1163*13101SVenki.Rajagopalan@Sun.COM 	 */
1164*13101SVenki.Rajagopalan@Sun.COM 	eport_vp_vhub_id = ntohl(desc_upd->up_eport_vp_vhub_id);
1165*13101SVenki.Rajagopalan@Sun.COM 
1166*13101SVenki.Rajagopalan@Sun.COM 	vhub_id = eport_vp_vhub_id & FIP_UP_VHUB_ID_MASK;
1167*13101SVenki.Rajagopalan@Sun.COM 	if (vhub_id != ld->ld_vhub_id) {
1168*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_vhub_update: "
1169*13101SVenki.Rajagopalan@Sun.COM 		    "invalid vhub id in vhub update pkt: exp 0x%x, got 0x%x",
1170*13101SVenki.Rajagopalan@Sun.COM 		    ld->ld_vhub_id, vhub_id);
1171*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1172*13101SVenki.Rajagopalan@Sun.COM 	}
1173*13101SVenki.Rajagopalan@Sun.COM 	eport_state = (uint8_t)((eport_vp_vhub_id >> FIP_UP_EPORT_STATE_SHIFT) &
1174*13101SVenki.Rajagopalan@Sun.COM 	    FIP_UP_EPORT_STATE_MASK);
1175*13101SVenki.Rajagopalan@Sun.COM 
1176*13101SVenki.Rajagopalan@Sun.COM 	/*
1177*13101SVenki.Rajagopalan@Sun.COM 	 * If this is the first update we receive, any tusn is ok.  Otherwise,
1178*13101SVenki.Rajagopalan@Sun.COM 	 * make sure the tusn we see in the packet is appropriate.
1179*13101SVenki.Rajagopalan@Sun.COM 	 */
1180*13101SVenki.Rajagopalan@Sun.COM 	tusn = ntohl(desc_upd->up_tusn);
1181*13101SVenki.Rajagopalan@Sun.COM 	prev_tusn = vhub_tbl_done ? etbl->tb_tusn : eupd->up_tusn;
1182*13101SVenki.Rajagopalan@Sun.COM 
1183*13101SVenki.Rajagopalan@Sun.COM 	if (prev_tusn != 0) {
1184*13101SVenki.Rajagopalan@Sun.COM 		if (tusn == prev_tusn) {
1185*13101SVenki.Rajagopalan@Sun.COM 			eib_fip_update_eport_state(ss, etbl, eupd,
1186*13101SVenki.Rajagopalan@Sun.COM 			    vhub_tbl_done, eport_state);
1187*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_SUCCESS);
1188*13101SVenki.Rajagopalan@Sun.COM 		}
1189*13101SVenki.Rajagopalan@Sun.COM 		if (tusn != (prev_tusn + 1)) {
1190*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
1191*13101SVenki.Rajagopalan@Sun.COM 			    "eib_fip_parse_vhub_update: "
1192*13101SVenki.Rajagopalan@Sun.COM 			    "out of order TUSN received (exp 0x%lx, "
1193*13101SVenki.Rajagopalan@Sun.COM 			    "got 0x%lx), dropping pkt", prev_tusn + 1, tusn);
1194*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_FAILURE);
1195*13101SVenki.Rajagopalan@Sun.COM 		}
1196*13101SVenki.Rajagopalan@Sun.COM 	}
1197*13101SVenki.Rajagopalan@Sun.COM 
1198*13101SVenki.Rajagopalan@Sun.COM 	/*
1199*13101SVenki.Rajagopalan@Sun.COM 	 * EoIB expects only type 0 (vnic address) entries to maintain the
1200*13101SVenki.Rajagopalan@Sun.COM 	 * context table
1201*13101SVenki.Rajagopalan@Sun.COM 	 */
1202*13101SVenki.Rajagopalan@Sun.COM 	entry = &(desc_upd->up_tbl_entry);
1203*13101SVenki.Rajagopalan@Sun.COM 	ASSERT((entry->te_v_rss_type & FIP_TE_TYPE_MASK) == FIP_TE_TYPE_VNIC);
1204*13101SVenki.Rajagopalan@Sun.COM 
1205*13101SVenki.Rajagopalan@Sun.COM 	/*
1206*13101SVenki.Rajagopalan@Sun.COM 	 * If the vHUB table has already been fully constructed and if we've
1207*13101SVenki.Rajagopalan@Sun.COM 	 * now received a notice to remove a vnic entry from it, do it.
1208*13101SVenki.Rajagopalan@Sun.COM 	 */
1209*13101SVenki.Rajagopalan@Sun.COM 	if ((vhub_tbl_done) &&
1210*13101SVenki.Rajagopalan@Sun.COM 	    ((entry->te_v_rss_type & FIP_TE_VALID) == 0)) {
1211*13101SVenki.Rajagopalan@Sun.COM 		eib_fip_dequeue_tbl_entry(etbl, entry->te_mac,
1212*13101SVenki.Rajagopalan@Sun.COM 		    tusn, eport_state);
1213*13101SVenki.Rajagopalan@Sun.COM 
1214*13101SVenki.Rajagopalan@Sun.COM 		if (bcmp(entry->te_mac, ld->ld_assigned_mac, ETHERADDRL) == 0) {
1215*13101SVenki.Rajagopalan@Sun.COM 			uint8_t *mymac;
1216*13101SVenki.Rajagopalan@Sun.COM 
1217*13101SVenki.Rajagopalan@Sun.COM 			mymac = entry->te_mac;
1218*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_WARN(ss->ei_instance,
1219*13101SVenki.Rajagopalan@Sun.COM 			    "eib_fip_parse_vhub_update: "
1220*13101SVenki.Rajagopalan@Sun.COM 			    "vhub update pkt received to kill self "
1221*13101SVenki.Rajagopalan@Sun.COM 			    "(%x:%x:%x:%x:%x:%x)", mymac[0], mymac[1], mymac[2],
1222*13101SVenki.Rajagopalan@Sun.COM 			    mymac[3], mymac[4], mymac[5]);
1223*13101SVenki.Rajagopalan@Sun.COM 
1224*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_FAILURE);
1225*13101SVenki.Rajagopalan@Sun.COM 		}
1226*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_SUCCESS);
1227*13101SVenki.Rajagopalan@Sun.COM 	}
1228*13101SVenki.Rajagopalan@Sun.COM 
1229*13101SVenki.Rajagopalan@Sun.COM 	/*
1230*13101SVenki.Rajagopalan@Sun.COM 	 * Otherwise, allocate a new eib_vhub_map_t and fill it in with
1231*13101SVenki.Rajagopalan@Sun.COM 	 * the details of the new entry
1232*13101SVenki.Rajagopalan@Sun.COM 	 */
1233*13101SVenki.Rajagopalan@Sun.COM 	if ((newmap = eib_fip_get_vhub_map()) == NULL) {
1234*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_parse_vhub_update: "
1235*13101SVenki.Rajagopalan@Sun.COM 		    "no memory for vhub update entry, will be ignoring"
1236*13101SVenki.Rajagopalan@Sun.COM 		    "this vhub update packet");
1237*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1238*13101SVenki.Rajagopalan@Sun.COM 	}
1239*13101SVenki.Rajagopalan@Sun.COM 
1240*13101SVenki.Rajagopalan@Sun.COM 	newmap->mp_v_rss_type = entry->te_v_rss_type;
1241*13101SVenki.Rajagopalan@Sun.COM 	bcopy(entry->te_mac, newmap->mp_mac, ETHERADDRL);
1242*13101SVenki.Rajagopalan@Sun.COM 	newmap->mp_qpn = (ntohl(entry->te_qpn) & FIP_TE_QPN_MASK);
1243*13101SVenki.Rajagopalan@Sun.COM 	newmap->mp_sl = (entry->te_sl & FIP_TE_SL_MASK);
1244*13101SVenki.Rajagopalan@Sun.COM 	newmap->mp_lid = ntohs(entry->te_lid);
1245*13101SVenki.Rajagopalan@Sun.COM 	newmap->mp_tusn = tusn;
1246*13101SVenki.Rajagopalan@Sun.COM 	newmap->mp_next = NULL;
1247*13101SVenki.Rajagopalan@Sun.COM 
1248*13101SVenki.Rajagopalan@Sun.COM 	/*
1249*13101SVenki.Rajagopalan@Sun.COM 	 * Update the full vhub table or chain it to the list of pending
1250*13101SVenki.Rajagopalan@Sun.COM 	 * updates depending on if the vhub table construction is over
1251*13101SVenki.Rajagopalan@Sun.COM 	 * or not.
1252*13101SVenki.Rajagopalan@Sun.COM 	 */
1253*13101SVenki.Rajagopalan@Sun.COM 	if (vhub_tbl_done) {
1254*13101SVenki.Rajagopalan@Sun.COM 		eib_fip_queue_tbl_entry(etbl, newmap, tusn, eport_state);
1255*13101SVenki.Rajagopalan@Sun.COM 	} else {
1256*13101SVenki.Rajagopalan@Sun.COM 		eib_fip_queue_upd_entry(eupd, newmap, tusn, eport_state);
1257*13101SVenki.Rajagopalan@Sun.COM 	}
1258*13101SVenki.Rajagopalan@Sun.COM 
1259*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
1260*13101SVenki.Rajagopalan@Sun.COM }
1261*13101SVenki.Rajagopalan@Sun.COM 
1262*13101SVenki.Rajagopalan@Sun.COM static void
eib_fip_update_eport_state(eib_t * ss,eib_vhub_table_t * tbl,eib_vhub_update_t * upd,boolean_t tbl_done,uint8_t eport_state)1263*13101SVenki.Rajagopalan@Sun.COM eib_fip_update_eport_state(eib_t *ss, eib_vhub_table_t *tbl,
1264*13101SVenki.Rajagopalan@Sun.COM     eib_vhub_update_t *upd, boolean_t tbl_done, uint8_t eport_state)
1265*13101SVenki.Rajagopalan@Sun.COM {
1266*13101SVenki.Rajagopalan@Sun.COM 	if (tbl_done) {
1267*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&tbl->tb_lock);
1268*13101SVenki.Rajagopalan@Sun.COM 		if (tbl->tb_eport_state != eport_state) {
1269*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_DEBUG(ss->ei_instance,
1270*13101SVenki.Rajagopalan@Sun.COM 			    "eib_fip_update_eport_state: "
1271*13101SVenki.Rajagopalan@Sun.COM 			    "eport state changing from %d to %d",
1272*13101SVenki.Rajagopalan@Sun.COM 			    tbl->tb_eport_state, eport_state);
1273*13101SVenki.Rajagopalan@Sun.COM 			tbl->tb_eport_state = eport_state;
1274*13101SVenki.Rajagopalan@Sun.COM 		}
1275*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&tbl->tb_lock);
1276*13101SVenki.Rajagopalan@Sun.COM 	} else {
1277*13101SVenki.Rajagopalan@Sun.COM 		mutex_enter(&upd->up_lock);
1278*13101SVenki.Rajagopalan@Sun.COM 		if (upd->up_eport_state != eport_state) {
1279*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_DEBUG(ss->ei_instance,
1280*13101SVenki.Rajagopalan@Sun.COM 			    "eib_fip_update_eport_state: "
1281*13101SVenki.Rajagopalan@Sun.COM 			    "eport state changing from %d to %d",
1282*13101SVenki.Rajagopalan@Sun.COM 			    upd->up_eport_state, eport_state);
1283*13101SVenki.Rajagopalan@Sun.COM 			upd->up_eport_state = eport_state;
1284*13101SVenki.Rajagopalan@Sun.COM 		}
1285*13101SVenki.Rajagopalan@Sun.COM 		mutex_exit(&upd->up_lock);
1286*13101SVenki.Rajagopalan@Sun.COM 	}
1287*13101SVenki.Rajagopalan@Sun.COM }
1288*13101SVenki.Rajagopalan@Sun.COM 
1289*13101SVenki.Rajagopalan@Sun.COM static void
eib_fip_queue_tbl_entry(eib_vhub_table_t * tbl,eib_vhub_map_t * map,uint32_t tusn,uint8_t eport_state)1290*13101SVenki.Rajagopalan@Sun.COM eib_fip_queue_tbl_entry(eib_vhub_table_t *tbl, eib_vhub_map_t *map,
1291*13101SVenki.Rajagopalan@Sun.COM     uint32_t tusn, uint8_t eport_state)
1292*13101SVenki.Rajagopalan@Sun.COM {
1293*13101SVenki.Rajagopalan@Sun.COM 	uint8_t bkt;
1294*13101SVenki.Rajagopalan@Sun.COM 
1295*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&tbl->tb_lock);
1296*13101SVenki.Rajagopalan@Sun.COM 
1297*13101SVenki.Rajagopalan@Sun.COM 	switch (map->mp_v_rss_type & FIP_TE_TYPE_MASK) {
1298*13101SVenki.Rajagopalan@Sun.COM 	case FIP_TE_TYPE_GATEWAY:
1299*13101SVenki.Rajagopalan@Sun.COM 		if (tbl->tb_gateway) {
1300*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(tbl->tb_gateway,
1301*13101SVenki.Rajagopalan@Sun.COM 			    sizeof (eib_vhub_map_t));
1302*13101SVenki.Rajagopalan@Sun.COM 		}
1303*13101SVenki.Rajagopalan@Sun.COM 		tbl->tb_gateway = map;
1304*13101SVenki.Rajagopalan@Sun.COM 		break;
1305*13101SVenki.Rajagopalan@Sun.COM 
1306*13101SVenki.Rajagopalan@Sun.COM 	case FIP_TE_TYPE_UNICAST_MISS:
1307*13101SVenki.Rajagopalan@Sun.COM 		if (tbl->tb_unicast_miss) {
1308*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(tbl->tb_unicast_miss,
1309*13101SVenki.Rajagopalan@Sun.COM 			    sizeof (eib_vhub_map_t));
1310*13101SVenki.Rajagopalan@Sun.COM 		}
1311*13101SVenki.Rajagopalan@Sun.COM 		tbl->tb_unicast_miss = map;
1312*13101SVenki.Rajagopalan@Sun.COM 		break;
1313*13101SVenki.Rajagopalan@Sun.COM 
1314*13101SVenki.Rajagopalan@Sun.COM 	case FIP_TE_TYPE_VHUB_MULTICAST:
1315*13101SVenki.Rajagopalan@Sun.COM 		if (tbl->tb_vhub_multicast) {
1316*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(tbl->tb_vhub_multicast,
1317*13101SVenki.Rajagopalan@Sun.COM 			    sizeof (eib_vhub_map_t));
1318*13101SVenki.Rajagopalan@Sun.COM 		}
1319*13101SVenki.Rajagopalan@Sun.COM 		tbl->tb_vhub_multicast = map;
1320*13101SVenki.Rajagopalan@Sun.COM 		break;
1321*13101SVenki.Rajagopalan@Sun.COM 
1322*13101SVenki.Rajagopalan@Sun.COM 	case FIP_TE_TYPE_MULTICAST_ENTRY:
1323*13101SVenki.Rajagopalan@Sun.COM 		/*
1324*13101SVenki.Rajagopalan@Sun.COM 		 * If multicast entry types are not to be specially
1325*13101SVenki.Rajagopalan@Sun.COM 		 * processed, treat them like regular vnic addresses.
1326*13101SVenki.Rajagopalan@Sun.COM 		 */
1327*13101SVenki.Rajagopalan@Sun.COM 		if (!eib_wa_no_mcast_entries) {
1328*13101SVenki.Rajagopalan@Sun.COM 			bkt = (map->mp_mac[ETHERADDRL-1]) % EIB_TB_NBUCKETS;
1329*13101SVenki.Rajagopalan@Sun.COM 			map->mp_next = tbl->tb_mcast_entry[bkt];
1330*13101SVenki.Rajagopalan@Sun.COM 			tbl->tb_mcast_entry[bkt] = map;
1331*13101SVenki.Rajagopalan@Sun.COM 			break;
1332*13101SVenki.Rajagopalan@Sun.COM 		}
1333*13101SVenki.Rajagopalan@Sun.COM 		/*FALLTHROUGH*/
1334*13101SVenki.Rajagopalan@Sun.COM 
1335*13101SVenki.Rajagopalan@Sun.COM 	case FIP_TE_TYPE_VNIC:
1336*13101SVenki.Rajagopalan@Sun.COM 		bkt = (map->mp_mac[ETHERADDRL-1]) % EIB_TB_NBUCKETS;
1337*13101SVenki.Rajagopalan@Sun.COM 		map->mp_next = tbl->tb_vnic_entry[bkt];
1338*13101SVenki.Rajagopalan@Sun.COM 		tbl->tb_vnic_entry[bkt] = map;
1339*13101SVenki.Rajagopalan@Sun.COM 		break;
1340*13101SVenki.Rajagopalan@Sun.COM 	}
1341*13101SVenki.Rajagopalan@Sun.COM 
1342*13101SVenki.Rajagopalan@Sun.COM 	tbl->tb_tusn = tusn;
1343*13101SVenki.Rajagopalan@Sun.COM 	tbl->tb_eport_state = eport_state;
1344*13101SVenki.Rajagopalan@Sun.COM 
1345*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&tbl->tb_lock);
1346*13101SVenki.Rajagopalan@Sun.COM }
1347*13101SVenki.Rajagopalan@Sun.COM 
1348*13101SVenki.Rajagopalan@Sun.COM static void
eib_fip_queue_upd_entry(eib_vhub_update_t * upd,eib_vhub_map_t * map,uint32_t tusn,uint8_t eport_state)1349*13101SVenki.Rajagopalan@Sun.COM eib_fip_queue_upd_entry(eib_vhub_update_t *upd, eib_vhub_map_t *map,
1350*13101SVenki.Rajagopalan@Sun.COM     uint32_t tusn, uint8_t eport_state)
1351*13101SVenki.Rajagopalan@Sun.COM {
1352*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_map_t *tail;
1353*13101SVenki.Rajagopalan@Sun.COM 
1354*13101SVenki.Rajagopalan@Sun.COM 	/*
1355*13101SVenki.Rajagopalan@Sun.COM 	 * The eib_vhub_update_t list is only touched/traversed when the
1356*13101SVenki.Rajagopalan@Sun.COM 	 * control cq handler is parsing either update or table message,
1357*13101SVenki.Rajagopalan@Sun.COM 	 * or by the table cleanup routine when we aren't attached to any
1358*13101SVenki.Rajagopalan@Sun.COM 	 * control mcgs.  Bottom line is that this list traversal is always
1359*13101SVenki.Rajagopalan@Sun.COM 	 * single-threaded and we could probably do away with the lock.
1360*13101SVenki.Rajagopalan@Sun.COM 	 */
1361*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&upd->up_lock);
1362*13101SVenki.Rajagopalan@Sun.COM 	for (tail = upd->up_vnic_entry;  tail != NULL; tail = tail->mp_next) {
1363*13101SVenki.Rajagopalan@Sun.COM 		if (tail->mp_next == NULL)
1364*13101SVenki.Rajagopalan@Sun.COM 			break;
1365*13101SVenki.Rajagopalan@Sun.COM 	}
1366*13101SVenki.Rajagopalan@Sun.COM 	if (tail) {
1367*13101SVenki.Rajagopalan@Sun.COM 		tail->mp_next = map;
1368*13101SVenki.Rajagopalan@Sun.COM 	} else {
1369*13101SVenki.Rajagopalan@Sun.COM 		upd->up_vnic_entry = map;
1370*13101SVenki.Rajagopalan@Sun.COM 	}
1371*13101SVenki.Rajagopalan@Sun.COM 
1372*13101SVenki.Rajagopalan@Sun.COM 	upd->up_tusn = tusn;
1373*13101SVenki.Rajagopalan@Sun.COM 	upd->up_eport_state = eport_state;
1374*13101SVenki.Rajagopalan@Sun.COM 
1375*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&upd->up_lock);
1376*13101SVenki.Rajagopalan@Sun.COM }
1377*13101SVenki.Rajagopalan@Sun.COM 
1378*13101SVenki.Rajagopalan@Sun.COM static void
eib_fip_queue_gw_entry(eib_vnic_t * vnic,eib_vhub_table_t * tbl,uint32_t tusn,uint8_t eport_state)1379*13101SVenki.Rajagopalan@Sun.COM eib_fip_queue_gw_entry(eib_vnic_t *vnic, eib_vhub_table_t *tbl, uint32_t tusn,
1380*13101SVenki.Rajagopalan@Sun.COM     uint8_t eport_state)
1381*13101SVenki.Rajagopalan@Sun.COM {
1382*13101SVenki.Rajagopalan@Sun.COM 	eib_t *ss = vnic->vn_ss;
1383*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_map_t *newmap;
1384*13101SVenki.Rajagopalan@Sun.COM 	eib_login_data_t *ld = &vnic->vn_login_data;
1385*13101SVenki.Rajagopalan@Sun.COM 
1386*13101SVenki.Rajagopalan@Sun.COM 	if ((newmap = eib_fip_get_vhub_map()) == NULL) {
1387*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_queue_gw_entry: "
1388*13101SVenki.Rajagopalan@Sun.COM 		    "no memory to queue gw entry, transactions could fail");
1389*13101SVenki.Rajagopalan@Sun.COM 		return;
1390*13101SVenki.Rajagopalan@Sun.COM 	}
1391*13101SVenki.Rajagopalan@Sun.COM 
1392*13101SVenki.Rajagopalan@Sun.COM 	newmap->mp_v_rss_type = FIP_TE_VALID | FIP_TE_TYPE_GATEWAY;
1393*13101SVenki.Rajagopalan@Sun.COM 	bcopy(eib_zero_mac, newmap->mp_mac, ETHERADDRL);
1394*13101SVenki.Rajagopalan@Sun.COM 	newmap->mp_qpn = ld->ld_gw_data_qpn;
1395*13101SVenki.Rajagopalan@Sun.COM 	newmap->mp_sl = ld->ld_gw_sl;
1396*13101SVenki.Rajagopalan@Sun.COM 	newmap->mp_lid = ld->ld_gw_lid;
1397*13101SVenki.Rajagopalan@Sun.COM 	newmap->mp_tusn = tusn;
1398*13101SVenki.Rajagopalan@Sun.COM 	newmap->mp_next = NULL;
1399*13101SVenki.Rajagopalan@Sun.COM 
1400*13101SVenki.Rajagopalan@Sun.COM 	eib_fip_queue_tbl_entry(tbl, newmap, tusn, eport_state);
1401*13101SVenki.Rajagopalan@Sun.COM }
1402*13101SVenki.Rajagopalan@Sun.COM 
1403*13101SVenki.Rajagopalan@Sun.COM static int
eib_fip_apply_updates(eib_t * ss,eib_vhub_table_t * tbl,eib_vhub_update_t * upd)1404*13101SVenki.Rajagopalan@Sun.COM eib_fip_apply_updates(eib_t *ss, eib_vhub_table_t *tbl, eib_vhub_update_t *upd)
1405*13101SVenki.Rajagopalan@Sun.COM {
1406*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_map_t *list;
1407*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_map_t *map;
1408*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_map_t *nxt;
1409*13101SVenki.Rajagopalan@Sun.COM 	uint32_t tbl_tusn = tbl->tb_tusn;
1410*13101SVenki.Rajagopalan@Sun.COM 
1411*13101SVenki.Rajagopalan@Sun.COM 	/*
1412*13101SVenki.Rajagopalan@Sun.COM 	 * Take the update list out
1413*13101SVenki.Rajagopalan@Sun.COM 	 */
1414*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&upd->up_lock);
1415*13101SVenki.Rajagopalan@Sun.COM 	list = upd->up_vnic_entry;
1416*13101SVenki.Rajagopalan@Sun.COM 	upd->up_vnic_entry = NULL;
1417*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&upd->up_lock);
1418*13101SVenki.Rajagopalan@Sun.COM 
1419*13101SVenki.Rajagopalan@Sun.COM 	/*
1420*13101SVenki.Rajagopalan@Sun.COM 	 * Skip any updates with older/same tusn as our vhub table
1421*13101SVenki.Rajagopalan@Sun.COM 	 */
1422*13101SVenki.Rajagopalan@Sun.COM 	nxt = NULL;
1423*13101SVenki.Rajagopalan@Sun.COM 	for (map = list; (map) && (map->mp_tusn <= tbl_tusn); map = nxt) {
1424*13101SVenki.Rajagopalan@Sun.COM 		nxt = map->mp_next;
1425*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(map, sizeof (eib_vhub_map_t));
1426*13101SVenki.Rajagopalan@Sun.COM 	}
1427*13101SVenki.Rajagopalan@Sun.COM 
1428*13101SVenki.Rajagopalan@Sun.COM 	if (map == NULL)
1429*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_SUCCESS);
1430*13101SVenki.Rajagopalan@Sun.COM 
1431*13101SVenki.Rajagopalan@Sun.COM 	/*
1432*13101SVenki.Rajagopalan@Sun.COM 	 * If we missed any updates between table tusn and the first
1433*13101SVenki.Rajagopalan@Sun.COM 	 * update tusn we got, we need to fail.
1434*13101SVenki.Rajagopalan@Sun.COM 	 */
1435*13101SVenki.Rajagopalan@Sun.COM 	if (map->mp_tusn > (tbl_tusn + 1)) {
1436*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_fip_apply_updates: "
1437*13101SVenki.Rajagopalan@Sun.COM 		    "vhub update missed tusn(s), expected=0x%lx, got=0x%lx",
1438*13101SVenki.Rajagopalan@Sun.COM 		    (tbl_tusn + 1), map->mp_tusn);
1439*13101SVenki.Rajagopalan@Sun.COM 		for (; map != NULL; map = nxt) {
1440*13101SVenki.Rajagopalan@Sun.COM 			nxt = map->mp_next;
1441*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(map, sizeof (eib_vhub_map_t));
1442*13101SVenki.Rajagopalan@Sun.COM 		}
1443*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
1444*13101SVenki.Rajagopalan@Sun.COM 	}
1445*13101SVenki.Rajagopalan@Sun.COM 
1446*13101SVenki.Rajagopalan@Sun.COM 	/*
1447*13101SVenki.Rajagopalan@Sun.COM 	 * If everything is fine, apply all the updates we received
1448*13101SVenki.Rajagopalan@Sun.COM 	 */
1449*13101SVenki.Rajagopalan@Sun.COM 	for (; map != NULL; map = nxt) {
1450*13101SVenki.Rajagopalan@Sun.COM 		nxt = map->mp_next;
1451*13101SVenki.Rajagopalan@Sun.COM 		map->mp_next = NULL;
1452*13101SVenki.Rajagopalan@Sun.COM 
1453*13101SVenki.Rajagopalan@Sun.COM 		if (map->mp_v_rss_type & FIP_TE_VALID) {
1454*13101SVenki.Rajagopalan@Sun.COM 			eib_fip_queue_tbl_entry(tbl, map, upd->up_tusn,
1455*13101SVenki.Rajagopalan@Sun.COM 			    upd->up_eport_state);
1456*13101SVenki.Rajagopalan@Sun.COM 		} else {
1457*13101SVenki.Rajagopalan@Sun.COM 			eib_fip_dequeue_tbl_entry(tbl, map->mp_mac,
1458*13101SVenki.Rajagopalan@Sun.COM 			    upd->up_tusn, upd->up_eport_state);
1459*13101SVenki.Rajagopalan@Sun.COM 			kmem_free(map, sizeof (eib_vhub_map_t));
1460*13101SVenki.Rajagopalan@Sun.COM 		}
1461*13101SVenki.Rajagopalan@Sun.COM 	}
1462*13101SVenki.Rajagopalan@Sun.COM 
1463*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
1464*13101SVenki.Rajagopalan@Sun.COM }
1465*13101SVenki.Rajagopalan@Sun.COM 
1466*13101SVenki.Rajagopalan@Sun.COM static void
eib_fip_dequeue_tbl_entry(eib_vhub_table_t * tbl,uint8_t * mac,uint32_t tusn,uint8_t eport_state)1467*13101SVenki.Rajagopalan@Sun.COM eib_fip_dequeue_tbl_entry(eib_vhub_table_t *tbl, uint8_t *mac, uint32_t tusn,
1468*13101SVenki.Rajagopalan@Sun.COM     uint8_t eport_state)
1469*13101SVenki.Rajagopalan@Sun.COM {
1470*13101SVenki.Rajagopalan@Sun.COM 	uint8_t bkt;
1471*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_map_t *prev;
1472*13101SVenki.Rajagopalan@Sun.COM 	eib_vhub_map_t *elem;
1473*13101SVenki.Rajagopalan@Sun.COM 
1474*13101SVenki.Rajagopalan@Sun.COM 	bkt = (mac[ETHERADDRL-1]) % EIB_TB_NBUCKETS;
1475*13101SVenki.Rajagopalan@Sun.COM 
1476*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&tbl->tb_lock);
1477*13101SVenki.Rajagopalan@Sun.COM 
1478*13101SVenki.Rajagopalan@Sun.COM 	/*
1479*13101SVenki.Rajagopalan@Sun.COM 	 * Note that for EoIB, the vhub table is maintained using only
1480*13101SVenki.Rajagopalan@Sun.COM 	 * vnic entry updates
1481*13101SVenki.Rajagopalan@Sun.COM 	 */
1482*13101SVenki.Rajagopalan@Sun.COM 	prev = NULL;
1483*13101SVenki.Rajagopalan@Sun.COM 	for (elem = tbl->tb_vnic_entry[bkt]; elem; elem = elem->mp_next) {
1484*13101SVenki.Rajagopalan@Sun.COM 		if (bcmp(elem->mp_mac, mac, ETHERADDRL) == 0)
1485*13101SVenki.Rajagopalan@Sun.COM 			break;
1486*13101SVenki.Rajagopalan@Sun.COM 		prev = elem;
1487*13101SVenki.Rajagopalan@Sun.COM 	}
1488*13101SVenki.Rajagopalan@Sun.COM 
1489*13101SVenki.Rajagopalan@Sun.COM 	if (prev && elem) {
1490*13101SVenki.Rajagopalan@Sun.COM 		prev->mp_next = elem->mp_next;
1491*13101SVenki.Rajagopalan@Sun.COM 		kmem_free(elem, sizeof (eib_vhub_map_t));
1492*13101SVenki.Rajagopalan@Sun.COM 	}
1493*13101SVenki.Rajagopalan@Sun.COM 
1494*13101SVenki.Rajagopalan@Sun.COM 	tbl->tb_tusn = tusn;
1495*13101SVenki.Rajagopalan@Sun.COM 	tbl->tb_eport_state = eport_state;
1496*13101SVenki.Rajagopalan@Sun.COM 
1497*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&tbl->tb_lock);
1498*13101SVenki.Rajagopalan@Sun.COM }
1499*13101SVenki.Rajagopalan@Sun.COM 
1500*13101SVenki.Rajagopalan@Sun.COM static eib_vhub_map_t *
eib_fip_get_vhub_map(void)1501*13101SVenki.Rajagopalan@Sun.COM eib_fip_get_vhub_map(void)
1502*13101SVenki.Rajagopalan@Sun.COM {
1503*13101SVenki.Rajagopalan@Sun.COM 	return (kmem_zalloc(sizeof (eib_vhub_map_t), KM_NOSLEEP));
1504*13101SVenki.Rajagopalan@Sun.COM }
1505