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/enx_impl.h>
33*13101SVenki.Rajagopalan@Sun.COM
34*13101SVenki.Rajagopalan@Sun.COM const char fip_vendor_mellanox[] = {
35*13101SVenki.Rajagopalan@Sun.COM 0x4d, 0x65, 0x6c, 0x6c, 0x61, 0x6e, 0x6f, 0x78
36*13101SVenki.Rajagopalan@Sun.COM };
37*13101SVenki.Rajagopalan@Sun.COM
38*13101SVenki.Rajagopalan@Sun.COM /*
39*13101SVenki.Rajagopalan@Sun.COM * HW/FW workaround
40*13101SVenki.Rajagopalan@Sun.COM *
41*13101SVenki.Rajagopalan@Sun.COM * Verification of descriptor list length in the received packets is
42*13101SVenki.Rajagopalan@Sun.COM * disabled, since experimentation shows that BX does not set the desc
43*13101SVenki.Rajagopalan@Sun.COM * list length correctly.
44*13101SVenki.Rajagopalan@Sun.COM */
45*13101SVenki.Rajagopalan@Sun.COM int enx_wa_no_desc_list_len = 1;
46*13101SVenki.Rajagopalan@Sun.COM
47*13101SVenki.Rajagopalan@Sun.COM /*
48*13101SVenki.Rajagopalan@Sun.COM * Static function declarations
49*13101SVenki.Rajagopalan@Sun.COM */
50*13101SVenki.Rajagopalan@Sun.COM static int eibnx_fip_make_solicit_pkt(eibnx_thr_info_t *, eibnx_wqe_t *);
51*13101SVenki.Rajagopalan@Sun.COM static int eibnx_fip_send_solicit_pkt(eibnx_thr_info_t *, eibnx_wqe_t *,
52*13101SVenki.Rajagopalan@Sun.COM eibnx_gw_addr_t *);
53*13101SVenki.Rajagopalan@Sun.COM static int eibnx_fip_parse_advt_pkt(uint8_t *, eibnx_gw_msg_t *);
54*13101SVenki.Rajagopalan@Sun.COM static void eibnx_rb_fip_make_solicit_pkt(eibnx_wqe_t *);
55*13101SVenki.Rajagopalan@Sun.COM
56*13101SVenki.Rajagopalan@Sun.COM /*
57*13101SVenki.Rajagopalan@Sun.COM * Prepare and send a solicit multicast packet to the All-EoIB-GWs-GID
58*13101SVenki.Rajagopalan@Sun.COM */
59*13101SVenki.Rajagopalan@Sun.COM int
eibnx_fip_solicit_mcast(eibnx_thr_info_t * info)60*13101SVenki.Rajagopalan@Sun.COM eibnx_fip_solicit_mcast(eibnx_thr_info_t *info)
61*13101SVenki.Rajagopalan@Sun.COM {
62*13101SVenki.Rajagopalan@Sun.COM eibnx_wqe_t *swqe;
63*13101SVenki.Rajagopalan@Sun.COM int ret;
64*13101SVenki.Rajagopalan@Sun.COM
65*13101SVenki.Rajagopalan@Sun.COM if ((swqe = eibnx_acquire_swqe(info, KM_SLEEP)) == NULL)
66*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_FAILURE);
67*13101SVenki.Rajagopalan@Sun.COM
68*13101SVenki.Rajagopalan@Sun.COM ret = eibnx_fip_make_solicit_pkt(info, swqe);
69*13101SVenki.Rajagopalan@Sun.COM if (ret != ENX_E_SUCCESS) {
70*13101SVenki.Rajagopalan@Sun.COM eibnx_release_swqe(swqe);
71*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_FAILURE);
72*13101SVenki.Rajagopalan@Sun.COM }
73*13101SVenki.Rajagopalan@Sun.COM
74*13101SVenki.Rajagopalan@Sun.COM ret = eibnx_fip_send_solicit_pkt(info, swqe, NULL);
75*13101SVenki.Rajagopalan@Sun.COM if (ret != ENX_E_SUCCESS) {
76*13101SVenki.Rajagopalan@Sun.COM eibnx_rb_fip_make_solicit_pkt(swqe);
77*13101SVenki.Rajagopalan@Sun.COM eibnx_release_swqe(swqe);
78*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_FAILURE);
79*13101SVenki.Rajagopalan@Sun.COM }
80*13101SVenki.Rajagopalan@Sun.COM
81*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_SUCCESS);
82*13101SVenki.Rajagopalan@Sun.COM }
83*13101SVenki.Rajagopalan@Sun.COM
84*13101SVenki.Rajagopalan@Sun.COM /*
85*13101SVenki.Rajagopalan@Sun.COM * Go through the list of already discovered gateways and send
86*13101SVenki.Rajagopalan@Sun.COM * a unicast solicitation to each gateway. This is required by
87*13101SVenki.Rajagopalan@Sun.COM * the EoIB specification ostensibly to receive updated
88*13101SVenki.Rajagopalan@Sun.COM * advertisements.
89*13101SVenki.Rajagopalan@Sun.COM */
90*13101SVenki.Rajagopalan@Sun.COM int
eibnx_fip_solicit_ucast(eibnx_thr_info_t * info,clock_t * solicit_period_ticks)91*13101SVenki.Rajagopalan@Sun.COM eibnx_fip_solicit_ucast(eibnx_thr_info_t *info, clock_t *solicit_period_ticks)
92*13101SVenki.Rajagopalan@Sun.COM {
93*13101SVenki.Rajagopalan@Sun.COM eibnx_gw_info_t *gw;
94*13101SVenki.Rajagopalan@Sun.COM eibnx_wqe_t *swqe;
95*13101SVenki.Rajagopalan@Sun.COM clock_t min_solicit_period_msec;
96*13101SVenki.Rajagopalan@Sun.COM int ret;
97*13101SVenki.Rajagopalan@Sun.COM
98*13101SVenki.Rajagopalan@Sun.COM /*
99*13101SVenki.Rajagopalan@Sun.COM * We want to read the gwlist and send a unicast to each
100*13101SVenki.Rajagopalan@Sun.COM * destination. Now, the only places where the gw list pointers
101*13101SVenki.Rajagopalan@Sun.COM * are updated are when we're adding a new gw item to the list
102*13101SVenki.Rajagopalan@Sun.COM * and when the list is being torn down and freed.
103*13101SVenki.Rajagopalan@Sun.COM *
104*13101SVenki.Rajagopalan@Sun.COM * Since new GWs are always inserted at the head of the list,
105*13101SVenki.Rajagopalan@Sun.COM * we're guaranteed that any tail subchain of the list will
106*13101SVenki.Rajagopalan@Sun.COM * not change by the addition of a new gw item coming into
107*13101SVenki.Rajagopalan@Sun.COM * the list.
108*13101SVenki.Rajagopalan@Sun.COM *
109*13101SVenki.Rajagopalan@Sun.COM * Also, since the gw list is torn down only by the port-monitor
110*13101SVenki.Rajagopalan@Sun.COM * thread (i.e. ourselves), we are also protected against the
111*13101SVenki.Rajagopalan@Sun.COM * list itself going away while we're here.
112*13101SVenki.Rajagopalan@Sun.COM *
113*13101SVenki.Rajagopalan@Sun.COM * Given these two constraints, we can safely read the list
114*13101SVenki.Rajagopalan@Sun.COM * of gateways without the gw list lock in this routine.
115*13101SVenki.Rajagopalan@Sun.COM */
116*13101SVenki.Rajagopalan@Sun.COM min_solicit_period_msec = drv_hztousec(*solicit_period_ticks) / 1000;
117*13101SVenki.Rajagopalan@Sun.COM for (gw = info->ti_gw; gw; gw = gw->gw_next) {
118*13101SVenki.Rajagopalan@Sun.COM
119*13101SVenki.Rajagopalan@Sun.COM if (eibnx_is_gw_dead(gw))
120*13101SVenki.Rajagopalan@Sun.COM continue;
121*13101SVenki.Rajagopalan@Sun.COM
122*13101SVenki.Rajagopalan@Sun.COM swqe = gw->gw_swqe;
123*13101SVenki.Rajagopalan@Sun.COM ASSERT(swqe != NULL);
124*13101SVenki.Rajagopalan@Sun.COM
125*13101SVenki.Rajagopalan@Sun.COM mutex_enter(&swqe->qe_lock);
126*13101SVenki.Rajagopalan@Sun.COM if (swqe->qe_type != ENX_QETYP_SWQE) {
127*13101SVenki.Rajagopalan@Sun.COM ENX_DPRINTF_DEBUG("eibnx_fip_solicit_ucast: "
128*13101SVenki.Rajagopalan@Sun.COM "gw wqe type (0x%lx) indicates this is not an "
129*13101SVenki.Rajagopalan@Sun.COM "swqe!, cannot send solicitation to gw",
130*13101SVenki.Rajagopalan@Sun.COM swqe->qe_type);
131*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&swqe->qe_lock);
132*13101SVenki.Rajagopalan@Sun.COM continue;
133*13101SVenki.Rajagopalan@Sun.COM } else if ((swqe->qe_flags & ENX_QEFL_INUSE) !=
134*13101SVenki.Rajagopalan@Sun.COM ENX_QEFL_INUSE) {
135*13101SVenki.Rajagopalan@Sun.COM ENX_DPRINTF_DEBUG("eibnx_fip_solicit_ucast: "
136*13101SVenki.Rajagopalan@Sun.COM "gw swqe flags (0x%lx) indicate swqe is free!, "
137*13101SVenki.Rajagopalan@Sun.COM "cannot send solicitation to gw", swqe->qe_flags);
138*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&swqe->qe_lock);
139*13101SVenki.Rajagopalan@Sun.COM continue;
140*13101SVenki.Rajagopalan@Sun.COM } else if ((swqe->qe_flags & ENX_QEFL_POSTED) ==
141*13101SVenki.Rajagopalan@Sun.COM ENX_QEFL_POSTED) {
142*13101SVenki.Rajagopalan@Sun.COM ENX_DPRINTF_DEBUG("eibnx_fip_solicit_ucast: gw swqe "
143*13101SVenki.Rajagopalan@Sun.COM "flags (0x%lx) indicate swqe is still with HCA!, "
144*13101SVenki.Rajagopalan@Sun.COM "cannot send solicitation to gw", swqe->qe_flags);
145*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&swqe->qe_lock);
146*13101SVenki.Rajagopalan@Sun.COM continue;
147*13101SVenki.Rajagopalan@Sun.COM }
148*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&swqe->qe_lock);
149*13101SVenki.Rajagopalan@Sun.COM
150*13101SVenki.Rajagopalan@Sun.COM /*
151*13101SVenki.Rajagopalan@Sun.COM * EoIB spec requires that each host send solicitation
152*13101SVenki.Rajagopalan@Sun.COM * to discovered gateways atleast every 4 * GW_ADV_PERIOD.
153*13101SVenki.Rajagopalan@Sun.COM * We make sure we send a solicitation to all gateways
154*13101SVenki.Rajagopalan@Sun.COM * every 4 * GW_ADV_PERIOD of the smallest value of
155*13101SVenki.Rajagopalan@Sun.COM * GW_ADV_PERIOD that we have in our gw list.
156*13101SVenki.Rajagopalan@Sun.COM */
157*13101SVenki.Rajagopalan@Sun.COM if ((gw->gw_adv_period * 4) < min_solicit_period_msec)
158*13101SVenki.Rajagopalan@Sun.COM min_solicit_period_msec = gw->gw_adv_period * 4;
159*13101SVenki.Rajagopalan@Sun.COM
160*13101SVenki.Rajagopalan@Sun.COM ret = eibnx_fip_make_solicit_pkt(info, swqe);
161*13101SVenki.Rajagopalan@Sun.COM if (ret != ENX_E_SUCCESS)
162*13101SVenki.Rajagopalan@Sun.COM continue;
163*13101SVenki.Rajagopalan@Sun.COM
164*13101SVenki.Rajagopalan@Sun.COM ret = eibnx_fip_send_solicit_pkt(info, swqe, &gw->gw_addr);
165*13101SVenki.Rajagopalan@Sun.COM if (ret != ENX_E_SUCCESS)
166*13101SVenki.Rajagopalan@Sun.COM eibnx_rb_fip_make_solicit_pkt(swqe);
167*13101SVenki.Rajagopalan@Sun.COM }
168*13101SVenki.Rajagopalan@Sun.COM
169*13101SVenki.Rajagopalan@Sun.COM *solicit_period_ticks = drv_usectohz(min_solicit_period_msec * 1000);
170*13101SVenki.Rajagopalan@Sun.COM
171*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_SUCCESS);
172*13101SVenki.Rajagopalan@Sun.COM }
173*13101SVenki.Rajagopalan@Sun.COM
174*13101SVenki.Rajagopalan@Sun.COM /*
175*13101SVenki.Rajagopalan@Sun.COM * Given a send wqe and an eibnx_thr_info_t pointer, fill in the
176*13101SVenki.Rajagopalan@Sun.COM * send buffer with a solicit packet in the network byte order.
177*13101SVenki.Rajagopalan@Sun.COM */
178*13101SVenki.Rajagopalan@Sun.COM static int
eibnx_fip_make_solicit_pkt(eibnx_thr_info_t * info,eibnx_wqe_t * swqe)179*13101SVenki.Rajagopalan@Sun.COM eibnx_fip_make_solicit_pkt(eibnx_thr_info_t *info, eibnx_wqe_t *swqe)
180*13101SVenki.Rajagopalan@Sun.COM {
181*13101SVenki.Rajagopalan@Sun.COM fip_solicit_t *solicit;
182*13101SVenki.Rajagopalan@Sun.COM fip_proto_t *proto;
183*13101SVenki.Rajagopalan@Sun.COM fip_basic_hdr_t *hdr;
184*13101SVenki.Rajagopalan@Sun.COM fip_desc_iba_t *iba;
185*13101SVenki.Rajagopalan@Sun.COM ib_gid_t port_gid;
186*13101SVenki.Rajagopalan@Sun.COM ib_guid_t port_guid;
187*13101SVenki.Rajagopalan@Sun.COM
188*13101SVenki.Rajagopalan@Sun.COM uint8_t *pkt = (uint8_t *)(uintptr_t)(swqe->qe_sgl.ds_va);
189*13101SVenki.Rajagopalan@Sun.COM uint_t pktsz = swqe->qe_sgl.ds_len;
190*13101SVenki.Rajagopalan@Sun.COM uint_t solicit_sz = sizeof (fip_solicit_t);
191*13101SVenki.Rajagopalan@Sun.COM
192*13101SVenki.Rajagopalan@Sun.COM if (pktsz < solicit_sz) {
193*13101SVenki.Rajagopalan@Sun.COM ENX_DPRINTF_ERR("swqe bufsize too small for pkt, "
194*13101SVenki.Rajagopalan@Sun.COM "pktsz=%x < expsz=%x", pktsz, solicit_sz);
195*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_FAILURE);
196*13101SVenki.Rajagopalan@Sun.COM }
197*13101SVenki.Rajagopalan@Sun.COM
198*13101SVenki.Rajagopalan@Sun.COM /*
199*13101SVenki.Rajagopalan@Sun.COM * Lint complains that there may be an alignment issue here,
200*13101SVenki.Rajagopalan@Sun.COM * but we know that the "pkt" is atleast double-word aligned,
201*13101SVenki.Rajagopalan@Sun.COM * so it's ok.
202*13101SVenki.Rajagopalan@Sun.COM */
203*13101SVenki.Rajagopalan@Sun.COM solicit = (fip_solicit_t *)pkt;
204*13101SVenki.Rajagopalan@Sun.COM
205*13101SVenki.Rajagopalan@Sun.COM /*
206*13101SVenki.Rajagopalan@Sun.COM * Fill in the FIP protocol version
207*13101SVenki.Rajagopalan@Sun.COM */
208*13101SVenki.Rajagopalan@Sun.COM proto = &solicit->sl_proto_version;
209*13101SVenki.Rajagopalan@Sun.COM proto->pr_version = FIP_PROTO_VERSION;
210*13101SVenki.Rajagopalan@Sun.COM
211*13101SVenki.Rajagopalan@Sun.COM /*
212*13101SVenki.Rajagopalan@Sun.COM * Fill in the basic header
213*13101SVenki.Rajagopalan@Sun.COM */
214*13101SVenki.Rajagopalan@Sun.COM hdr = &solicit->sl_fip_hdr;
215*13101SVenki.Rajagopalan@Sun.COM hdr->hd_opcode = htons(FIP_OPCODE_EOIB);
216*13101SVenki.Rajagopalan@Sun.COM hdr->hd_subcode = FIP_SUBCODE_H_SOLICIT;
217*13101SVenki.Rajagopalan@Sun.COM hdr->hd_desc_list_len = htons((solicit_sz >> 2) - 2);
218*13101SVenki.Rajagopalan@Sun.COM hdr->hd_flags = 0;
219*13101SVenki.Rajagopalan@Sun.COM hdr->hd_type = FIP_DESC_TYPE_VENDOR_ID;
220*13101SVenki.Rajagopalan@Sun.COM hdr->hd_len = FIP_DESC_LEN_VENDOR_ID;
221*13101SVenki.Rajagopalan@Sun.COM bcopy(fip_vendor_mellanox, hdr->hd_vendor_id, FIP_VENDOR_LEN);
222*13101SVenki.Rajagopalan@Sun.COM
223*13101SVenki.Rajagopalan@Sun.COM /*
224*13101SVenki.Rajagopalan@Sun.COM * Fill in the Infiniband Address descriptor
225*13101SVenki.Rajagopalan@Sun.COM */
226*13101SVenki.Rajagopalan@Sun.COM iba = &solicit->sl_iba;
227*13101SVenki.Rajagopalan@Sun.COM iba->ia_type = FIP_DESC_TYPE_IBA;
228*13101SVenki.Rajagopalan@Sun.COM iba->ia_len = FIP_DESC_LEN_IBA;
229*13101SVenki.Rajagopalan@Sun.COM bcopy(fip_vendor_mellanox, iba->ia_vendor_id, FIP_VENDOR_LEN);
230*13101SVenki.Rajagopalan@Sun.COM iba->ia_qpn = htonl(info->ti_qpn);
231*13101SVenki.Rajagopalan@Sun.COM iba->ia_sl_portid = 0;
232*13101SVenki.Rajagopalan@Sun.COM iba->ia_lid = htons(info->ti_pi->p_base_lid);
233*13101SVenki.Rajagopalan@Sun.COM port_gid = info->ti_pi->p_sgid_tbl[0];
234*13101SVenki.Rajagopalan@Sun.COM port_guid = htonll(port_gid.gid_guid);
235*13101SVenki.Rajagopalan@Sun.COM bcopy(&port_guid, iba->ia_guid, FIP_GUID_LEN);
236*13101SVenki.Rajagopalan@Sun.COM
237*13101SVenki.Rajagopalan@Sun.COM /*
238*13101SVenki.Rajagopalan@Sun.COM * Adjust the ds_len in the sgl to indicate the size of the
239*13101SVenki.Rajagopalan@Sun.COM * solicit pkt before returning
240*13101SVenki.Rajagopalan@Sun.COM */
241*13101SVenki.Rajagopalan@Sun.COM swqe->qe_sgl.ds_len = solicit_sz;
242*13101SVenki.Rajagopalan@Sun.COM
243*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_SUCCESS);
244*13101SVenki.Rajagopalan@Sun.COM }
245*13101SVenki.Rajagopalan@Sun.COM
246*13101SVenki.Rajagopalan@Sun.COM static int
eibnx_setup_ud_dest(eibnx_thr_info_t * info,eibnx_wqe_t * swqe,eibnx_gw_addr_t * gw_addr)247*13101SVenki.Rajagopalan@Sun.COM eibnx_setup_ud_dest(eibnx_thr_info_t *info, eibnx_wqe_t *swqe,
248*13101SVenki.Rajagopalan@Sun.COM eibnx_gw_addr_t *gw_addr)
249*13101SVenki.Rajagopalan@Sun.COM {
250*13101SVenki.Rajagopalan@Sun.COM eibnx_t *ss = enx_global_ss;
251*13101SVenki.Rajagopalan@Sun.COM ibt_path_attr_t attr;
252*13101SVenki.Rajagopalan@Sun.COM ibt_path_info_t path;
253*13101SVenki.Rajagopalan@Sun.COM ibt_status_t ret;
254*13101SVenki.Rajagopalan@Sun.COM
255*13101SVenki.Rajagopalan@Sun.COM /*
256*13101SVenki.Rajagopalan@Sun.COM * If this a multicast send, we'll have the gateway address NULL,
257*13101SVenki.Rajagopalan@Sun.COM * and we'll need to modify the UD destination to send to the
258*13101SVenki.Rajagopalan@Sun.COM * solicit mcg.
259*13101SVenki.Rajagopalan@Sun.COM */
260*13101SVenki.Rajagopalan@Sun.COM if (gw_addr == NULL) {
261*13101SVenki.Rajagopalan@Sun.COM ret = ibt_modify_ud_dest(swqe->qe_wr.send.wr.ud.udwr_dest,
262*13101SVenki.Rajagopalan@Sun.COM info->ti_solicit_mcg->mc_qkey, IB_MC_QPN,
263*13101SVenki.Rajagopalan@Sun.COM &info->ti_solicit_mcg->mc_adds_vect);
264*13101SVenki.Rajagopalan@Sun.COM if (ret != IBT_SUCCESS) {
265*13101SVenki.Rajagopalan@Sun.COM ENX_DPRINTF_ERR("ibt_modify_ud_dest() failed with "
266*13101SVenki.Rajagopalan@Sun.COM "ret=%d, qkey=%x, qpn=%x", ret,
267*13101SVenki.Rajagopalan@Sun.COM info->ti_solicit_mcg->mc_qkey, IB_MC_QPN);
268*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_FAILURE);
269*13101SVenki.Rajagopalan@Sun.COM }
270*13101SVenki.Rajagopalan@Sun.COM
271*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_SUCCESS);
272*13101SVenki.Rajagopalan@Sun.COM }
273*13101SVenki.Rajagopalan@Sun.COM
274*13101SVenki.Rajagopalan@Sun.COM /*
275*13101SVenki.Rajagopalan@Sun.COM * If this is a unicast send, but we already have the gw address
276*13101SVenki.Rajagopalan@Sun.COM * vector, the ud destination handle has already been set up for
277*13101SVenki.Rajagopalan@Sun.COM * this gateway, so we can return.
278*13101SVenki.Rajagopalan@Sun.COM */
279*13101SVenki.Rajagopalan@Sun.COM if (gw_addr->ga_vect)
280*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_SUCCESS);
281*13101SVenki.Rajagopalan@Sun.COM
282*13101SVenki.Rajagopalan@Sun.COM /*
283*13101SVenki.Rajagopalan@Sun.COM * Get the reversible path information for this gateway
284*13101SVenki.Rajagopalan@Sun.COM */
285*13101SVenki.Rajagopalan@Sun.COM bzero(&attr, sizeof (ibt_path_info_t));
286*13101SVenki.Rajagopalan@Sun.COM attr.pa_dgids = &gw_addr->ga_gid;
287*13101SVenki.Rajagopalan@Sun.COM attr.pa_num_dgids = 1;
288*13101SVenki.Rajagopalan@Sun.COM attr.pa_sgid = info->ti_pi->p_sgid_tbl[0];
289*13101SVenki.Rajagopalan@Sun.COM attr.pa_pkey = gw_addr->ga_pkey;
290*13101SVenki.Rajagopalan@Sun.COM
291*13101SVenki.Rajagopalan@Sun.COM bzero(&path, sizeof (ibt_path_info_t));
292*13101SVenki.Rajagopalan@Sun.COM ret = ibt_get_paths(ss->nx_ibt_hdl, IBT_PATH_PKEY,
293*13101SVenki.Rajagopalan@Sun.COM &attr, 1, &path, NULL);
294*13101SVenki.Rajagopalan@Sun.COM if ((ret != IBT_SUCCESS) || (path.pi_hca_guid == 0)) {
295*13101SVenki.Rajagopalan@Sun.COM ENX_DPRINTF_ERR("ibt_get_paths() failed with "
296*13101SVenki.Rajagopalan@Sun.COM "ret=%d, gid_prefix=%llx, gid_guid=%llx", ret,
297*13101SVenki.Rajagopalan@Sun.COM gw_addr->ga_gid.gid_prefix, gw_addr->ga_gid.gid_guid);
298*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_FAILURE);
299*13101SVenki.Rajagopalan@Sun.COM }
300*13101SVenki.Rajagopalan@Sun.COM
301*13101SVenki.Rajagopalan@Sun.COM /*
302*13101SVenki.Rajagopalan@Sun.COM * And save the address vector
303*13101SVenki.Rajagopalan@Sun.COM */
304*13101SVenki.Rajagopalan@Sun.COM gw_addr->ga_vect = kmem_zalloc(sizeof (ibt_adds_vect_t), KM_SLEEP);
305*13101SVenki.Rajagopalan@Sun.COM bcopy(&path.pi_prim_cep_path.cep_adds_vect, gw_addr->ga_vect,
306*13101SVenki.Rajagopalan@Sun.COM sizeof (ibt_adds_vect_t));
307*13101SVenki.Rajagopalan@Sun.COM
308*13101SVenki.Rajagopalan@Sun.COM /*
309*13101SVenki.Rajagopalan@Sun.COM * Modify the UD destination handle on this swqe entry to address
310*13101SVenki.Rajagopalan@Sun.COM * this gateway
311*13101SVenki.Rajagopalan@Sun.COM */
312*13101SVenki.Rajagopalan@Sun.COM ret = ibt_modify_ud_dest(swqe->qe_wr.send.wr.ud.udwr_dest,
313*13101SVenki.Rajagopalan@Sun.COM gw_addr->ga_qkey, gw_addr->ga_qpn, gw_addr->ga_vect);
314*13101SVenki.Rajagopalan@Sun.COM if (ret != IBT_SUCCESS) {
315*13101SVenki.Rajagopalan@Sun.COM ENX_DPRINTF_ERR("ibt_modify_ud_dest() failed with "
316*13101SVenki.Rajagopalan@Sun.COM "ret=%d, qkey=%x, qpn=%x", ret, gw_addr->ga_qkey,
317*13101SVenki.Rajagopalan@Sun.COM gw_addr->ga_qpn);
318*13101SVenki.Rajagopalan@Sun.COM kmem_free(gw_addr->ga_vect, sizeof (ibt_adds_vect_t));
319*13101SVenki.Rajagopalan@Sun.COM gw_addr->ga_vect = NULL;
320*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_FAILURE);
321*13101SVenki.Rajagopalan@Sun.COM }
322*13101SVenki.Rajagopalan@Sun.COM
323*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_SUCCESS);
324*13101SVenki.Rajagopalan@Sun.COM }
325*13101SVenki.Rajagopalan@Sun.COM
326*13101SVenki.Rajagopalan@Sun.COM /*
327*13101SVenki.Rajagopalan@Sun.COM * Send a solicit packet to the appropriate destination: if the
328*13101SVenki.Rajagopalan@Sun.COM * destination gw addr is specified, send a unicast message to it;
329*13101SVenki.Rajagopalan@Sun.COM * if not, send a multicast using the solicit mcg address.
330*13101SVenki.Rajagopalan@Sun.COM */
331*13101SVenki.Rajagopalan@Sun.COM static int
eibnx_fip_send_solicit_pkt(eibnx_thr_info_t * info,eibnx_wqe_t * swqe,eibnx_gw_addr_t * gw_addr)332*13101SVenki.Rajagopalan@Sun.COM eibnx_fip_send_solicit_pkt(eibnx_thr_info_t *info, eibnx_wqe_t *swqe,
333*13101SVenki.Rajagopalan@Sun.COM eibnx_gw_addr_t *gw_addr)
334*13101SVenki.Rajagopalan@Sun.COM {
335*13101SVenki.Rajagopalan@Sun.COM ibt_status_t ret;
336*13101SVenki.Rajagopalan@Sun.COM
337*13101SVenki.Rajagopalan@Sun.COM if (eibnx_setup_ud_dest(info, swqe, gw_addr) != ENX_E_SUCCESS)
338*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_FAILURE);
339*13101SVenki.Rajagopalan@Sun.COM
340*13101SVenki.Rajagopalan@Sun.COM mutex_enter(&swqe->qe_lock);
341*13101SVenki.Rajagopalan@Sun.COM
342*13101SVenki.Rajagopalan@Sun.COM /*
343*13101SVenki.Rajagopalan@Sun.COM * Note that if the post send fails, we don't really need to undo
344*13101SVenki.Rajagopalan@Sun.COM * anything we did in setting up the ud destination; we can always
345*13101SVenki.Rajagopalan@Sun.COM * use it for the next time.
346*13101SVenki.Rajagopalan@Sun.COM */
347*13101SVenki.Rajagopalan@Sun.COM ret = ibt_post_send(info->ti_chan, &(swqe->qe_wr.send), 1, NULL);
348*13101SVenki.Rajagopalan@Sun.COM if (ret != IBT_SUCCESS) {
349*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&swqe->qe_lock);
350*13101SVenki.Rajagopalan@Sun.COM ENX_DPRINTF_ERR("ibt_post_send() failed for solicit, "
351*13101SVenki.Rajagopalan@Sun.COM "ret=%d", ret);
352*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_FAILURE);
353*13101SVenki.Rajagopalan@Sun.COM }
354*13101SVenki.Rajagopalan@Sun.COM
355*13101SVenki.Rajagopalan@Sun.COM /*
356*13101SVenki.Rajagopalan@Sun.COM * Set the 'posted' flag for the send wqe. If this is an unicast
357*13101SVenki.Rajagopalan@Sun.COM * send, the wqe is attached to a specific gw entry and we should
358*13101SVenki.Rajagopalan@Sun.COM * not release the wqe back to the pool on the send completion.
359*13101SVenki.Rajagopalan@Sun.COM */
360*13101SVenki.Rajagopalan@Sun.COM swqe->qe_flags |= ENX_QEFL_POSTED;
361*13101SVenki.Rajagopalan@Sun.COM if (gw_addr == NULL) {
362*13101SVenki.Rajagopalan@Sun.COM swqe->qe_flags |= ENX_QEFL_RELONCOMP;
363*13101SVenki.Rajagopalan@Sun.COM info->ti_mcast_done = 1;
364*13101SVenki.Rajagopalan@Sun.COM }
365*13101SVenki.Rajagopalan@Sun.COM
366*13101SVenki.Rajagopalan@Sun.COM mutex_exit(&swqe->qe_lock);
367*13101SVenki.Rajagopalan@Sun.COM
368*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_SUCCESS);
369*13101SVenki.Rajagopalan@Sun.COM }
370*13101SVenki.Rajagopalan@Sun.COM
371*13101SVenki.Rajagopalan@Sun.COM /*
372*13101SVenki.Rajagopalan@Sun.COM * Parse a received packet from the gateway into the
373*13101SVenki.Rajagopalan@Sun.COM * eibnx_gw_msg_t argument. Note that at this point, this
374*13101SVenki.Rajagopalan@Sun.COM * driver only expects to receive advertisements from the
375*13101SVenki.Rajagopalan@Sun.COM * GW, nothing else.
376*13101SVenki.Rajagopalan@Sun.COM */
377*13101SVenki.Rajagopalan@Sun.COM int
eibnx_fip_parse_pkt(uint8_t * pkt,eibnx_gw_msg_t * msg)378*13101SVenki.Rajagopalan@Sun.COM eibnx_fip_parse_pkt(uint8_t *pkt, eibnx_gw_msg_t *msg)
379*13101SVenki.Rajagopalan@Sun.COM {
380*13101SVenki.Rajagopalan@Sun.COM fip_basic_hdr_t *hdr;
381*13101SVenki.Rajagopalan@Sun.COM uint16_t opcode;
382*13101SVenki.Rajagopalan@Sun.COM uint8_t subcode;
383*13101SVenki.Rajagopalan@Sun.COM int ret = ENX_E_FAILURE;
384*13101SVenki.Rajagopalan@Sun.COM
385*13101SVenki.Rajagopalan@Sun.COM /*
386*13101SVenki.Rajagopalan@Sun.COM * Lint complains about potential alignment problem here,
387*13101SVenki.Rajagopalan@Sun.COM * but the fip_* structures are all packed and each of them
388*13101SVenki.Rajagopalan@Sun.COM * is aligned on a word boundary, so we're ok.
389*13101SVenki.Rajagopalan@Sun.COM */
390*13101SVenki.Rajagopalan@Sun.COM hdr = (fip_basic_hdr_t *)(pkt + sizeof (fip_proto_t));
391*13101SVenki.Rajagopalan@Sun.COM
392*13101SVenki.Rajagopalan@Sun.COM /*
393*13101SVenki.Rajagopalan@Sun.COM * Verify that the opcode is EoIB
394*13101SVenki.Rajagopalan@Sun.COM */
395*13101SVenki.Rajagopalan@Sun.COM if ((opcode = ntohs(hdr->hd_opcode)) != FIP_OPCODE_EOIB) {
396*13101SVenki.Rajagopalan@Sun.COM ENX_DPRINTF_WARN("unsupported opcode (%x) found in "
397*13101SVenki.Rajagopalan@Sun.COM "gw advertisement, ignoring", opcode);
398*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_FAILURE);
399*13101SVenki.Rajagopalan@Sun.COM }
400*13101SVenki.Rajagopalan@Sun.COM
401*13101SVenki.Rajagopalan@Sun.COM /*
402*13101SVenki.Rajagopalan@Sun.COM * We only handle GW advertisements in the eibnx driver code. However,
403*13101SVenki.Rajagopalan@Sun.COM * the BridgeX gateway software currently sends login acknowledgements
404*13101SVenki.Rajagopalan@Sun.COM * to the one who did the solicitation instead of the one who actually
405*13101SVenki.Rajagopalan@Sun.COM * made the login request, so we need to do something about this as
406*13101SVenki.Rajagopalan@Sun.COM * well.
407*13101SVenki.Rajagopalan@Sun.COM */
408*13101SVenki.Rajagopalan@Sun.COM subcode = hdr->hd_subcode;
409*13101SVenki.Rajagopalan@Sun.COM switch (subcode) {
410*13101SVenki.Rajagopalan@Sun.COM case FIP_SUBCODE_G_ADVERTISE:
411*13101SVenki.Rajagopalan@Sun.COM ret = eibnx_fip_parse_advt_pkt(pkt, msg);
412*13101SVenki.Rajagopalan@Sun.COM break;
413*13101SVenki.Rajagopalan@Sun.COM
414*13101SVenki.Rajagopalan@Sun.COM case FIP_SUBCODE_G_VNIC_LOGIN_ACK:
415*13101SVenki.Rajagopalan@Sun.COM msg->gm_type = FIP_VNIC_LOGIN_ACK;
416*13101SVenki.Rajagopalan@Sun.COM ret = ENX_E_SUCCESS;
417*13101SVenki.Rajagopalan@Sun.COM break;
418*13101SVenki.Rajagopalan@Sun.COM
419*13101SVenki.Rajagopalan@Sun.COM default:
420*13101SVenki.Rajagopalan@Sun.COM ENX_DPRINTF_WARN("unsupported subcode (%x) found in "
421*13101SVenki.Rajagopalan@Sun.COM "gw advertisement, ignoring", subcode);
422*13101SVenki.Rajagopalan@Sun.COM ret = ENX_E_FAILURE;
423*13101SVenki.Rajagopalan@Sun.COM break;
424*13101SVenki.Rajagopalan@Sun.COM }
425*13101SVenki.Rajagopalan@Sun.COM
426*13101SVenki.Rajagopalan@Sun.COM return (ret);
427*13101SVenki.Rajagopalan@Sun.COM }
428*13101SVenki.Rajagopalan@Sun.COM
429*13101SVenki.Rajagopalan@Sun.COM /*
430*13101SVenki.Rajagopalan@Sun.COM * Parse and validate a packet known to be an advertisement from
431*13101SVenki.Rajagopalan@Sun.COM * the GW.
432*13101SVenki.Rajagopalan@Sun.COM */
433*13101SVenki.Rajagopalan@Sun.COM static int
eibnx_fip_parse_advt_pkt(uint8_t * pkt,eibnx_gw_msg_t * msg)434*13101SVenki.Rajagopalan@Sun.COM eibnx_fip_parse_advt_pkt(uint8_t *pkt, eibnx_gw_msg_t *msg)
435*13101SVenki.Rajagopalan@Sun.COM {
436*13101SVenki.Rajagopalan@Sun.COM fip_advertise_t *advertise;
437*13101SVenki.Rajagopalan@Sun.COM fip_basic_hdr_t *hdr;
438*13101SVenki.Rajagopalan@Sun.COM fip_desc_iba_t *desc_iba;
439*13101SVenki.Rajagopalan@Sun.COM fip_desc_gwinfo_t *desc_gwinfo;
440*13101SVenki.Rajagopalan@Sun.COM fip_desc_gwid_t *desc_gwid;
441*13101SVenki.Rajagopalan@Sun.COM fip_desc_keepalive_t *desc_ka;
442*13101SVenki.Rajagopalan@Sun.COM eibnx_gw_info_t *gwi;
443*13101SVenki.Rajagopalan@Sun.COM ib_guid_t guid;
444*13101SVenki.Rajagopalan@Sun.COM uint16_t rss_qpn_num_net_vnics;
445*13101SVenki.Rajagopalan@Sun.COM uint16_t sl_portid;
446*13101SVenki.Rajagopalan@Sun.COM uint16_t flags;
447*13101SVenki.Rajagopalan@Sun.COM
448*13101SVenki.Rajagopalan@Sun.COM /*
449*13101SVenki.Rajagopalan@Sun.COM * Lint complains about potential alignment problem here,
450*13101SVenki.Rajagopalan@Sun.COM * but we know that "pkt" is always atleast double-word
451*13101SVenki.Rajagopalan@Sun.COM * aligned when it's passed to us, so we're ok.
452*13101SVenki.Rajagopalan@Sun.COM */
453*13101SVenki.Rajagopalan@Sun.COM advertise = (fip_advertise_t *)pkt;
454*13101SVenki.Rajagopalan@Sun.COM
455*13101SVenki.Rajagopalan@Sun.COM /*
456*13101SVenki.Rajagopalan@Sun.COM * Verify if the descriptor list length in the received
457*13101SVenki.Rajagopalan@Sun.COM * packet is valid. Currently disabled.
458*13101SVenki.Rajagopalan@Sun.COM *
459*13101SVenki.Rajagopalan@Sun.COM * Experimentation shows that BX doesn't set the desc list
460*13101SVenki.Rajagopalan@Sun.COM * length correctly, so we also simply ignore it and move
461*13101SVenki.Rajagopalan@Sun.COM * on. If and when BX fixes this problem, we'll need to
462*13101SVenki.Rajagopalan@Sun.COM * enable the warning+failure below.
463*13101SVenki.Rajagopalan@Sun.COM */
464*13101SVenki.Rajagopalan@Sun.COM hdr = &(advertise->ad_fip_header);
465*13101SVenki.Rajagopalan@Sun.COM if (!enx_wa_no_desc_list_len) {
466*13101SVenki.Rajagopalan@Sun.COM uint_t pkt_data_sz;
467*13101SVenki.Rajagopalan@Sun.COM
468*13101SVenki.Rajagopalan@Sun.COM pkt_data_sz = (ntohs(hdr->hd_desc_list_len) + 2) << 2;
469*13101SVenki.Rajagopalan@Sun.COM if (pkt_data_sz < sizeof (fip_advertise_t)) {
470*13101SVenki.Rajagopalan@Sun.COM ENX_DPRINTF_WARN("advertisement from gw too small; "
471*13101SVenki.Rajagopalan@Sun.COM "expected %x, got %x", sizeof (fip_advertise_t),
472*13101SVenki.Rajagopalan@Sun.COM pkt_data_sz);
473*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_FAILURE);
474*13101SVenki.Rajagopalan@Sun.COM }
475*13101SVenki.Rajagopalan@Sun.COM }
476*13101SVenki.Rajagopalan@Sun.COM
477*13101SVenki.Rajagopalan@Sun.COM /*
478*13101SVenki.Rajagopalan@Sun.COM * Validate all the header and descriptor types and lengths
479*13101SVenki.Rajagopalan@Sun.COM */
480*13101SVenki.Rajagopalan@Sun.COM
481*13101SVenki.Rajagopalan@Sun.COM if (hdr->hd_type != FIP_DESC_TYPE_VENDOR_ID ||
482*13101SVenki.Rajagopalan@Sun.COM hdr->hd_len != FIP_DESC_LEN_VENDOR_ID) {
483*13101SVenki.Rajagopalan@Sun.COM ENX_DPRINTF_WARN("invalid type/len in fip basic header; "
484*13101SVenki.Rajagopalan@Sun.COM "expected (%x,%x), got (%x,%x)", FIP_DESC_TYPE_VENDOR_ID,
485*13101SVenki.Rajagopalan@Sun.COM FIP_DESC_LEN_VENDOR_ID, hdr->hd_type, hdr->hd_len);
486*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_FAILURE);
487*13101SVenki.Rajagopalan@Sun.COM }
488*13101SVenki.Rajagopalan@Sun.COM
489*13101SVenki.Rajagopalan@Sun.COM desc_iba = &(advertise->ad_iba);
490*13101SVenki.Rajagopalan@Sun.COM if (desc_iba->ia_type != FIP_DESC_TYPE_IBA ||
491*13101SVenki.Rajagopalan@Sun.COM desc_iba->ia_len != FIP_DESC_LEN_IBA) {
492*13101SVenki.Rajagopalan@Sun.COM ENX_DPRINTF_WARN("invalid type/len in fip iba desc; "
493*13101SVenki.Rajagopalan@Sun.COM "expected (%x,%x), got (%x,%x)", FIP_DESC_TYPE_IBA,
494*13101SVenki.Rajagopalan@Sun.COM FIP_DESC_LEN_IBA, desc_iba->ia_type, desc_iba->ia_len);
495*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_FAILURE);
496*13101SVenki.Rajagopalan@Sun.COM }
497*13101SVenki.Rajagopalan@Sun.COM
498*13101SVenki.Rajagopalan@Sun.COM desc_gwinfo = &(advertise->ad_gwinfo);
499*13101SVenki.Rajagopalan@Sun.COM if (desc_gwinfo->gi_type != FIP_DESC_TYPE_EOIB_GW_INFO ||
500*13101SVenki.Rajagopalan@Sun.COM desc_gwinfo->gi_len != FIP_DESC_LEN_EOIB_GW_INFO) {
501*13101SVenki.Rajagopalan@Sun.COM ENX_DPRINTF_WARN("invalid type/len in fip gwinfo desc; "
502*13101SVenki.Rajagopalan@Sun.COM "expected (%x,%x), got (%x,%x)",
503*13101SVenki.Rajagopalan@Sun.COM FIP_DESC_TYPE_EOIB_GW_INFO, FIP_DESC_LEN_EOIB_GW_INFO,
504*13101SVenki.Rajagopalan@Sun.COM desc_gwinfo->gi_type, desc_gwinfo->gi_len);
505*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_FAILURE);
506*13101SVenki.Rajagopalan@Sun.COM }
507*13101SVenki.Rajagopalan@Sun.COM
508*13101SVenki.Rajagopalan@Sun.COM desc_gwid = &(advertise->ad_gwid);
509*13101SVenki.Rajagopalan@Sun.COM if (desc_gwid->id_type != FIP_DESC_TYPE_GW_ID ||
510*13101SVenki.Rajagopalan@Sun.COM desc_gwid->id_len != FIP_DESC_LEN_GW_ID) {
511*13101SVenki.Rajagopalan@Sun.COM ENX_DPRINTF_WARN("invalid type/len in fip gwid desc; "
512*13101SVenki.Rajagopalan@Sun.COM "expected (%x,%x), got (%x,%x)",
513*13101SVenki.Rajagopalan@Sun.COM FIP_DESC_TYPE_GW_ID, FIP_DESC_LEN_GW_ID,
514*13101SVenki.Rajagopalan@Sun.COM desc_gwid->id_type, desc_gwid->id_len);
515*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_FAILURE);
516*13101SVenki.Rajagopalan@Sun.COM }
517*13101SVenki.Rajagopalan@Sun.COM
518*13101SVenki.Rajagopalan@Sun.COM desc_ka = &(advertise->ad_keep_alive);
519*13101SVenki.Rajagopalan@Sun.COM if (desc_ka->ka_type != FIP_DESC_TYPE_KEEP_ALIVE ||
520*13101SVenki.Rajagopalan@Sun.COM desc_ka->ka_len != FIP_DESC_LEN_KEEP_ALIVE) {
521*13101SVenki.Rajagopalan@Sun.COM ENX_DPRINTF_WARN("invalid type/len in fip ka desc; "
522*13101SVenki.Rajagopalan@Sun.COM "expected (%x,%x), got (%x,%x)",
523*13101SVenki.Rajagopalan@Sun.COM FIP_DESC_TYPE_KEEP_ALIVE, FIP_DESC_LEN_KEEP_ALIVE,
524*13101SVenki.Rajagopalan@Sun.COM desc_ka->ka_type, desc_ka->ka_len);
525*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_FAILURE);
526*13101SVenki.Rajagopalan@Sun.COM }
527*13101SVenki.Rajagopalan@Sun.COM
528*13101SVenki.Rajagopalan@Sun.COM /*
529*13101SVenki.Rajagopalan@Sun.COM * Record if the gw is available for login ('A' bit in the header)
530*13101SVenki.Rajagopalan@Sun.COM */
531*13101SVenki.Rajagopalan@Sun.COM flags = ntohs(hdr->hd_flags);
532*13101SVenki.Rajagopalan@Sun.COM gwi = &(msg->u.gm_info);
533*13101SVenki.Rajagopalan@Sun.COM gwi->gw_flag_available = (flags & FIP_BHFLAG_GWAVAIL) ? 1 : 0;
534*13101SVenki.Rajagopalan@Sun.COM
535*13101SVenki.Rajagopalan@Sun.COM /*
536*13101SVenki.Rajagopalan@Sun.COM * Record if this was in response to a solicit request (unicast
537*13101SVenki.Rajagopalan@Sun.COM * advertisement) or not ('S' bit in the header)
538*13101SVenki.Rajagopalan@Sun.COM */
539*13101SVenki.Rajagopalan@Sun.COM gwi->gw_flag_ucast_advt = (flags & FIP_BHFLAG_SLCTMSG) ? 1 : 0;
540*13101SVenki.Rajagopalan@Sun.COM msg->gm_type = (gwi->gw_flag_ucast_advt) ?
541*13101SVenki.Rajagopalan@Sun.COM FIP_GW_ADVERTISE_UCAST : FIP_GW_ADVERTISE_MCAST;
542*13101SVenki.Rajagopalan@Sun.COM
543*13101SVenki.Rajagopalan@Sun.COM /*
544*13101SVenki.Rajagopalan@Sun.COM * Record all info from the Infiniband Address descriptor
545*13101SVenki.Rajagopalan@Sun.COM */
546*13101SVenki.Rajagopalan@Sun.COM gwi->gw_ctrl_qpn = (ntohl(desc_iba->ia_qpn) & FIP_IBA_QPN_MASK);
547*13101SVenki.Rajagopalan@Sun.COM
548*13101SVenki.Rajagopalan@Sun.COM sl_portid = ntohs(desc_iba->ia_sl_portid);
549*13101SVenki.Rajagopalan@Sun.COM gwi->gw_portid = (sl_portid & FIP_IBA_PORTID_MASK);
550*13101SVenki.Rajagopalan@Sun.COM gwi->gw_sl = ((sl_portid & FIP_IBA_SL_MASK) >> FIP_IBA_SL_SHIFT);
551*13101SVenki.Rajagopalan@Sun.COM
552*13101SVenki.Rajagopalan@Sun.COM gwi->gw_lid = ntohs(desc_iba->ia_lid);
553*13101SVenki.Rajagopalan@Sun.COM
554*13101SVenki.Rajagopalan@Sun.COM bcopy(desc_iba->ia_guid, &guid, sizeof (ib_guid_t));
555*13101SVenki.Rajagopalan@Sun.COM gwi->gw_guid = ntohll(guid);
556*13101SVenki.Rajagopalan@Sun.COM
557*13101SVenki.Rajagopalan@Sun.COM /*
558*13101SVenki.Rajagopalan@Sun.COM * Record all info from the EoIB GW Information descriptor
559*13101SVenki.Rajagopalan@Sun.COM */
560*13101SVenki.Rajagopalan@Sun.COM if (desc_gwinfo->gi_flags & FIP_GWI_HOST_ADMIND_VNICS_MASK)
561*13101SVenki.Rajagopalan@Sun.COM gwi->gw_is_host_adm_vnics = 1;
562*13101SVenki.Rajagopalan@Sun.COM else
563*13101SVenki.Rajagopalan@Sun.COM gwi->gw_is_host_adm_vnics = 0;
564*13101SVenki.Rajagopalan@Sun.COM
565*13101SVenki.Rajagopalan@Sun.COM rss_qpn_num_net_vnics = ntohs(desc_gwinfo->gi_rss_qpn_num_net_vnics);
566*13101SVenki.Rajagopalan@Sun.COM gwi->gw_num_net_vnics = (rss_qpn_num_net_vnics &
567*13101SVenki.Rajagopalan@Sun.COM FIP_GWI_NUM_NET_VNICS_MASK);
568*13101SVenki.Rajagopalan@Sun.COM gwi->gw_n_rss_qpn = ((rss_qpn_num_net_vnics &
569*13101SVenki.Rajagopalan@Sun.COM FIP_GWI_RSS_QPN_MASK) >> FIP_GWI_RSS_QPN_SHIFT);
570*13101SVenki.Rajagopalan@Sun.COM bcopy(desc_gwinfo->gi_vendor_id, gwi->gw_vendor_id, FIP_VENDOR_LEN);
571*13101SVenki.Rajagopalan@Sun.COM (gwi->gw_vendor_id)[FIP_VENDOR_LEN] = '\0';
572*13101SVenki.Rajagopalan@Sun.COM
573*13101SVenki.Rajagopalan@Sun.COM /*
574*13101SVenki.Rajagopalan@Sun.COM * Record all info from the Gateway Identifier descriptor
575*13101SVenki.Rajagopalan@Sun.COM */
576*13101SVenki.Rajagopalan@Sun.COM bcopy(desc_gwid->id_guid, &guid, sizeof (ib_guid_t));
577*13101SVenki.Rajagopalan@Sun.COM gwi->gw_system_guid = ntohll(guid);
578*13101SVenki.Rajagopalan@Sun.COM bcopy(desc_gwid->id_sysname, gwi->gw_system_name, FIP_SYSNAME_LEN);
579*13101SVenki.Rajagopalan@Sun.COM (gwi->gw_system_name)[FIP_SYSNAME_LEN] = '\0';
580*13101SVenki.Rajagopalan@Sun.COM bcopy(desc_gwid->id_portname, gwi->gw_port_name, FIP_PORTNAME_LEN);
581*13101SVenki.Rajagopalan@Sun.COM (gwi->gw_port_name)[FIP_PORTNAME_LEN] = '\0';
582*13101SVenki.Rajagopalan@Sun.COM
583*13101SVenki.Rajagopalan@Sun.COM /*
584*13101SVenki.Rajagopalan@Sun.COM * Record all info from the Keep Alive descriptor
585*13101SVenki.Rajagopalan@Sun.COM */
586*13101SVenki.Rajagopalan@Sun.COM gwi->gw_adv_period = ntohl(desc_ka->ka_gw_adv_period);
587*13101SVenki.Rajagopalan@Sun.COM gwi->gw_ka_period = ntohl(desc_ka->ka_gw_ka_period);
588*13101SVenki.Rajagopalan@Sun.COM gwi->gw_vnic_ka_period = ntohl(desc_ka->ka_vnic_ka_period);
589*13101SVenki.Rajagopalan@Sun.COM
590*13101SVenki.Rajagopalan@Sun.COM gwi->gw_next = NULL;
591*13101SVenki.Rajagopalan@Sun.COM
592*13101SVenki.Rajagopalan@Sun.COM return (ENX_E_SUCCESS);
593*13101SVenki.Rajagopalan@Sun.COM }
594*13101SVenki.Rajagopalan@Sun.COM
595*13101SVenki.Rajagopalan@Sun.COM /*
596*13101SVenki.Rajagopalan@Sun.COM * Rollback whatever we did for making a solicit packet
597*13101SVenki.Rajagopalan@Sun.COM */
598*13101SVenki.Rajagopalan@Sun.COM static void
eibnx_rb_fip_make_solicit_pkt(eibnx_wqe_t * swqe)599*13101SVenki.Rajagopalan@Sun.COM eibnx_rb_fip_make_solicit_pkt(eibnx_wqe_t *swqe)
600*13101SVenki.Rajagopalan@Sun.COM {
601*13101SVenki.Rajagopalan@Sun.COM uint8_t *pkt = (uint8_t *)(uintptr_t)(swqe->qe_sgl.ds_va);
602*13101SVenki.Rajagopalan@Sun.COM
603*13101SVenki.Rajagopalan@Sun.COM bzero(pkt, sizeof (fip_solicit_t));
604*13101SVenki.Rajagopalan@Sun.COM swqe->qe_sgl.ds_len = swqe->qe_bufsz;
605*13101SVenki.Rajagopalan@Sun.COM }
606