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 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 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 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