1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 #include <sys/types.h>
27 #include <sys/kmem.h>
28 #include <sys/conf.h>
29 #include <sys/ddi.h>
30 #include <sys/sunddi.h>
31 #include <sys/ksynch.h>
32
33 #include <sys/ib/clients/eoib/eib_impl.h>
34
35 /*
36 * Definitions private to this file
37 */
38 ib_gid_t eib_reserved_gid;
39
40 uint8_t eib_zero_mac[] = {
41 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
42 };
43
44 uint8_t eib_broadcast_mac[] = {
45 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
46 };
47
48 int eib_setbit_mod67[] = {
49 -1, 0, 1, 39, 2, 15, 40, 23,
50 3, 12, 16, 59, 41, 19, 24, 54,
51 4, -1, 13, 10, 17, 62, 60, 28,
52 42, 30, 20, 51, 25, 44, 55, 47,
53 5, 32, -1, 38, 14, 22, 11, 58,
54 18, 53, 63, 9, 61, 27, 29, 50,
55 43, 46, 31, 37, 21, 57, 52, 8,
56 26, 49, 45, 36, 56, 7, 48, 35,
57 6, 34, 33
58 };
59
60 char *eib_pvt_props[] = {
61 EIB_DLPROP_GW_EPORT_STATE,
62 EIB_DLPROP_HCA_GUID,
63 EIB_DLPROP_PORT_GUID,
64 NULL
65 };
66
67 #define eib_prop_get_and_test(inst, dp, propname, propval) \
68 { \
69 (propval) = ddi_prop_get_int(DDI_DEV_T_ANY, (dp), \
70 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, (propname), -1); \
71 if ((propval) == -1) { \
72 EIB_DPRINTF_WARN((inst), "eib_get_props: " \
73 "ddi_prop_get_int() could not find " \
74 "property '%s'", (propname)); \
75 goto get_props_fail; \
76 } \
77 }
78
79 #define eib_prop64_get_and_test(inst, dp, propname, propval) \
80 { \
81 (propval) = ddi_prop_get_int64(DDI_DEV_T_ANY, (dp), \
82 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, (propname), -1); \
83 if ((propval) == -1) { \
84 EIB_DPRINTF_WARN((inst), "eib_get_props: " \
85 "ddi_prop_get_int64() could not find " \
86 "property '%s'", (propname)); \
87 goto get_props_fail; \
88 } \
89 }
90
91 #define eib_propstr_get_and_test(inst, dp, propname, propval_p) \
92 { \
93 int rv; \
94 \
95 *(propval_p) = NULL; \
96 \
97 rv = ddi_prop_lookup_string(DDI_DEV_T_ANY, (dp), \
98 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, (propname), \
99 (propval_p)); \
100 if (rv != DDI_PROP_SUCCESS) { \
101 EIB_DPRINTF_WARN((inst), "eib_get_props: " \
102 "ddi_prop_lookup_string() could not find " \
103 "property '%s'", (propname)); \
104 goto get_props_fail; \
105 } \
106 }
107
108 /*
109 * HW/FW workarounds
110 */
111
112 /*
113 * 1. Verification of descriptor list length in the received packets is
114 * disabled, since experimentation shows that BX does not set the desc
115 * list length correctly. True for EoIB nexus as well.
116 */
117 int eib_wa_no_desc_list_len = 1;
118
119 /*
120 * 2. LSO/Checksum_Offload for EoIB packets does not seem to be supported
121 * currently, so we'll disable both temporarily.
122 */
123 int eib_wa_no_cksum_offload = 1;
124 int eib_wa_no_lso = 1;
125
126 /*
127 * 3. The "multicast entry" types are not clearly defined in the spec
128 * at the moment. The current BX software/firmware appears to ignore
129 * the type of the context table entries, so we will treat these
130 * addresses just like regular vnic addresses.
131 */
132 int eib_wa_no_mcast_entries = 1;
133
134 /*
135 * 4. VHUB updates from the gateways provide us with destination LIDs,
136 * and we will hand-create these address vectors.
137 */
138 int eib_wa_no_av_discover = 1;
139
140 /*
141 * 5. The older BX software does not seem to set the VP flag correctly
142 * in the login acknowledgements even when it successfully allocates
143 * a vlan, so we will ignore it for now.
144 */
145 int eib_wa_no_good_vp_flag = 1;
146
147 /*
148 * 6. Each vhub table is expected to carry a checksum at the end to
149 * verify the contents of the received vhub table. The current BX
150 * software/firmware does not seem to fill this field with the
151 * correct value (and/or the spec description is ambiguous). We
152 * will ignore the vhub table checksum verification for now.
153 */
154 int eib_wa_no_good_vhub_cksum = 1;
155
156 int
eib_get_props(eib_t * ss)157 eib_get_props(eib_t *ss)
158 {
159 int val;
160 int64_t val64;
161 char *str;
162 clock_t gw_ka_usecs;
163 clock_t vnic_ka_usecs;
164
165 ss->ei_gw_props = kmem_zalloc(sizeof (eib_gw_props_t), KM_SLEEP);
166 ss->ei_props = kmem_zalloc(sizeof (eib_props_t), KM_SLEEP);
167
168 mutex_init(&ss->ei_gw_props->pp_gw_lock, NULL, MUTEX_DRIVER, NULL);
169
170 /*
171 * The interface speed is currently set to 10Gb/s, since we don't
172 * have a way yet to figure this virtual-wire specific data from
173 * the gateway. The rest of the properties are handed over to us
174 * by the EoIB nexus.
175 */
176 ss->ei_props->ep_ifspeed = 10000000000;
177
178 eib_prop64_get_and_test(ss->ei_instance, ss->ei_dip,
179 EIB_PROP_HCA_GUID, val64);
180 ss->ei_props->ep_hca_guid = (ib_guid_t)val64;
181
182 eib_prop64_get_and_test(ss->ei_instance, ss->ei_dip,
183 EIB_PROP_GW_SYS_GUID, val64);
184 ss->ei_gw_props->pp_gw_system_guid = (ib_guid_t)val64;
185
186 eib_prop64_get_and_test(ss->ei_instance, ss->ei_dip,
187 EIB_PROP_GW_GUID, val64);
188 ss->ei_gw_props->pp_gw_guid = (ib_guid_t)val64;
189
190 eib_prop64_get_and_test(ss->ei_instance, ss->ei_dip,
191 EIB_PROP_GW_SN_PREFIX, val64);
192 ss->ei_gw_props->pp_gw_sn_prefix = (ib_sn_prefix_t)val64;
193
194 eib_prop_get_and_test(ss->ei_instance, ss->ei_dip,
195 EIB_PROP_GW_ADV_PERIOD, val);
196 ss->ei_gw_props->pp_gw_adv_period = (uint_t)val;
197
198 eib_prop_get_and_test(ss->ei_instance, ss->ei_dip,
199 EIB_PROP_GW_KA_PERIOD, val);
200 ss->ei_gw_props->pp_gw_ka_period = (uint_t)val;
201
202 gw_ka_usecs = ss->ei_gw_props->pp_gw_ka_period * 1000;
203 gw_ka_usecs = ((gw_ka_usecs << 2) + gw_ka_usecs) >> 1;
204 ss->ei_gw_props->pp_gw_ka_ticks = drv_usectohz(gw_ka_usecs);
205
206 eib_prop_get_and_test(ss->ei_instance, ss->ei_dip,
207 EIB_PROP_VNIC_KA_PERIOD, val);
208 ss->ei_gw_props->pp_vnic_ka_period = (uint_t)val;
209
210 vnic_ka_usecs = ss->ei_gw_props->pp_vnic_ka_period * 1000;
211 ss->ei_gw_props->pp_vnic_ka_ticks = drv_usectohz(vnic_ka_usecs);
212
213 eib_prop_get_and_test(ss->ei_instance, ss->ei_dip,
214 EIB_PROP_GW_CTRL_QPN, val);
215 ss->ei_gw_props->pp_gw_ctrl_qpn = (ib_qpn_t)val;
216
217 eib_prop_get_and_test(ss->ei_instance, ss->ei_dip,
218 EIB_PROP_GW_LID, val);
219 ss->ei_gw_props->pp_gw_lid = (ib_lid_t)val;
220
221 eib_prop_get_and_test(ss->ei_instance, ss->ei_dip,
222 EIB_PROP_GW_PORTID, val);
223 ss->ei_gw_props->pp_gw_portid = (uint16_t)val;
224
225 eib_prop_get_and_test(ss->ei_instance, ss->ei_dip,
226 EIB_PROP_GW_NUM_NET_VNICS, val);
227 ss->ei_gw_props->pp_gw_num_net_vnics = (uint16_t)val;
228
229 eib_prop_get_and_test(ss->ei_instance, ss->ei_dip,
230 EIB_PROP_GW_AVAILABLE, val);
231 ss->ei_gw_props->pp_gw_flag_available = (uint8_t)val;
232
233 eib_prop_get_and_test(ss->ei_instance, ss->ei_dip,
234 EIB_PROP_GW_HOST_VNICS, val);
235 ss->ei_gw_props->pp_gw_is_host_adm_vnics = (uint8_t)val;
236
237 eib_prop_get_and_test(ss->ei_instance, ss->ei_dip,
238 EIB_PROP_GW_SL, val);
239 ss->ei_gw_props->pp_gw_sl = (uint8_t)val;
240
241 eib_prop_get_and_test(ss->ei_instance, ss->ei_dip,
242 EIB_PROP_GW_N_RSS_QPN, val);
243 ss->ei_gw_props->pp_gw_n_rss_qpn = (uint8_t)val;
244
245 eib_prop_get_and_test(ss->ei_instance, ss->ei_dip,
246 EIB_PROP_HCA_PORTNUM, val);
247 ss->ei_props->ep_port_num = (uint8_t)val;
248
249 eib_propstr_get_and_test(ss->ei_instance, ss->ei_dip,
250 EIB_PROP_GW_SYS_NAME, &str);
251 ss->ei_gw_props->pp_gw_system_name = (uint8_t *)str;
252
253 eib_propstr_get_and_test(ss->ei_instance, ss->ei_dip,
254 EIB_PROP_GW_PORT_NAME, &str);
255 ss->ei_gw_props->pp_gw_port_name = (uint8_t *)str;
256
257 eib_propstr_get_and_test(ss->ei_instance, ss->ei_dip,
258 EIB_PROP_GW_VENDOR_ID, &str);
259 ss->ei_gw_props->pp_gw_vendor_id = (uint8_t *)str;
260
261 return (EIB_E_SUCCESS);
262
263 get_props_fail:
264 eib_rb_get_props(ss);
265 return (EIB_E_FAILURE);
266 }
267
268 void
eib_update_props(eib_t * ss,eib_gw_info_t * new_gw_info)269 eib_update_props(eib_t *ss, eib_gw_info_t *new_gw_info)
270 {
271 eib_gw_props_t *gwp = ss->ei_gw_props;
272 dev_info_t *dip = ss->ei_dip;
273 char *str;
274
275 ASSERT(gwp != NULL && dip != NULL);
276
277 mutex_enter(&gwp->pp_gw_lock);
278
279 gwp->pp_gw_system_guid = new_gw_info->gi_system_guid;
280 (void) ddi_prop_update_int64(DDI_DEV_T_NONE, dip, EIB_PROP_GW_SYS_GUID,
281 gwp->pp_gw_system_guid);
282
283 gwp->pp_gw_guid = new_gw_info->gi_guid;
284 (void) ddi_prop_update_int64(DDI_DEV_T_NONE, dip, EIB_PROP_GW_GUID,
285 gwp->pp_gw_guid);
286
287 gwp->pp_gw_sn_prefix = new_gw_info->gi_sn_prefix;
288 (void) ddi_prop_update_int64(DDI_DEV_T_NONE, dip, EIB_PROP_GW_SN_PREFIX,
289 gwp->pp_gw_sn_prefix);
290
291 gwp->pp_gw_adv_period = new_gw_info->gi_adv_period;
292 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, EIB_PROP_GW_ADV_PERIOD,
293 gwp->pp_gw_adv_period);
294
295 gwp->pp_gw_ka_period = new_gw_info->gi_ka_period;
296 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, EIB_PROP_GW_KA_PERIOD,
297 gwp->pp_gw_ka_period);
298
299 gwp->pp_vnic_ka_period = new_gw_info->gi_vnic_ka_period;
300 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, EIB_PROP_VNIC_KA_PERIOD,
301 gwp->pp_vnic_ka_period);
302
303 gwp->pp_gw_ctrl_qpn = new_gw_info->gi_ctrl_qpn;
304 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, EIB_PROP_GW_CTRL_QPN,
305 gwp->pp_gw_ctrl_qpn);
306
307 gwp->pp_gw_lid = new_gw_info->gi_lid;
308 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, EIB_PROP_GW_LID,
309 gwp->pp_gw_lid);
310
311 gwp->pp_gw_portid = new_gw_info->gi_portid;
312 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, EIB_PROP_GW_PORTID,
313 gwp->pp_gw_portid);
314
315 gwp->pp_gw_num_net_vnics = new_gw_info->gi_num_net_vnics;
316 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip,
317 EIB_PROP_GW_NUM_NET_VNICS, gwp->pp_gw_num_net_vnics);
318
319 gwp->pp_gw_flag_available = new_gw_info->gi_flag_available;
320 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, EIB_PROP_GW_AVAILABLE,
321 gwp->pp_gw_flag_available);
322
323 gwp->pp_gw_is_host_adm_vnics = new_gw_info->gi_is_host_adm_vnics;
324 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, EIB_PROP_GW_HOST_VNICS,
325 gwp->pp_gw_is_host_adm_vnics);
326
327 gwp->pp_gw_sl = new_gw_info->gi_sl;
328 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, EIB_PROP_GW_SL,
329 gwp->pp_gw_sl);
330
331 gwp->pp_gw_n_rss_qpn = new_gw_info->gi_n_rss_qpn;
332 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, EIB_PROP_GW_N_RSS_QPN,
333 gwp->pp_gw_n_rss_qpn);
334
335 (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
336 EIB_PROP_GW_SYS_NAME, (char *)(new_gw_info->gi_system_name));
337 (void) ddi_prop_lookup_string(DDI_DEV_T_ANY, dip,
338 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, EIB_PROP_GW_SYS_NAME, &str);
339 if (gwp->pp_gw_system_name) {
340 ddi_prop_free(gwp->pp_gw_system_name);
341 }
342 gwp->pp_gw_system_name = (uint8_t *)str;
343
344 (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
345 EIB_PROP_GW_PORT_NAME, (char *)(new_gw_info->gi_port_name));
346 (void) ddi_prop_lookup_string(DDI_DEV_T_ANY, dip,
347 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, EIB_PROP_GW_PORT_NAME, &str);
348 if (gwp->pp_gw_port_name) {
349 ddi_prop_free(gwp->pp_gw_port_name);
350 }
351 gwp->pp_gw_port_name = (uint8_t *)str;
352
353 (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
354 EIB_PROP_GW_VENDOR_ID, (char *)(new_gw_info->gi_vendor_id));
355 (void) ddi_prop_lookup_string(DDI_DEV_T_ANY, dip,
356 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, EIB_PROP_GW_VENDOR_ID, &str);
357 if (gwp->pp_gw_vendor_id) {
358 ddi_prop_free(gwp->pp_gw_vendor_id);
359 }
360 gwp->pp_gw_vendor_id = (uint8_t *)str;
361
362 mutex_exit(&gwp->pp_gw_lock);
363 }
364
365 void
eib_rb_get_props(eib_t * ss)366 eib_rb_get_props(eib_t *ss)
367 {
368 /*
369 * Free any allocations
370 */
371 if (ss->ei_gw_props->pp_gw_vendor_id) {
372 ddi_prop_free(ss->ei_gw_props->pp_gw_vendor_id);
373 ss->ei_gw_props->pp_gw_vendor_id = NULL;
374 }
375 if (ss->ei_gw_props->pp_gw_port_name) {
376 ddi_prop_free(ss->ei_gw_props->pp_gw_port_name);
377 ss->ei_gw_props->pp_gw_port_name = NULL;
378 }
379 if (ss->ei_gw_props->pp_gw_system_name) {
380 ddi_prop_free(ss->ei_gw_props->pp_gw_system_name);
381 ss->ei_gw_props->pp_gw_system_name = NULL;
382 }
383
384 mutex_destroy(&ss->ei_gw_props->pp_gw_lock);
385
386 /*
387 * Free space allocated for holding the props
388 */
389 kmem_free(ss->ei_props, sizeof (eib_props_t));
390 kmem_free(ss->ei_gw_props, sizeof (eib_gw_props_t));
391
392 ss->ei_props = NULL;
393 ss->ei_gw_props = NULL;
394 }
395