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