Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / io / ib / clients / eoib / eib_cmn.c
blob87dc9cecd6d7d35042deb46c844de7a9bea9dbd6
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
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>
33 #include <sys/ib/clients/eoib/eib_impl.h>
36 * Definitions private to this file
38 ib_gid_t eib_reserved_gid;
40 uint8_t eib_zero_mac[] = {
41 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
44 uint8_t eib_broadcast_mac[] = {
45 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
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
60 char *eib_pvt_props[] = {
61 EIB_DLPROP_GW_EPORT_STATE,
62 EIB_DLPROP_HCA_GUID,
63 EIB_DLPROP_PORT_GUID,
64 NULL
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 } \
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 } \
91 #define eib_propstr_get_and_test(inst, dp, propname, propval_p) \
92 { \
93 int rv; \
95 *(propval_p) = NULL; \
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; \
109 * HW/FW workarounds
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.
117 int eib_wa_no_desc_list_len = 1;
120 * 2. LSO/Checksum_Offload for EoIB packets does not seem to be supported
121 * currently, so we'll disable both temporarily.
123 int eib_wa_no_cksum_offload = 1;
124 int eib_wa_no_lso = 1;
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.
132 int eib_wa_no_mcast_entries = 1;
135 * 4. VHUB updates from the gateways provide us with destination LIDs,
136 * and we will hand-create these address vectors.
138 int eib_wa_no_av_discover = 1;
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.
145 int eib_wa_no_good_vp_flag = 1;
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.
154 int eib_wa_no_good_vhub_cksum = 1;
157 eib_get_props(eib_t *ss)
159 int val;
160 int64_t val64;
161 char *str;
162 clock_t gw_ka_usecs;
163 clock_t vnic_ka_usecs;
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);
168 mutex_init(&ss->ei_gw_props->pp_gw_lock, NULL, MUTEX_DRIVER, NULL);
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.
176 ss->ei_props->ep_ifspeed = 10000000000;
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;
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;
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;
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;
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;
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;
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);
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;
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);
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
261 return (EIB_E_SUCCESS);
263 get_props_fail:
264 eib_rb_get_props(ss);
265 return (EIB_E_FAILURE);
268 void
269 eib_update_props(eib_t *ss, eib_gw_info_t *new_gw_info)
271 eib_gw_props_t *gwp = ss->ei_gw_props;
272 dev_info_t *dip = ss->ei_dip;
273 char *str;
275 ASSERT(gwp != NULL && dip != NULL);
277 mutex_enter(&gwp->pp_gw_lock);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
342 gwp->pp_gw_system_name = (uint8_t *)str;
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);
351 gwp->pp_gw_port_name = (uint8_t *)str;
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);
360 gwp->pp_gw_vendor_id = (uint8_t *)str;
362 mutex_exit(&gwp->pp_gw_lock);
365 void
366 eib_rb_get_props(eib_t *ss)
369 * Free any allocations
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;
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;
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;
384 mutex_destroy(&ss->ei_gw_props->pp_gw_lock);
387 * Free space allocated for holding the props
389 kmem_free(ss->ei_props, sizeof (eib_props_t));
390 kmem_free(ss->ei_gw_props, sizeof (eib_gw_props_t));
392 ss->ei_props = NULL;
393 ss->ei_gw_props = NULL;