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