Print this page
patch fix
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/ib/mgt/ibdm/ibdm.c
+++ new/usr/src/uts/common/io/ib/mgt/ibdm/ibdm.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25 /*
26 26 * ibdm.c
27 27 *
28 28 * This file contains the InifiniBand Device Manager (IBDM) support functions.
↓ open down ↓ |
28 lines elided |
↑ open up ↑ |
29 29 * IB nexus driver will only be the client for the IBDM module.
30 30 *
31 31 * IBDM registers with IBTF for HCA arrival/removal notification.
32 32 * IBDM registers with SA access to send DM MADs to discover the IOC's behind
33 33 * the IOU's.
34 34 *
35 35 * IB nexus driver registers with IBDM to find the information about the
36 36 * HCA's and IOC's (behind the IOU) present on the IB fabric.
37 37 */
38 38
39 +#include <sys/sysmacros.h>
39 40 #include <sys/systm.h>
40 41 #include <sys/taskq.h>
41 42 #include <sys/ib/mgt/ibdm/ibdm_impl.h>
42 43 #include <sys/ib/mgt/ibmf/ibmf_impl.h>
43 44 #include <sys/ib/ibtl/impl/ibtl_ibnex.h>
44 45 #include <sys/modctl.h>
45 46
46 47 /* Function Prototype declarations */
47 48 static int ibdm_free_iou_info(ibdm_dp_gidinfo_t *, ibdm_iou_info_t **);
48 49 static int ibdm_fini(void);
49 50 static int ibdm_init(void);
50 51 static int ibdm_get_reachable_ports(ibdm_port_attr_t *,
51 52 ibdm_hca_list_t *);
52 53 static ibdm_dp_gidinfo_t *ibdm_check_dgid(ib_guid_t, ib_sn_prefix_t);
53 54 static ibdm_dp_gidinfo_t *ibdm_check_dest_nodeguid(ibdm_dp_gidinfo_t *);
54 55 static boolean_t ibdm_is_cisco(ib_guid_t);
55 56 static boolean_t ibdm_is_cisco_switch(ibdm_dp_gidinfo_t *);
56 57 static void ibdm_wait_cisco_probe_completion(ibdm_dp_gidinfo_t *);
57 58 static int ibdm_set_classportinfo(ibdm_dp_gidinfo_t *);
58 59 static int ibdm_send_classportinfo(ibdm_dp_gidinfo_t *);
59 60 static int ibdm_send_iounitinfo(ibdm_dp_gidinfo_t *);
60 61 static int ibdm_is_dev_mgt_supported(ibdm_dp_gidinfo_t *);
61 62 static int ibdm_get_node_port_guids(ibmf_saa_handle_t, ib_lid_t,
62 63 ib_guid_t *, ib_guid_t *);
63 64 static int ibdm_retry_command(ibdm_timeout_cb_args_t *);
64 65 static int ibdm_get_diagcode(ibdm_dp_gidinfo_t *, int);
65 66 static int ibdm_verify_mad_status(ib_mad_hdr_t *);
66 67 static int ibdm_handle_redirection(ibmf_msg_t *,
67 68 ibdm_dp_gidinfo_t *, int *);
68 69 static void ibdm_wait_probe_completion(void);
69 70 static void ibdm_sweep_fabric(int);
70 71 static void ibdm_probe_gid_thread(void *);
71 72 static void ibdm_wakeup_probe_gid_cv(void);
72 73 static void ibdm_port_attr_ibmf_init(ibdm_port_attr_t *, ib_pkey_t, int);
73 74 static int ibdm_port_attr_ibmf_fini(ibdm_port_attr_t *, int);
74 75 static void ibdm_update_port_attr(ibdm_port_attr_t *);
75 76 static void ibdm_handle_hca_attach(ib_guid_t);
76 77 static void ibdm_handle_srventry_mad(ibmf_msg_t *,
77 78 ibdm_dp_gidinfo_t *, int *);
78 79 static void ibdm_ibmf_recv_cb(ibmf_handle_t, ibmf_msg_t *, void *);
79 80 static void ibdm_recv_incoming_mad(void *);
80 81 static void ibdm_process_incoming_mad(ibmf_handle_t, ibmf_msg_t *, void *);
81 82 static void ibdm_ibmf_send_cb(ibmf_handle_t, ibmf_msg_t *, void *);
82 83 static void ibdm_pkt_timeout_hdlr(void *arg);
83 84 static void ibdm_initialize_port(ibdm_port_attr_t *);
84 85 static void ibdm_update_port_pkeys(ibdm_port_attr_t *port);
85 86 static void ibdm_handle_diagcode(ibmf_msg_t *, ibdm_dp_gidinfo_t *, int *);
86 87 static void ibdm_probe_gid(ibdm_dp_gidinfo_t *);
87 88 static void ibdm_alloc_send_buffers(ibmf_msg_t *);
88 89 static void ibdm_free_send_buffers(ibmf_msg_t *);
89 90 static void ibdm_handle_hca_detach(ib_guid_t);
90 91 static void ibdm_handle_port_change_event(ibt_async_event_t *);
91 92 static int ibdm_fini_port(ibdm_port_attr_t *);
92 93 static int ibdm_uninit_hca(ibdm_hca_list_t *);
93 94 static void ibdm_handle_setclassportinfo(ibmf_handle_t, ibmf_msg_t *,
94 95 ibdm_dp_gidinfo_t *, int *);
95 96 static void ibdm_handle_iounitinfo(ibmf_handle_t,
96 97 ibmf_msg_t *, ibdm_dp_gidinfo_t *, int *);
97 98 static void ibdm_handle_ioc_profile(ibmf_handle_t,
98 99 ibmf_msg_t *, ibdm_dp_gidinfo_t *, int *);
99 100 static void ibdm_event_hdlr(void *, ibt_hca_hdl_t,
100 101 ibt_async_code_t, ibt_async_event_t *);
101 102 static void ibdm_handle_classportinfo(ibmf_handle_t,
102 103 ibmf_msg_t *, ibdm_dp_gidinfo_t *, int *);
103 104 static void ibdm_update_ioc_port_gidlist(ibdm_ioc_info_t *,
104 105 ibdm_dp_gidinfo_t *);
105 106
106 107 static ibdm_hca_list_t *ibdm_dup_hca_attr(ibdm_hca_list_t *);
107 108 static ibdm_ioc_info_t *ibdm_dup_ioc_info(ibdm_ioc_info_t *,
108 109 ibdm_dp_gidinfo_t *gid_list);
109 110 static void ibdm_probe_ioc(ib_guid_t, ib_guid_t, int);
110 111 static ibdm_ioc_info_t *ibdm_is_ioc_present(ib_guid_t,
111 112 ibdm_dp_gidinfo_t *, int *);
112 113 static ibdm_port_attr_t *ibdm_get_port_attr(ibt_async_event_t *,
113 114 ibdm_hca_list_t **);
114 115 static sa_node_record_t *ibdm_get_node_records(ibmf_saa_handle_t,
115 116 size_t *, ib_guid_t);
116 117 static int ibdm_get_node_record_by_port(ibmf_saa_handle_t,
117 118 ib_guid_t, sa_node_record_t **, size_t *);
118 119 static sa_portinfo_record_t *ibdm_get_portinfo(ibmf_saa_handle_t, size_t *,
119 120 ib_lid_t);
120 121 static ibdm_dp_gidinfo_t *ibdm_create_gid_info(ibdm_port_attr_t *,
121 122 ib_gid_t, ib_gid_t);
122 123 static ibdm_dp_gidinfo_t *ibdm_find_gid(ib_guid_t, ib_guid_t);
123 124 static int ibdm_send_ioc_profile(ibdm_dp_gidinfo_t *, uint8_t);
124 125 static ibdm_ioc_info_t *ibdm_update_ioc_gidlist(ibdm_dp_gidinfo_t *, int);
125 126 static void ibdm_saa_event_cb(ibmf_saa_handle_t, ibmf_saa_subnet_event_t,
126 127 ibmf_saa_event_details_t *, void *);
127 128 static void ibdm_reprobe_update_port_srv(ibdm_ioc_info_t *,
128 129 ibdm_dp_gidinfo_t *);
129 130 static ibdm_dp_gidinfo_t *ibdm_handle_gid_rm(ibdm_dp_gidinfo_t *);
130 131 static void ibdm_rmfrom_glgid_list(ibdm_dp_gidinfo_t *,
131 132 ibdm_dp_gidinfo_t *);
132 133 static void ibdm_addto_gidlist(ibdm_gid_t **, ibdm_gid_t *);
133 134 static void ibdm_free_gid_list(ibdm_gid_t *);
134 135 static void ibdm_rescan_gidlist(ib_guid_t *ioc_guid);
135 136 static void ibdm_notify_newgid_iocs(ibdm_dp_gidinfo_t *);
136 137 static void ibdm_saa_event_taskq(void *);
137 138 static void ibdm_free_saa_event_arg(ibdm_saa_event_arg_t *);
138 139 static void ibdm_get_next_port(ibdm_hca_list_t **,
139 140 ibdm_port_attr_t **, int);
140 141 static void ibdm_add_to_gl_gid(ibdm_dp_gidinfo_t *,
141 142 ibdm_dp_gidinfo_t *);
142 143 static void ibdm_addto_glhcalist(ibdm_dp_gidinfo_t *,
143 144 ibdm_hca_list_t *);
144 145 static void ibdm_delete_glhca_list(ibdm_dp_gidinfo_t *);
145 146 static void ibdm_saa_handle_new_gid(void *);
146 147 static void ibdm_reset_all_dgids(ibmf_saa_handle_t);
147 148 static void ibdm_reset_gidinfo(ibdm_dp_gidinfo_t *);
148 149 static void ibdm_delete_gidinfo(ibdm_dp_gidinfo_t *);
149 150 static void ibdm_fill_srv_attr_mod(ib_mad_hdr_t *, ibdm_timeout_cb_args_t *);
150 151 static void ibdm_bump_transactionID(ibdm_dp_gidinfo_t *);
151 152 static ibdm_ioc_info_t *ibdm_handle_prev_iou();
152 153 static int ibdm_serv_cmp(ibdm_srvents_info_t *, ibdm_srvents_info_t *,
153 154 int);
154 155 static ibdm_ioc_info_t *ibdm_get_ioc_info_with_gid(ib_guid_t,
155 156 ibdm_dp_gidinfo_t **);
156 157
157 158 int ibdm_dft_timeout = IBDM_DFT_TIMEOUT;
158 159 int ibdm_dft_retry_cnt = IBDM_DFT_NRETRIES;
159 160 #ifdef DEBUG
160 161 int ibdm_ignore_saa_event = 0;
161 162 #endif
162 163 int ibdm_enumerate_iocs = 0;
163 164
164 165 /* Modload support */
165 166 static struct modlmisc ibdm_modlmisc = {
166 167 &mod_miscops,
167 168 "InfiniBand Device Manager"
168 169 };
169 170
170 171 struct modlinkage ibdm_modlinkage = {
171 172 MODREV_1,
172 173 (void *)&ibdm_modlmisc,
173 174 NULL
174 175 };
175 176
176 177 static ibt_clnt_modinfo_t ibdm_ibt_modinfo = {
177 178 IBTI_V_CURR,
178 179 IBT_DM,
179 180 ibdm_event_hdlr,
180 181 NULL,
181 182 "ibdm"
182 183 };
183 184
184 185 /* Global variables */
185 186 ibdm_t ibdm;
186 187 int ibdm_taskq_enable = IBDM_ENABLE_TASKQ_HANDLING;
187 188 char *ibdm_string = "ibdm";
188 189
189 190 _NOTE(SCHEME_PROTECTS_DATA("Serialized access by cv",
190 191 ibdm.ibdm_dp_gidlist_head))
191 192
192 193 /*
193 194 * _init
194 195 * Loadable module init, called before any other module.
195 196 * Initialize mutex
196 197 * Register with IBTF
197 198 */
198 199 int
199 200 _init(void)
200 201 {
201 202 int err;
202 203
203 204 IBTF_DPRINTF_L4("ibdm", "\t_init: addr of ibdm %p", &ibdm);
204 205
205 206 if ((err = ibdm_init()) != IBDM_SUCCESS) {
206 207 IBTF_DPRINTF_L2("ibdm", "_init: ibdm_init failed 0x%x", err);
207 208 (void) ibdm_fini();
208 209 return (DDI_FAILURE);
209 210 }
210 211
211 212 if ((err = mod_install(&ibdm_modlinkage)) != 0) {
212 213 IBTF_DPRINTF_L2("ibdm", "_init: mod_install failed 0x%x", err);
213 214 (void) ibdm_fini();
214 215 }
215 216 return (err);
216 217 }
217 218
218 219
219 220 int
220 221 _fini(void)
221 222 {
222 223 int err;
223 224
224 225 if ((err = ibdm_fini()) != IBDM_SUCCESS) {
225 226 IBTF_DPRINTF_L2("ibdm", "_fini: ibdm_fini failed 0x%x", err);
226 227 (void) ibdm_init();
227 228 return (EBUSY);
228 229 }
229 230
230 231 if ((err = mod_remove(&ibdm_modlinkage)) != 0) {
231 232 IBTF_DPRINTF_L2("ibdm", "_fini: mod_remove failed 0x%x", err);
232 233 (void) ibdm_init();
233 234 }
234 235 return (err);
235 236 }
236 237
237 238
238 239 int
239 240 _info(struct modinfo *modinfop)
240 241 {
241 242 return (mod_info(&ibdm_modlinkage, modinfop));
242 243 }
243 244
244 245
245 246 /*
246 247 * ibdm_init():
247 248 * Register with IBTF
248 249 * Allocate memory for the HCAs
249 250 * Allocate minor-nodes for the HCAs
250 251 */
251 252 static int
252 253 ibdm_init(void)
253 254 {
254 255 int i, hca_count;
255 256 ib_guid_t *hca_guids;
256 257 ibt_status_t status;
257 258
258 259 IBTF_DPRINTF_L4("ibdm", "\tibdm_init:");
259 260 if (!(ibdm.ibdm_state & IBDM_LOCKS_ALLOCED)) {
260 261 mutex_init(&ibdm.ibdm_mutex, NULL, MUTEX_DEFAULT, NULL);
261 262 mutex_init(&ibdm.ibdm_hl_mutex, NULL, MUTEX_DEFAULT, NULL);
262 263 mutex_init(&ibdm.ibdm_ibnex_mutex, NULL, MUTEX_DEFAULT, NULL);
263 264 cv_init(&ibdm.ibdm_port_settle_cv, NULL, CV_DRIVER, NULL);
264 265 mutex_enter(&ibdm.ibdm_mutex);
265 266 ibdm.ibdm_state |= IBDM_LOCKS_ALLOCED;
266 267 }
267 268
268 269 if (!(ibdm.ibdm_state & IBDM_IBT_ATTACHED)) {
269 270 if ((status = ibt_attach(&ibdm_ibt_modinfo, NULL, NULL,
270 271 (void *)&ibdm.ibdm_ibt_clnt_hdl)) != IBT_SUCCESS) {
271 272 IBTF_DPRINTF_L2("ibdm", "ibdm_init: ibt_attach "
272 273 "failed %x", status);
273 274 mutex_exit(&ibdm.ibdm_mutex);
274 275 return (IBDM_FAILURE);
275 276 }
276 277
277 278 ibdm.ibdm_state |= IBDM_IBT_ATTACHED;
278 279 mutex_exit(&ibdm.ibdm_mutex);
279 280 }
280 281
281 282
282 283 if (!(ibdm.ibdm_state & IBDM_HCA_ATTACHED)) {
283 284 hca_count = ibt_get_hca_list(&hca_guids);
284 285 IBTF_DPRINTF_L4("ibdm", "ibdm_init: num_hcas = %d", hca_count);
285 286 for (i = 0; i < hca_count; i++)
286 287 (void) ibdm_handle_hca_attach(hca_guids[i]);
287 288 if (hca_count)
288 289 ibt_free_hca_list(hca_guids, hca_count);
289 290
290 291 mutex_enter(&ibdm.ibdm_mutex);
291 292 ibdm.ibdm_state |= IBDM_HCA_ATTACHED;
292 293 mutex_exit(&ibdm.ibdm_mutex);
293 294 }
294 295
295 296 if (!(ibdm.ibdm_state & IBDM_CVS_ALLOCED)) {
296 297 cv_init(&ibdm.ibdm_probe_cv, NULL, CV_DRIVER, NULL);
297 298 cv_init(&ibdm.ibdm_busy_cv, NULL, CV_DRIVER, NULL);
298 299 mutex_enter(&ibdm.ibdm_mutex);
299 300 ibdm.ibdm_state |= IBDM_CVS_ALLOCED;
300 301 mutex_exit(&ibdm.ibdm_mutex);
301 302 }
302 303 return (IBDM_SUCCESS);
303 304 }
304 305
305 306
306 307 static int
307 308 ibdm_free_iou_info(ibdm_dp_gidinfo_t *gid_info, ibdm_iou_info_t **ioup)
308 309 {
309 310 int ii, k, niocs;
310 311 size_t size;
311 312 ibdm_gid_t *delete, *head;
312 313 timeout_id_t timeout_id;
313 314 ibdm_ioc_info_t *ioc;
314 315 ibdm_iou_info_t *gl_iou = *ioup;
315 316
316 317 ASSERT(mutex_owned(&gid_info->gl_mutex));
317 318 if (gl_iou == NULL) {
318 319 IBTF_DPRINTF_L4("ibdm", "\tibdm_free_iou_info: No IOU");
319 320 return (0);
320 321 }
321 322
322 323 niocs = gl_iou->iou_info.iou_num_ctrl_slots;
323 324 IBTF_DPRINTF_L4("ibdm", "\tfree_iou_info: gid_info = %p, niocs %d",
324 325 gid_info, niocs);
325 326
326 327 for (ii = 0; ii < niocs; ii++) {
327 328 ioc = (ibdm_ioc_info_t *)&gl_iou->iou_ioc_info[ii];
328 329
329 330 /* handle the case where an ioc_timeout_id is scheduled */
330 331 if (ioc->ioc_timeout_id) {
331 332 timeout_id = ioc->ioc_timeout_id;
332 333 ioc->ioc_timeout_id = 0;
333 334 mutex_exit(&gid_info->gl_mutex);
334 335 IBTF_DPRINTF_L5("ibdm", "free_iou_info: "
335 336 "ioc_timeout_id = 0x%x", timeout_id);
336 337 if (untimeout(timeout_id) == -1) {
337 338 IBTF_DPRINTF_L2("ibdm", "free_iou_info: "
338 339 "untimeout ioc_timeout_id failed");
339 340 mutex_enter(&gid_info->gl_mutex);
340 341 return (-1);
341 342 }
342 343 mutex_enter(&gid_info->gl_mutex);
343 344 }
344 345
345 346 /* handle the case where an ioc_dc_timeout_id is scheduled */
346 347 if (ioc->ioc_dc_timeout_id) {
347 348 timeout_id = ioc->ioc_dc_timeout_id;
348 349 ioc->ioc_dc_timeout_id = 0;
349 350 mutex_exit(&gid_info->gl_mutex);
350 351 IBTF_DPRINTF_L5("ibdm", "free_iou_info: "
351 352 "ioc_dc_timeout_id = 0x%x", timeout_id);
352 353 if (untimeout(timeout_id) == -1) {
353 354 IBTF_DPRINTF_L2("ibdm", "free_iou_info: "
354 355 "untimeout ioc_dc_timeout_id failed");
355 356 mutex_enter(&gid_info->gl_mutex);
356 357 return (-1);
357 358 }
358 359 mutex_enter(&gid_info->gl_mutex);
359 360 }
360 361
361 362 /* handle the case where serv[k].se_timeout_id is scheduled */
362 363 for (k = 0; k < ioc->ioc_profile.ioc_service_entries; k++) {
363 364 if (ioc->ioc_serv[k].se_timeout_id) {
364 365 timeout_id = ioc->ioc_serv[k].se_timeout_id;
365 366 ioc->ioc_serv[k].se_timeout_id = 0;
366 367 mutex_exit(&gid_info->gl_mutex);
367 368 IBTF_DPRINTF_L5("ibdm", "free_iou_info: "
368 369 "ioc->ioc_serv[%d].se_timeout_id = 0x%x",
369 370 k, timeout_id);
370 371 if (untimeout(timeout_id) == -1) {
371 372 IBTF_DPRINTF_L2("ibdm", "free_iou_info:"
372 373 " untimeout se_timeout_id failed");
373 374 mutex_enter(&gid_info->gl_mutex);
374 375 return (-1);
375 376 }
376 377 mutex_enter(&gid_info->gl_mutex);
377 378 }
378 379 }
379 380
380 381 /* delete GID list in IOC */
381 382 head = ioc->ioc_gid_list;
382 383 while (head) {
383 384 IBTF_DPRINTF_L4("ibdm", "\tibdm_free_iou_info: "
384 385 "Deleting gid_list struct %p", head);
385 386 delete = head;
386 387 head = head->gid_next;
387 388 kmem_free(delete, sizeof (ibdm_gid_t));
388 389 }
389 390 ioc->ioc_gid_list = NULL;
390 391
391 392 /* delete ioc_serv */
392 393 size = ioc->ioc_profile.ioc_service_entries *
393 394 sizeof (ibdm_srvents_info_t);
394 395 if (ioc->ioc_serv && size) {
395 396 kmem_free(ioc->ioc_serv, size);
396 397 ioc->ioc_serv = NULL;
397 398 }
398 399 }
399 400 /*
400 401 * Clear the IBDM_CISCO_PROBE_DONE flag to get the IO Unit information
401 402 * via the switch during the probe process.
402 403 */
403 404 gid_info->gl_flag &= ~IBDM_CISCO_PROBE_DONE;
404 405
405 406 IBTF_DPRINTF_L4("ibdm", "\tibdm_free_iou_info: deleting IOU & IOC");
406 407 size = sizeof (ibdm_iou_info_t) + niocs * sizeof (ibdm_ioc_info_t);
407 408 kmem_free(gl_iou, size);
408 409 *ioup = NULL;
409 410 return (0);
410 411 }
411 412
412 413
413 414 /*
414 415 * ibdm_fini():
415 416 * Un-register with IBTF
416 417 * De allocate memory for the GID info
417 418 */
418 419 static int
419 420 ibdm_fini()
420 421 {
421 422 int ii;
422 423 ibdm_hca_list_t *hca_list, *temp;
423 424 ibdm_dp_gidinfo_t *gid_info, *tmp;
424 425 ibdm_gid_t *head, *delete;
425 426
426 427 IBTF_DPRINTF_L4("ibdm", "\tibdm_fini");
427 428
428 429 mutex_enter(&ibdm.ibdm_hl_mutex);
429 430 if (ibdm.ibdm_state & IBDM_IBT_ATTACHED) {
430 431 if (ibt_detach(ibdm.ibdm_ibt_clnt_hdl) != IBT_SUCCESS) {
431 432 IBTF_DPRINTF_L2("ibdm", "\t_fini: ibt_detach failed");
432 433 mutex_exit(&ibdm.ibdm_hl_mutex);
433 434 return (IBDM_FAILURE);
434 435 }
435 436 ibdm.ibdm_state &= ~IBDM_IBT_ATTACHED;
436 437 ibdm.ibdm_ibt_clnt_hdl = NULL;
437 438 }
438 439
439 440 hca_list = ibdm.ibdm_hca_list_head;
440 441 IBTF_DPRINTF_L4("ibdm", "\tibdm_fini: nhcas %d", ibdm.ibdm_hca_count);
441 442 for (ii = 0; ii < ibdm.ibdm_hca_count; ii++) {
442 443 temp = hca_list;
443 444 hca_list = hca_list->hl_next;
444 445 IBTF_DPRINTF_L4("ibdm", "\tibdm_fini: hca %p", temp);
445 446 if (ibdm_uninit_hca(temp) != IBDM_SUCCESS) {
446 447 IBTF_DPRINTF_L2("ibdm", "\tibdm_fini: "
447 448 "uninit_hca %p failed", temp);
448 449 mutex_exit(&ibdm.ibdm_hl_mutex);
449 450 return (IBDM_FAILURE);
450 451 }
451 452 }
452 453 mutex_exit(&ibdm.ibdm_hl_mutex);
453 454
454 455 mutex_enter(&ibdm.ibdm_mutex);
455 456 if (ibdm.ibdm_state & IBDM_HCA_ATTACHED)
456 457 ibdm.ibdm_state &= ~IBDM_HCA_ATTACHED;
457 458
458 459 gid_info = ibdm.ibdm_dp_gidlist_head;
459 460 while (gid_info) {
460 461 mutex_enter(&gid_info->gl_mutex);
461 462 (void) ibdm_free_iou_info(gid_info, &gid_info->gl_iou);
462 463 mutex_exit(&gid_info->gl_mutex);
463 464 ibdm_delete_glhca_list(gid_info);
464 465
465 466 tmp = gid_info;
466 467 gid_info = gid_info->gl_next;
467 468 mutex_destroy(&tmp->gl_mutex);
468 469 head = tmp->gl_gid;
469 470 while (head) {
470 471 IBTF_DPRINTF_L4("ibdm",
471 472 "\tibdm_fini: Deleting gid structs");
472 473 delete = head;
473 474 head = head->gid_next;
474 475 kmem_free(delete, sizeof (ibdm_gid_t));
475 476 }
476 477 kmem_free(tmp, sizeof (ibdm_dp_gidinfo_t));
477 478 }
478 479 mutex_exit(&ibdm.ibdm_mutex);
479 480
480 481 if (ibdm.ibdm_state & IBDM_LOCKS_ALLOCED) {
481 482 ibdm.ibdm_state &= ~IBDM_LOCKS_ALLOCED;
482 483 mutex_destroy(&ibdm.ibdm_mutex);
483 484 mutex_destroy(&ibdm.ibdm_hl_mutex);
484 485 mutex_destroy(&ibdm.ibdm_ibnex_mutex);
485 486 cv_destroy(&ibdm.ibdm_port_settle_cv);
486 487 }
487 488 if (ibdm.ibdm_state & IBDM_CVS_ALLOCED) {
488 489 ibdm.ibdm_state &= ~IBDM_CVS_ALLOCED;
489 490 cv_destroy(&ibdm.ibdm_probe_cv);
490 491 cv_destroy(&ibdm.ibdm_busy_cv);
491 492 }
492 493 return (IBDM_SUCCESS);
493 494 }
494 495
495 496
496 497 /*
497 498 * ibdm_event_hdlr()
498 499 *
499 500 * IBDM registers this asynchronous event handler at the time of
500 501 * ibt_attach. IBDM support the following async events. For other
501 502 * event, simply returns success.
502 503 * IBT_HCA_ATTACH_EVENT:
503 504 * Retrieves the information about all the port that are
504 505 * present on this HCA, allocates the port attributes
505 506 * structure and calls IB nexus callback routine with
506 507 * the port attributes structure as an input argument.
507 508 * IBT_HCA_DETACH_EVENT:
508 509 * Retrieves the information about all the ports that are
509 510 * present on this HCA and calls IB nexus callback with
510 511 * port guid as an argument
511 512 * IBT_EVENT_PORT_UP:
512 513 * Register with IBMF and SA access
513 514 * Setup IBMF receive callback routine
514 515 * IBT_EVENT_PORT_DOWN:
515 516 * Un-Register with IBMF and SA access
516 517 * Teardown IBMF receive callback routine
517 518 */
518 519 /*ARGSUSED*/
519 520 static void
520 521 ibdm_event_hdlr(void *clnt_hdl,
521 522 ibt_hca_hdl_t hca_hdl, ibt_async_code_t code, ibt_async_event_t *event)
522 523 {
523 524 ibdm_hca_list_t *hca_list;
524 525 ibdm_port_attr_t *port;
525 526 ibmf_saa_handle_t port_sa_hdl;
526 527
527 528 IBTF_DPRINTF_L4("ibdm", "\tevent_hdlr: async code 0x%x", code);
528 529
529 530 switch (code) {
530 531 case IBT_HCA_ATTACH_EVENT: /* New HCA registered with IBTF */
531 532 ibdm_handle_hca_attach(event->ev_hca_guid);
532 533 break;
533 534
534 535 case IBT_HCA_DETACH_EVENT: /* HCA unregistered with IBTF */
535 536 ibdm_handle_hca_detach(event->ev_hca_guid);
536 537 mutex_enter(&ibdm.ibdm_ibnex_mutex);
537 538 if (ibdm.ibdm_ibnex_callback != NULL) {
538 539 (*ibdm.ibdm_ibnex_callback)((void *)
539 540 &event->ev_hca_guid, IBDM_EVENT_HCA_REMOVED);
540 541 }
541 542 mutex_exit(&ibdm.ibdm_ibnex_mutex);
542 543 break;
543 544
544 545 case IBT_EVENT_PORT_UP:
545 546 IBTF_DPRINTF_L4("ibdm", "\tevent_hdlr: PORT_UP");
546 547 mutex_enter(&ibdm.ibdm_hl_mutex);
547 548 port = ibdm_get_port_attr(event, &hca_list);
548 549 if (port == NULL) {
549 550 IBTF_DPRINTF_L2("ibdm",
550 551 "\tevent_hdlr: HCA not present");
551 552 mutex_exit(&ibdm.ibdm_hl_mutex);
552 553 break;
553 554 }
554 555 ibdm_initialize_port(port);
555 556 hca_list->hl_nports_active++;
556 557 cv_broadcast(&ibdm.ibdm_port_settle_cv);
557 558 mutex_exit(&ibdm.ibdm_hl_mutex);
558 559
559 560 /* Inform IB nexus driver */
560 561 mutex_enter(&ibdm.ibdm_ibnex_mutex);
561 562 if (ibdm.ibdm_ibnex_callback != NULL) {
562 563 (*ibdm.ibdm_ibnex_callback)((void *)
563 564 &event->ev_hca_guid, IBDM_EVENT_PORT_UP);
564 565 }
565 566 mutex_exit(&ibdm.ibdm_ibnex_mutex);
566 567 break;
567 568
568 569 case IBT_ERROR_PORT_DOWN:
569 570 IBTF_DPRINTF_L4("ibdm", "\tevent_hdlr: PORT_DOWN");
570 571 mutex_enter(&ibdm.ibdm_hl_mutex);
571 572 port = ibdm_get_port_attr(event, &hca_list);
572 573 if (port == NULL) {
573 574 IBTF_DPRINTF_L2("ibdm",
574 575 "\tevent_hdlr: HCA not present");
575 576 mutex_exit(&ibdm.ibdm_hl_mutex);
576 577 break;
577 578 }
578 579 hca_list->hl_nports_active--;
579 580 port_sa_hdl = port->pa_sa_hdl;
580 581 (void) ibdm_fini_port(port);
581 582 port->pa_state = IBT_PORT_DOWN;
582 583 cv_broadcast(&ibdm.ibdm_port_settle_cv);
583 584 mutex_exit(&ibdm.ibdm_hl_mutex);
584 585 ibdm_reset_all_dgids(port_sa_hdl);
585 586 break;
586 587
587 588 case IBT_PORT_CHANGE_EVENT:
588 589 IBTF_DPRINTF_L4("ibdm", "\tevent_hdlr: PORT_CHANGE");
589 590 if (event->ev_port_flags & IBT_PORT_CHANGE_PKEY)
590 591 ibdm_handle_port_change_event(event);
591 592 break;
592 593
593 594 default: /* Ignore all other events/errors */
594 595 break;
595 596 }
596 597 }
597 598
598 599 static void
599 600 ibdm_handle_port_change_event(ibt_async_event_t *event)
600 601 {
601 602 ibdm_port_attr_t *port;
602 603 ibdm_hca_list_t *hca_list;
603 604
604 605 IBTF_DPRINTF_L2("ibdm", "\tibdm_handle_port_change_event:"
605 606 " HCA guid %llx", event->ev_hca_guid);
606 607 mutex_enter(&ibdm.ibdm_hl_mutex);
607 608 port = ibdm_get_port_attr(event, &hca_list);
608 609 if (port == NULL) {
609 610 IBTF_DPRINTF_L2("ibdm", "\tevent_hdlr: HCA not present");
610 611 mutex_exit(&ibdm.ibdm_hl_mutex);
611 612 return;
612 613 }
613 614 ibdm_update_port_pkeys(port);
614 615 cv_broadcast(&ibdm.ibdm_port_settle_cv);
615 616 mutex_exit(&ibdm.ibdm_hl_mutex);
616 617
617 618 /* Inform IB nexus driver */
618 619 mutex_enter(&ibdm.ibdm_ibnex_mutex);
619 620 if (ibdm.ibdm_ibnex_callback != NULL) {
620 621 (*ibdm.ibdm_ibnex_callback)((void *)
621 622 &event->ev_hca_guid, IBDM_EVENT_PORT_PKEY_CHANGE);
622 623 }
623 624 mutex_exit(&ibdm.ibdm_ibnex_mutex);
624 625 }
625 626
626 627 /*
627 628 * ibdm_update_port_pkeys()
628 629 * Update the pkey table
629 630 * Update the port attributes
630 631 */
631 632 static void
632 633 ibdm_update_port_pkeys(ibdm_port_attr_t *port)
633 634 {
634 635 uint_t nports, size;
635 636 uint_t pkey_idx, opkey_idx;
636 637 uint16_t npkeys;
637 638 ibt_hca_portinfo_t *pinfop;
638 639 ib_pkey_t pkey;
639 640 ibdm_pkey_tbl_t *pkey_tbl;
640 641 ibdm_port_attr_t newport;
641 642
642 643 IBTF_DPRINTF_L4("ibdm", "\tupdate_port_pkeys:");
643 644 ASSERT(MUTEX_HELD(&ibdm.ibdm_hl_mutex));
644 645
645 646 /* Check whether the port is active */
646 647 if (ibt_get_port_state(port->pa_hca_hdl, port->pa_port_num, NULL,
647 648 NULL) != IBT_SUCCESS)
648 649 return;
649 650
650 651 if (ibt_query_hca_ports(port->pa_hca_hdl, port->pa_port_num,
651 652 &pinfop, &nports, &size) != IBT_SUCCESS) {
652 653 /* This should not occur */
653 654 port->pa_npkeys = 0;
654 655 port->pa_pkey_tbl = NULL;
655 656 return;
656 657 }
657 658
658 659 npkeys = pinfop->p_pkey_tbl_sz;
659 660 pkey_tbl = kmem_zalloc(npkeys * sizeof (ibdm_pkey_tbl_t), KM_SLEEP);
660 661 newport.pa_pkey_tbl = pkey_tbl;
661 662 newport.pa_ibmf_hdl = port->pa_ibmf_hdl;
662 663
663 664 for (pkey_idx = 0; pkey_idx < npkeys; pkey_idx++) {
664 665 pkey = pkey_tbl[pkey_idx].pt_pkey =
665 666 pinfop->p_pkey_tbl[pkey_idx];
666 667 /*
667 668 * Is this pkey present in the current table ?
668 669 */
669 670 for (opkey_idx = 0; opkey_idx < port->pa_npkeys; opkey_idx++) {
670 671 if (pkey == port->pa_pkey_tbl[opkey_idx].pt_pkey) {
671 672 pkey_tbl[pkey_idx].pt_qp_hdl =
672 673 port->pa_pkey_tbl[opkey_idx].pt_qp_hdl;
673 674 port->pa_pkey_tbl[opkey_idx].pt_qp_hdl = NULL;
674 675 break;
675 676 }
676 677 }
677 678
678 679 if (opkey_idx == port->pa_npkeys) {
679 680 pkey = pkey_tbl[pkey_idx].pt_pkey;
680 681 if (IBDM_INVALID_PKEY(pkey)) {
681 682 pkey_tbl[pkey_idx].pt_qp_hdl = NULL;
682 683 continue;
683 684 }
684 685 ibdm_port_attr_ibmf_init(&newport, pkey, pkey_idx);
685 686 }
686 687 }
687 688
688 689 for (opkey_idx = 0; opkey_idx < port->pa_npkeys; opkey_idx++) {
689 690 if (port->pa_pkey_tbl[opkey_idx].pt_qp_hdl != NULL) {
690 691 if (ibdm_port_attr_ibmf_fini(port, opkey_idx) !=
691 692 IBDM_SUCCESS) {
692 693 IBTF_DPRINTF_L2("ibdm", "\tupdate_port_pkeys: "
693 694 "ibdm_port_attr_ibmf_fini failed for "
694 695 "port pkey 0x%x",
695 696 port->pa_pkey_tbl[opkey_idx].pt_pkey);
696 697 }
697 698 }
698 699 }
699 700
700 701 if (port->pa_pkey_tbl != NULL) {
701 702 kmem_free(port->pa_pkey_tbl,
702 703 port->pa_npkeys * sizeof (ibdm_pkey_tbl_t));
703 704 }
704 705
705 706 port->pa_npkeys = npkeys;
706 707 port->pa_pkey_tbl = pkey_tbl;
707 708 port->pa_sn_prefix = pinfop->p_sgid_tbl[0].gid_prefix;
708 709 port->pa_state = pinfop->p_linkstate;
709 710 ibt_free_portinfo(pinfop, size);
710 711 }
711 712
712 713 /*
713 714 * ibdm_initialize_port()
714 715 * Register with IBMF
715 716 * Register with SA access
716 717 * Register a receive callback routine with IBMF. IBMF invokes
717 718 * this routine whenever a MAD arrives at this port.
718 719 * Update the port attributes
719 720 */
720 721 static void
721 722 ibdm_initialize_port(ibdm_port_attr_t *port)
722 723 {
723 724 int ii;
724 725 uint_t nports, size;
725 726 uint_t pkey_idx;
726 727 ib_pkey_t pkey;
727 728 ibt_hca_portinfo_t *pinfop;
728 729 ibmf_register_info_t ibmf_reg;
729 730 ibmf_saa_subnet_event_args_t event_args;
730 731
731 732 IBTF_DPRINTF_L4("ibdm", "\tinitialize_port:");
732 733 ASSERT(MUTEX_HELD(&ibdm.ibdm_hl_mutex));
733 734
734 735 /* Check whether the port is active */
735 736 if (ibt_get_port_state(port->pa_hca_hdl, port->pa_port_num, NULL,
736 737 NULL) != IBT_SUCCESS)
737 738 return;
738 739
739 740 if (port->pa_sa_hdl != NULL || port->pa_pkey_tbl != NULL)
740 741 return;
741 742
742 743 if (ibt_query_hca_ports(port->pa_hca_hdl, port->pa_port_num,
743 744 &pinfop, &nports, &size) != IBT_SUCCESS) {
744 745 /* This should not occur */
745 746 port->pa_npkeys = 0;
746 747 port->pa_pkey_tbl = NULL;
747 748 return;
748 749 }
749 750 port->pa_sn_prefix = pinfop->p_sgid_tbl[0].gid_prefix;
750 751
751 752 port->pa_state = pinfop->p_linkstate;
752 753 port->pa_npkeys = pinfop->p_pkey_tbl_sz;
753 754 port->pa_pkey_tbl = (ibdm_pkey_tbl_t *)kmem_zalloc(
754 755 port->pa_npkeys * sizeof (ibdm_pkey_tbl_t), KM_SLEEP);
755 756
756 757 for (pkey_idx = 0; pkey_idx < port->pa_npkeys; pkey_idx++)
757 758 port->pa_pkey_tbl[pkey_idx].pt_pkey =
758 759 pinfop->p_pkey_tbl[pkey_idx];
759 760
760 761 ibt_free_portinfo(pinfop, size);
761 762
762 763 if (ibdm_enumerate_iocs) {
763 764 event_args.is_event_callback = ibdm_saa_event_cb;
764 765 event_args.is_event_callback_arg = port;
765 766 if (ibmf_sa_session_open(port->pa_port_guid, 0, &event_args,
766 767 IBMF_VERSION, 0, &port->pa_sa_hdl) != IBMF_SUCCESS) {
767 768 IBTF_DPRINTF_L2("ibdm", "\tinitialize_port: "
768 769 "sa access registration failed");
769 770 (void) ibdm_fini_port(port);
770 771 return;
771 772 }
772 773
773 774 ibmf_reg.ir_ci_guid = port->pa_hca_guid;
774 775 ibmf_reg.ir_port_num = port->pa_port_num;
775 776 ibmf_reg.ir_client_class = DEV_MGT_MANAGER;
776 777
777 778 if (ibmf_register(&ibmf_reg, IBMF_VERSION, 0, NULL, NULL,
778 779 &port->pa_ibmf_hdl, &port->pa_ibmf_caps) != IBMF_SUCCESS) {
779 780 IBTF_DPRINTF_L2("ibdm", "\tinitialize_port: "
780 781 "IBMF registration failed");
781 782 (void) ibdm_fini_port(port);
782 783 return;
783 784 }
784 785
785 786 if (ibmf_setup_async_cb(port->pa_ibmf_hdl,
786 787 IBMF_QP_HANDLE_DEFAULT,
787 788 ibdm_ibmf_recv_cb, 0, 0) != IBMF_SUCCESS) {
788 789 IBTF_DPRINTF_L2("ibdm", "\tinitialize_port: "
789 790 "IBMF setup recv cb failed");
790 791 (void) ibdm_fini_port(port);
791 792 return;
792 793 }
793 794 } else {
794 795 port->pa_sa_hdl = NULL;
795 796 port->pa_ibmf_hdl = NULL;
796 797 }
797 798
798 799 for (ii = 0; ii < port->pa_npkeys; ii++) {
799 800 pkey = port->pa_pkey_tbl[ii].pt_pkey;
800 801 if (IBDM_INVALID_PKEY(pkey)) {
801 802 port->pa_pkey_tbl[ii].pt_qp_hdl = NULL;
802 803 continue;
803 804 }
804 805 ibdm_port_attr_ibmf_init(port, pkey, ii);
805 806 }
806 807 }
807 808
808 809
809 810 /*
810 811 * ibdm_port_attr_ibmf_init:
811 812 * With IBMF - Alloc QP Handle and Setup Async callback
812 813 */
813 814 static void
814 815 ibdm_port_attr_ibmf_init(ibdm_port_attr_t *port, ib_pkey_t pkey, int ii)
815 816 {
816 817 int ret;
817 818
818 819 if (ibdm_enumerate_iocs == 0) {
819 820 port->pa_pkey_tbl[ii].pt_qp_hdl = NULL;
820 821 return;
821 822 }
822 823
823 824 if ((ret = ibmf_alloc_qp(port->pa_ibmf_hdl, pkey, IB_GSI_QKEY,
824 825 IBMF_ALT_QP_MAD_NO_RMPP, &port->pa_pkey_tbl[ii].pt_qp_hdl)) !=
825 826 IBMF_SUCCESS) {
826 827 IBTF_DPRINTF_L2("ibdm", "\tport_attr_ibmf_init: "
827 828 "IBMF failed to alloc qp %d", ret);
828 829 port->pa_pkey_tbl[ii].pt_qp_hdl = NULL;
829 830 return;
830 831 }
831 832
832 833 IBTF_DPRINTF_L4("ibdm", "\tport_attr_ibmf_init: QP handle is %p",
833 834 port->pa_ibmf_hdl);
834 835
835 836 if ((ret = ibmf_setup_async_cb(port->pa_ibmf_hdl,
836 837 port->pa_pkey_tbl[ii].pt_qp_hdl, ibdm_ibmf_recv_cb, 0, 0)) !=
837 838 IBMF_SUCCESS) {
838 839 IBTF_DPRINTF_L2("ibdm", "\tport_attr_ibmf_init: "
839 840 "IBMF setup recv cb failed %d", ret);
840 841 (void) ibmf_free_qp(port->pa_ibmf_hdl,
841 842 &port->pa_pkey_tbl[ii].pt_qp_hdl, 0);
842 843 port->pa_pkey_tbl[ii].pt_qp_hdl = NULL;
843 844 }
844 845 }
845 846
846 847
847 848 /*
848 849 * ibdm_get_port_attr()
849 850 * Get port attributes from HCA guid and port number
850 851 * Return pointer to ibdm_port_attr_t on Success
851 852 * and NULL on failure
852 853 */
853 854 static ibdm_port_attr_t *
854 855 ibdm_get_port_attr(ibt_async_event_t *event, ibdm_hca_list_t **retval)
855 856 {
856 857 ibdm_hca_list_t *hca_list;
857 858 ibdm_port_attr_t *port_attr;
858 859 int ii;
859 860
860 861 IBTF_DPRINTF_L4("ibdm", "\tget_port_attr: port# %d", event->ev_port);
861 862 ASSERT(MUTEX_HELD(&ibdm.ibdm_hl_mutex));
862 863 hca_list = ibdm.ibdm_hca_list_head;
863 864 while (hca_list) {
864 865 if (hca_list->hl_hca_guid == event->ev_hca_guid) {
865 866 for (ii = 0; ii < hca_list->hl_nports; ii++) {
866 867 port_attr = &hca_list->hl_port_attr[ii];
867 868 if (port_attr->pa_port_num == event->ev_port) {
868 869 *retval = hca_list;
869 870 return (port_attr);
870 871 }
871 872 }
872 873 }
873 874 hca_list = hca_list->hl_next;
874 875 }
875 876 return (NULL);
876 877 }
877 878
878 879
879 880 /*
880 881 * ibdm_update_port_attr()
881 882 * Update the port attributes
882 883 */
883 884 static void
884 885 ibdm_update_port_attr(ibdm_port_attr_t *port)
885 886 {
886 887 uint_t nports, size;
887 888 uint_t pkey_idx;
888 889 ibt_hca_portinfo_t *portinfop;
889 890
890 891 IBTF_DPRINTF_L4("ibdm", "\tupdate_port_attr: Begin");
891 892 if (ibt_query_hca_ports(port->pa_hca_hdl,
892 893 port->pa_port_num, &portinfop, &nports, &size) != IBT_SUCCESS) {
893 894 /* This should not occur */
894 895 port->pa_npkeys = 0;
895 896 port->pa_pkey_tbl = NULL;
896 897 return;
897 898 }
898 899 port->pa_sn_prefix = portinfop->p_sgid_tbl[0].gid_prefix;
899 900
900 901 port->pa_state = portinfop->p_linkstate;
901 902
902 903 /*
903 904 * PKey information in portinfo valid only if port is
904 905 * ACTIVE. Bail out if not.
905 906 */
906 907 if (port->pa_state != IBT_PORT_ACTIVE) {
907 908 port->pa_npkeys = 0;
908 909 port->pa_pkey_tbl = NULL;
909 910 ibt_free_portinfo(portinfop, size);
910 911 return;
911 912 }
912 913
913 914 port->pa_npkeys = portinfop->p_pkey_tbl_sz;
914 915 port->pa_pkey_tbl = (ibdm_pkey_tbl_t *)kmem_zalloc(
915 916 port->pa_npkeys * sizeof (ibdm_pkey_tbl_t), KM_SLEEP);
916 917
917 918 for (pkey_idx = 0; pkey_idx < port->pa_npkeys; pkey_idx++) {
918 919 port->pa_pkey_tbl[pkey_idx].pt_pkey =
919 920 portinfop->p_pkey_tbl[pkey_idx];
920 921 }
921 922 ibt_free_portinfo(portinfop, size);
922 923 }
923 924
924 925
925 926 /*
926 927 * ibdm_handle_hca_attach()
927 928 */
928 929 static void
929 930 ibdm_handle_hca_attach(ib_guid_t hca_guid)
930 931 {
931 932 uint_t size;
932 933 uint_t ii, nports;
933 934 ibt_status_t status;
934 935 ibt_hca_hdl_t hca_hdl;
935 936 ibt_hca_attr_t *hca_attr;
936 937 ibdm_hca_list_t *hca_list, *temp;
937 938 ibdm_port_attr_t *port_attr;
938 939 ibt_hca_portinfo_t *portinfop;
939 940
940 941 IBTF_DPRINTF_L4("ibdm",
941 942 "\thandle_hca_attach: hca_guid = 0x%llX", hca_guid);
942 943
943 944 /* open the HCA first */
944 945 if ((status = ibt_open_hca(ibdm.ibdm_ibt_clnt_hdl, hca_guid,
945 946 &hca_hdl)) != IBT_SUCCESS) {
946 947 IBTF_DPRINTF_L2("ibdm", "\thandle_hca_attach: "
947 948 "open_hca failed, status 0x%x", status);
948 949 return;
949 950 }
950 951
951 952 hca_attr = (ibt_hca_attr_t *)
952 953 kmem_alloc(sizeof (ibt_hca_attr_t), KM_SLEEP);
953 954 /* ibt_query_hca always returns IBT_SUCCESS */
954 955 (void) ibt_query_hca(hca_hdl, hca_attr);
955 956
956 957 IBTF_DPRINTF_L4("ibdm", "\tvid: 0x%x, pid: 0x%x, ver: 0x%x,"
957 958 " #ports: %d", hca_attr->hca_vendor_id, hca_attr->hca_device_id,
958 959 hca_attr->hca_version_id, hca_attr->hca_nports);
959 960
960 961 if ((status = ibt_query_hca_ports(hca_hdl, 0, &portinfop, &nports,
961 962 &size)) != IBT_SUCCESS) {
962 963 IBTF_DPRINTF_L2("ibdm", "\thandle_hca_attach: "
963 964 "ibt_query_hca_ports failed, status 0x%x", status);
↓ open down ↓ |
915 lines elided |
↑ open up ↑ |
964 965 kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
965 966 (void) ibt_close_hca(hca_hdl);
966 967 return;
967 968 }
968 969 hca_list = (ibdm_hca_list_t *)
969 970 kmem_zalloc((sizeof (ibdm_hca_list_t)), KM_SLEEP);
970 971 hca_list->hl_port_attr = (ibdm_port_attr_t *)kmem_zalloc(
971 972 (sizeof (ibdm_port_attr_t) * hca_attr->hca_nports), KM_SLEEP);
972 973 hca_list->hl_hca_guid = hca_attr->hca_node_guid;
973 974 hca_list->hl_nports = hca_attr->hca_nports;
974 - hca_list->hl_attach_time = ddi_get_time();
975 + hca_list->hl_attach_time = gethrtime();
975 976 hca_list->hl_hca_hdl = hca_hdl;
976 977
977 978 /*
978 979 * Init a dummy port attribute for the HCA node
979 980 * This is for Per-HCA Node. Initialize port_attr :
980 981 * hca_guid & port_guid -> hca_guid
981 982 * npkeys, pkey_tbl is NULL
982 983 * port_num, sn_prefix is 0
983 984 * vendorid, product_id, dev_version from HCA
984 985 * pa_state is IBT_PORT_ACTIVE
985 986 */
986 987 hca_list->hl_hca_port_attr = (ibdm_port_attr_t *)kmem_zalloc(
987 988 sizeof (ibdm_port_attr_t), KM_SLEEP);
988 989 port_attr = hca_list->hl_hca_port_attr;
989 990 port_attr->pa_vendorid = hca_attr->hca_vendor_id;
990 991 port_attr->pa_productid = hca_attr->hca_device_id;
991 992 port_attr->pa_dev_version = hca_attr->hca_version_id;
992 993 port_attr->pa_hca_guid = hca_attr->hca_node_guid;
993 994 port_attr->pa_hca_hdl = hca_list->hl_hca_hdl;
994 995 port_attr->pa_port_guid = hca_attr->hca_node_guid;
995 996 port_attr->pa_state = IBT_PORT_ACTIVE;
996 997
997 998
998 999 for (ii = 0; ii < nports; ii++) {
999 1000 port_attr = &hca_list->hl_port_attr[ii];
1000 1001 port_attr->pa_vendorid = hca_attr->hca_vendor_id;
1001 1002 port_attr->pa_productid = hca_attr->hca_device_id;
1002 1003 port_attr->pa_dev_version = hca_attr->hca_version_id;
1003 1004 port_attr->pa_hca_guid = hca_attr->hca_node_guid;
1004 1005 port_attr->pa_hca_hdl = hca_list->hl_hca_hdl;
1005 1006 port_attr->pa_port_guid = portinfop[ii].p_sgid_tbl->gid_guid;
1006 1007 port_attr->pa_sn_prefix = portinfop[ii].p_sgid_tbl->gid_prefix;
1007 1008 port_attr->pa_port_num = portinfop[ii].p_port_num;
1008 1009 port_attr->pa_state = portinfop[ii].p_linkstate;
1009 1010
1010 1011 /*
1011 1012 * Register with IBMF, SA access when the port is in
1012 1013 * ACTIVE state. Also register a callback routine
1013 1014 * with IBMF to receive incoming DM MAD's.
1014 1015 * The IBDM event handler takes care of registration of
1015 1016 * port which are not active.
1016 1017 */
1017 1018 IBTF_DPRINTF_L4("ibdm",
1018 1019 "\thandle_hca_attach: port guid %llx Port state 0x%x",
1019 1020 port_attr->pa_port_guid, portinfop[ii].p_linkstate);
1020 1021
1021 1022 if (portinfop[ii].p_linkstate == IBT_PORT_ACTIVE) {
1022 1023 mutex_enter(&ibdm.ibdm_hl_mutex);
1023 1024 hca_list->hl_nports_active++;
1024 1025 ibdm_initialize_port(port_attr);
1025 1026 cv_broadcast(&ibdm.ibdm_port_settle_cv);
1026 1027 mutex_exit(&ibdm.ibdm_hl_mutex);
1027 1028 }
1028 1029 }
1029 1030 mutex_enter(&ibdm.ibdm_hl_mutex);
1030 1031 for (temp = ibdm.ibdm_hca_list_head; temp; temp = temp->hl_next) {
1031 1032 if (temp->hl_hca_guid == hca_guid) {
1032 1033 IBTF_DPRINTF_L2("ibdm", "hca_attach: HCA %llX "
1033 1034 "already seen by IBDM", hca_guid);
1034 1035 mutex_exit(&ibdm.ibdm_hl_mutex);
1035 1036 (void) ibdm_uninit_hca(hca_list);
1036 1037 return;
1037 1038 }
1038 1039 }
1039 1040 ibdm.ibdm_hca_count++;
1040 1041 if (ibdm.ibdm_hca_list_head == NULL) {
1041 1042 ibdm.ibdm_hca_list_head = hca_list;
1042 1043 ibdm.ibdm_hca_list_tail = hca_list;
1043 1044 } else {
1044 1045 ibdm.ibdm_hca_list_tail->hl_next = hca_list;
1045 1046 ibdm.ibdm_hca_list_tail = hca_list;
1046 1047 }
1047 1048 mutex_exit(&ibdm.ibdm_hl_mutex);
1048 1049 mutex_enter(&ibdm.ibdm_ibnex_mutex);
1049 1050 if (ibdm.ibdm_ibnex_callback != NULL) {
1050 1051 (*ibdm.ibdm_ibnex_callback)((void *)
1051 1052 &hca_guid, IBDM_EVENT_HCA_ADDED);
1052 1053 }
1053 1054 mutex_exit(&ibdm.ibdm_ibnex_mutex);
1054 1055
1055 1056 kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
1056 1057 ibt_free_portinfo(portinfop, size);
1057 1058 }
1058 1059
1059 1060
1060 1061 /*
1061 1062 * ibdm_handle_hca_detach()
1062 1063 */
1063 1064 static void
1064 1065 ibdm_handle_hca_detach(ib_guid_t hca_guid)
1065 1066 {
1066 1067 ibdm_hca_list_t *head, *prev = NULL;
1067 1068 size_t len;
1068 1069 ibdm_dp_gidinfo_t *gidinfo;
1069 1070 ibdm_port_attr_t *port_attr;
1070 1071 int i;
1071 1072
1072 1073 IBTF_DPRINTF_L4("ibdm",
1073 1074 "\thandle_hca_detach: hca_guid = 0x%llx", hca_guid);
1074 1075
1075 1076 /* Make sure no probes are running */
1076 1077 mutex_enter(&ibdm.ibdm_mutex);
1077 1078 while (ibdm.ibdm_busy & IBDM_BUSY)
1078 1079 cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
1079 1080 ibdm.ibdm_busy |= IBDM_BUSY;
1080 1081 mutex_exit(&ibdm.ibdm_mutex);
1081 1082
1082 1083 mutex_enter(&ibdm.ibdm_hl_mutex);
1083 1084 head = ibdm.ibdm_hca_list_head;
1084 1085 while (head) {
1085 1086 if (head->hl_hca_guid == hca_guid) {
1086 1087 if (prev == NULL)
1087 1088 ibdm.ibdm_hca_list_head = head->hl_next;
1088 1089 else
1089 1090 prev->hl_next = head->hl_next;
1090 1091 if (ibdm.ibdm_hca_list_tail == head)
1091 1092 ibdm.ibdm_hca_list_tail = prev;
1092 1093 ibdm.ibdm_hca_count--;
1093 1094 break;
1094 1095 }
1095 1096 prev = head;
1096 1097 head = head->hl_next;
1097 1098 }
1098 1099 mutex_exit(&ibdm.ibdm_hl_mutex);
1099 1100 if (ibdm_uninit_hca(head) != IBDM_SUCCESS)
1100 1101 (void) ibdm_handle_hca_attach(hca_guid);
1101 1102
1102 1103 #ifdef DEBUG
1103 1104 if (ibdm_enumerate_iocs == 0) {
1104 1105 ASSERT(ibdm.ibdm_dp_gidlist_head == NULL);
1105 1106 }
1106 1107 #endif
1107 1108
1108 1109 /*
1109 1110 * Now clean up the HCA lists in the gidlist.
1110 1111 */
1111 1112 for (gidinfo = ibdm.ibdm_dp_gidlist_head; gidinfo; gidinfo =
1112 1113 gidinfo->gl_next) {
1113 1114 prev = NULL;
1114 1115 head = gidinfo->gl_hca_list;
1115 1116 while (head) {
1116 1117 if (head->hl_hca_guid == hca_guid) {
1117 1118 if (prev == NULL)
1118 1119 gidinfo->gl_hca_list =
1119 1120 head->hl_next;
1120 1121 else
1121 1122 prev->hl_next = head->hl_next;
1122 1123 for (i = 0; i < head->hl_nports; i++) {
1123 1124 port_attr = &head->hl_port_attr[i];
1124 1125 if (port_attr->pa_pkey_tbl != NULL)
1125 1126 kmem_free(
1126 1127 port_attr->pa_pkey_tbl,
1127 1128 port_attr->pa_npkeys *
1128 1129 sizeof (ibdm_pkey_tbl_t));
1129 1130 }
1130 1131 len = sizeof (ibdm_hca_list_t) +
1131 1132 (head->hl_nports *
1132 1133 sizeof (ibdm_port_attr_t));
1133 1134 kmem_free(head, len);
1134 1135
1135 1136 break;
1136 1137 }
1137 1138 prev = head;
1138 1139 head = head->hl_next;
1139 1140 }
1140 1141 }
1141 1142
1142 1143 mutex_enter(&ibdm.ibdm_mutex);
1143 1144 ibdm.ibdm_busy &= ~IBDM_BUSY;
1144 1145 cv_broadcast(&ibdm.ibdm_busy_cv);
1145 1146 mutex_exit(&ibdm.ibdm_mutex);
1146 1147 }
1147 1148
1148 1149
1149 1150 static int
1150 1151 ibdm_uninit_hca(ibdm_hca_list_t *head)
1151 1152 {
1152 1153 int ii;
1153 1154 ibdm_port_attr_t *port_attr;
1154 1155
1155 1156 for (ii = 0; ii < head->hl_nports; ii++) {
1156 1157 port_attr = &head->hl_port_attr[ii];
1157 1158 if (ibdm_fini_port(port_attr) != IBDM_SUCCESS) {
1158 1159 IBTF_DPRINTF_L2("ibdm", "uninit_hca: HCA %p port 0x%x "
1159 1160 "ibdm_fini_port() failed", head, ii);
1160 1161 return (IBDM_FAILURE);
1161 1162 }
1162 1163 }
1163 1164 if (head->hl_hca_hdl)
1164 1165 if (ibt_close_hca(head->hl_hca_hdl) != IBT_SUCCESS) {
1165 1166 IBTF_DPRINTF_L2("ibdm", "uninit_hca: "
1166 1167 "ibt_close_hca() failed");
1167 1168 return (IBDM_FAILURE);
1168 1169 }
1169 1170 kmem_free(head->hl_port_attr,
1170 1171 head->hl_nports * sizeof (ibdm_port_attr_t));
1171 1172 kmem_free(head->hl_hca_port_attr, sizeof (ibdm_port_attr_t));
1172 1173 kmem_free(head, sizeof (ibdm_hca_list_t));
1173 1174 return (IBDM_SUCCESS);
1174 1175 }
1175 1176
1176 1177
1177 1178 /*
1178 1179 * For each port on the HCA,
1179 1180 * 1) Teardown IBMF receive callback function
1180 1181 * 2) Unregister with IBMF
1181 1182 * 3) Unregister with SA access
1182 1183 */
1183 1184 static int
1184 1185 ibdm_fini_port(ibdm_port_attr_t *port_attr)
1185 1186 {
1186 1187 int ii, ibmf_status;
1187 1188
1188 1189 for (ii = 0; ii < port_attr->pa_npkeys; ii++) {
1189 1190 if (port_attr->pa_pkey_tbl == NULL)
1190 1191 break;
1191 1192 if (!port_attr->pa_pkey_tbl[ii].pt_qp_hdl)
1192 1193 continue;
1193 1194 if (ibdm_port_attr_ibmf_fini(port_attr, ii) != IBDM_SUCCESS) {
1194 1195 IBTF_DPRINTF_L4("ibdm", "\tfini_port: "
1195 1196 "ibdm_port_attr_ibmf_fini failed for "
1196 1197 "port pkey 0x%x", ii);
1197 1198 return (IBDM_FAILURE);
1198 1199 }
1199 1200 }
1200 1201
1201 1202 if (port_attr->pa_ibmf_hdl) {
1202 1203 ibmf_status = ibmf_tear_down_async_cb(port_attr->pa_ibmf_hdl,
1203 1204 IBMF_QP_HANDLE_DEFAULT, 0);
1204 1205 if (ibmf_status != IBMF_SUCCESS) {
1205 1206 IBTF_DPRINTF_L4("ibdm", "\tfini_port: "
1206 1207 "ibmf_tear_down_async_cb failed %d", ibmf_status);
1207 1208 return (IBDM_FAILURE);
1208 1209 }
1209 1210
1210 1211 ibmf_status = ibmf_unregister(&port_attr->pa_ibmf_hdl, 0);
1211 1212 if (ibmf_status != IBMF_SUCCESS) {
1212 1213 IBTF_DPRINTF_L2("ibdm", "\tfini_port: "
1213 1214 "ibmf_unregister failed %d", ibmf_status);
1214 1215 return (IBDM_FAILURE);
1215 1216 }
1216 1217
1217 1218 port_attr->pa_ibmf_hdl = NULL;
1218 1219 }
1219 1220
1220 1221 if (port_attr->pa_sa_hdl) {
1221 1222 ibmf_status = ibmf_sa_session_close(&port_attr->pa_sa_hdl, 0);
1222 1223 if (ibmf_status != IBMF_SUCCESS) {
1223 1224 IBTF_DPRINTF_L2("ibdm", "\tfini_port: "
1224 1225 "ibmf_sa_session_close failed %d", ibmf_status);
1225 1226 return (IBDM_FAILURE);
1226 1227 }
1227 1228 port_attr->pa_sa_hdl = NULL;
1228 1229 }
1229 1230
1230 1231 if (port_attr->pa_pkey_tbl != NULL) {
1231 1232 kmem_free(port_attr->pa_pkey_tbl,
1232 1233 port_attr->pa_npkeys * sizeof (ibdm_pkey_tbl_t));
1233 1234 port_attr->pa_pkey_tbl = NULL;
1234 1235 port_attr->pa_npkeys = 0;
1235 1236 }
1236 1237
1237 1238 return (IBDM_SUCCESS);
1238 1239 }
1239 1240
1240 1241
1241 1242 /*
1242 1243 * ibdm_port_attr_ibmf_fini:
1243 1244 * With IBMF - Tear down Async callback and free QP Handle
1244 1245 */
1245 1246 static int
1246 1247 ibdm_port_attr_ibmf_fini(ibdm_port_attr_t *port_attr, int ii)
1247 1248 {
1248 1249 int ibmf_status;
1249 1250
1250 1251 IBTF_DPRINTF_L5("ibdm", "\tport_attr_ibmf_fini:");
1251 1252
1252 1253 if (ibdm_enumerate_iocs == 0) {
1253 1254 ASSERT(port_attr->pa_pkey_tbl[ii].pt_qp_hdl == NULL);
1254 1255 return (IBDM_SUCCESS);
1255 1256 }
1256 1257
1257 1258 if (port_attr->pa_pkey_tbl[ii].pt_qp_hdl) {
1258 1259 ibmf_status = ibmf_tear_down_async_cb(port_attr->pa_ibmf_hdl,
1259 1260 port_attr->pa_pkey_tbl[ii].pt_qp_hdl, 0);
1260 1261 if (ibmf_status != IBMF_SUCCESS) {
1261 1262 IBTF_DPRINTF_L4("ibdm", "\tport_attr_ibmf_fini: "
1262 1263 "ibmf_tear_down_async_cb failed %d", ibmf_status);
1263 1264 return (IBDM_FAILURE);
1264 1265 }
1265 1266 ibmf_status = ibmf_free_qp(port_attr->pa_ibmf_hdl,
1266 1267 &port_attr->pa_pkey_tbl[ii].pt_qp_hdl, 0);
1267 1268 if (ibmf_status != IBMF_SUCCESS) {
1268 1269 IBTF_DPRINTF_L4("ibdm", "\tport_attr_ibmf_fini: "
1269 1270 "ibmf_free_qp failed %d", ibmf_status);
1270 1271 return (IBDM_FAILURE);
1271 1272 }
1272 1273 port_attr->pa_pkey_tbl[ii].pt_qp_hdl = NULL;
1273 1274 }
1274 1275 return (IBDM_SUCCESS);
1275 1276 }
1276 1277
1277 1278
1278 1279 /*
1279 1280 * ibdm_gid_decr_pending:
1280 1281 * decrement gl_pending_cmds. If zero wakeup sleeping threads
1281 1282 */
1282 1283 static void
1283 1284 ibdm_gid_decr_pending(ibdm_dp_gidinfo_t *gidinfo)
1284 1285 {
1285 1286 mutex_enter(&ibdm.ibdm_mutex);
1286 1287 mutex_enter(&gidinfo->gl_mutex);
1287 1288 if (--gidinfo->gl_pending_cmds == 0) {
1288 1289 /*
1289 1290 * Handle DGID getting removed.
1290 1291 */
1291 1292 if (gidinfo->gl_disconnected) {
1292 1293 mutex_exit(&gidinfo->gl_mutex);
1293 1294 mutex_exit(&ibdm.ibdm_mutex);
1294 1295
1295 1296 IBTF_DPRINTF_L3(ibdm_string, "\tgid_decr_pending: "
1296 1297 "gidinfo %p hot removal", gidinfo);
1297 1298 ibdm_delete_gidinfo(gidinfo);
1298 1299
1299 1300 mutex_enter(&ibdm.ibdm_mutex);
1300 1301 ibdm.ibdm_ngid_probes_in_progress--;
1301 1302 ibdm_wait_probe_completion();
1302 1303 mutex_exit(&ibdm.ibdm_mutex);
1303 1304 return;
1304 1305 }
1305 1306 mutex_exit(&gidinfo->gl_mutex);
1306 1307 mutex_exit(&ibdm.ibdm_mutex);
1307 1308 ibdm_notify_newgid_iocs(gidinfo);
1308 1309 mutex_enter(&ibdm.ibdm_mutex);
1309 1310 mutex_enter(&gidinfo->gl_mutex);
1310 1311
1311 1312 ibdm.ibdm_ngid_probes_in_progress--;
1312 1313 ibdm_wait_probe_completion();
1313 1314 }
1314 1315 mutex_exit(&gidinfo->gl_mutex);
1315 1316 mutex_exit(&ibdm.ibdm_mutex);
1316 1317 }
1317 1318
1318 1319
1319 1320 /*
1320 1321 * ibdm_wait_probe_completion:
1321 1322 * wait for probing to complete
1322 1323 */
1323 1324 static void
1324 1325 ibdm_wait_probe_completion(void)
1325 1326 {
1326 1327 ASSERT(MUTEX_HELD(&ibdm.ibdm_mutex));
1327 1328 if (ibdm.ibdm_ngid_probes_in_progress) {
1328 1329 IBTF_DPRINTF_L4("ibdm", "\twait for probe complete");
1329 1330 ibdm.ibdm_busy |= IBDM_PROBE_IN_PROGRESS;
1330 1331 while (ibdm.ibdm_busy & IBDM_PROBE_IN_PROGRESS)
1331 1332 cv_wait(&ibdm.ibdm_probe_cv, &ibdm.ibdm_mutex);
1332 1333 }
1333 1334 }
1334 1335
1335 1336
1336 1337 /*
1337 1338 * ibdm_wait_cisco_probe_completion:
1338 1339 * wait for the reply from the Cisco FC GW switch after a setclassportinfo
1339 1340 * request is sent. This wait can be achieved on each gid.
1340 1341 */
1341 1342 static void
1342 1343 ibdm_wait_cisco_probe_completion(ibdm_dp_gidinfo_t *gidinfo)
1343 1344 {
1344 1345 ASSERT(MUTEX_HELD(&gidinfo->gl_mutex));
1345 1346 IBTF_DPRINTF_L4("ibdm", "\twait for cisco probe complete");
1346 1347 gidinfo->gl_flag |= IBDM_CISCO_PROBE;
1347 1348 while (gidinfo->gl_flag & IBDM_CISCO_PROBE)
1348 1349 cv_wait(&gidinfo->gl_probe_cv, &gidinfo->gl_mutex);
1349 1350 }
1350 1351
1351 1352
1352 1353 /*
1353 1354 * ibdm_wakeup_probe_gid_cv:
1354 1355 * wakeup waiting threads (based on ibdm_ngid_probes_in_progress)
1355 1356 */
1356 1357 static void
1357 1358 ibdm_wakeup_probe_gid_cv(void)
1358 1359 {
1359 1360 ASSERT(MUTEX_HELD(&ibdm.ibdm_mutex));
1360 1361 if (!ibdm.ibdm_ngid_probes_in_progress) {
1361 1362 IBTF_DPRINTF_L4("ibdm", "wakeup_probe_gid_thread: Wakeup");
1362 1363 ibdm.ibdm_busy &= ~IBDM_PROBE_IN_PROGRESS;
1363 1364 cv_broadcast(&ibdm.ibdm_probe_cv);
1364 1365 }
1365 1366
1366 1367 }
1367 1368
1368 1369
1369 1370 /*
1370 1371 * ibdm_sweep_fabric(reprobe_flag)
1371 1372 * Find all possible Managed IOU's and their IOC's that are visible
1372 1373 * to the host. The algorithm used is as follows
1373 1374 *
1374 1375 * Send a "bus walk" request for each port on the host HCA to SA access
1375 1376 * SA returns complete set of GID's that are reachable from
1376 1377 * source port. This is done in parallel.
1377 1378 *
1378 1379 * Initialize GID state to IBDM_GID_PROBE_NOT_DONE
1379 1380 *
1380 1381 * Sort the GID list and eliminate duplicate GID's
1381 1382 * 1) Use DGID for sorting
1382 1383 * 2) use PortGuid for sorting
1383 1384 * Send SA query to retrieve NodeRecord and
1384 1385 * extract PortGuid from that.
1385 1386 *
1386 1387 * Set GID state to IBDM_GID_PROBE_FAILED to all the ports that dont
1387 1388 * support DM MAD's
1388 1389 * Send a "Portinfo" query to get the port capabilities and
1389 1390 * then check for DM MAD's support
1390 1391 *
1391 1392 * Send "ClassPortInfo" request for all the GID's in parallel,
1392 1393 * set the GID state to IBDM_GET_CLASSPORTINFO and wait on the
1393 1394 * cv_signal to complete.
1394 1395 *
1395 1396 * When DM agent on the remote GID sends back the response, IBMF
1396 1397 * invokes DM callback routine.
1397 1398 *
1398 1399 * If the response is proper, send "IOUnitInfo" request and set
1399 1400 * GID state to IBDM_GET_IOUNITINFO.
1400 1401 *
1401 1402 * If the response is proper, send "IocProfileInfo" request to
1402 1403 * all the IOC simultaneously and set GID state to IBDM_GET_IOC_DETAILS.
1403 1404 *
1404 1405 * Send request to get Service entries simultaneously
1405 1406 *
1406 1407 * Signal the waiting thread when received response for all the commands.
1407 1408 *
1408 1409 * Set the GID state to IBDM_GID_PROBE_FAILED when received a error
1409 1410 * response during the probing period.
1410 1411 *
1411 1412 * Note:
1412 1413 * ibdm.ibdm_ngid_probes_in_progress and ibdm_gid_list_t:gl_pending_cmds
1413 1414 * keep track of number commands in progress at any point of time.
1414 1415 * MAD transaction ID is used to identify a particular GID
1415 1416 * TBD: Consider registering the IBMF receive callback on demand
1416 1417 *
1417 1418 * Note: This routine must be called with ibdm.ibdm_mutex held
1418 1419 * TBD: Re probe the failure GID (for certain failures) when requested
1419 1420 * for fabric sweep next time
1420 1421 *
1421 1422 * Parameters : If reprobe_flag is set, All IOCs will be reprobed.
1422 1423 */
1423 1424 static void
1424 1425 ibdm_sweep_fabric(int reprobe_flag)
1425 1426 {
1426 1427 int ii;
1427 1428 int new_paths = 0;
1428 1429 uint8_t niocs;
1429 1430 taskqid_t tid;
1430 1431 ibdm_ioc_info_t *ioc;
1431 1432 ibdm_hca_list_t *hca_list = NULL;
1432 1433 ibdm_port_attr_t *port = NULL;
1433 1434 ibdm_dp_gidinfo_t *gid_info;
1434 1435
1435 1436 IBTF_DPRINTF_L4("ibdm", "\tsweep_fabric: Enter");
1436 1437 ASSERT(MUTEX_HELD(&ibdm.ibdm_mutex));
1437 1438
1438 1439 /*
1439 1440 * Check whether a sweep already in progress. If so, just
1440 1441 * wait for the fabric sweep to complete
1441 1442 */
1442 1443 while (ibdm.ibdm_busy & IBDM_BUSY)
1443 1444 cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
1444 1445 ibdm.ibdm_busy |= IBDM_BUSY;
1445 1446 mutex_exit(&ibdm.ibdm_mutex);
1446 1447
1447 1448 ibdm_dump_sweep_fabric_timestamp(0);
1448 1449
1449 1450 /* Rescan the GID list for any removed GIDs for reprobe */
1450 1451 if (reprobe_flag)
1451 1452 ibdm_rescan_gidlist(NULL);
1452 1453
1453 1454 /*
1454 1455 * Get list of all the ports reachable from the local known HCA
1455 1456 * ports which are active
1456 1457 */
1457 1458 mutex_enter(&ibdm.ibdm_hl_mutex);
1458 1459 for (ibdm_get_next_port(&hca_list, &port, 1); port;
1459 1460 ibdm_get_next_port(&hca_list, &port, 1)) {
1460 1461 /*
1461 1462 * Get PATHS to all the reachable ports from
1462 1463 * SGID and update the global ibdm structure.
1463 1464 */
1464 1465 new_paths = ibdm_get_reachable_ports(port, hca_list);
1465 1466 ibdm.ibdm_ngids += new_paths;
1466 1467 }
1467 1468 mutex_exit(&ibdm.ibdm_hl_mutex);
1468 1469
1469 1470 mutex_enter(&ibdm.ibdm_mutex);
1470 1471 ibdm.ibdm_ngid_probes_in_progress += ibdm.ibdm_ngids;
1471 1472 mutex_exit(&ibdm.ibdm_mutex);
1472 1473
1473 1474 /* Send a request to probe GIDs asynchronously. */
1474 1475 for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info;
1475 1476 gid_info = gid_info->gl_next) {
1476 1477 mutex_enter(&gid_info->gl_mutex);
1477 1478 gid_info->gl_reprobe_flag = reprobe_flag;
1478 1479 mutex_exit(&gid_info->gl_mutex);
1479 1480
1480 1481 /* process newly encountered GIDs */
1481 1482 tid = taskq_dispatch(system_taskq, ibdm_probe_gid_thread,
1482 1483 (void *)gid_info, TQ_NOSLEEP);
1483 1484 IBTF_DPRINTF_L4("ibdm", "\tsweep_fabric: gid_info = %p"
1484 1485 " taskq_id = %x", gid_info, tid);
1485 1486 /* taskq failed to dispatch call it directly */
1486 1487 if (tid == NULL)
1487 1488 ibdm_probe_gid_thread((void *)gid_info);
1488 1489 }
1489 1490
1490 1491 mutex_enter(&ibdm.ibdm_mutex);
1491 1492 ibdm_wait_probe_completion();
1492 1493
1493 1494 /*
1494 1495 * Update the properties, if reprobe_flag is set
1495 1496 * Skip if gl_reprobe_flag is set, this will be
1496 1497 * a re-inserted / new GID, for which notifications
1497 1498 * have already been send.
1498 1499 */
1499 1500 if (reprobe_flag) {
1500 1501 for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info;
1501 1502 gid_info = gid_info->gl_next) {
1502 1503 if (gid_info->gl_iou == NULL)
1503 1504 continue;
1504 1505 if (gid_info->gl_reprobe_flag) {
1505 1506 gid_info->gl_reprobe_flag = 0;
1506 1507 continue;
1507 1508 }
1508 1509
1509 1510 niocs = gid_info->gl_iou->iou_info.iou_num_ctrl_slots;
1510 1511 for (ii = 0; ii < niocs; ii++) {
1511 1512 ioc = IBDM_GIDINFO2IOCINFO(gid_info, ii);
1512 1513 if (ioc)
1513 1514 ibdm_reprobe_update_port_srv(ioc,
1514 1515 gid_info);
1515 1516 }
1516 1517 }
1517 1518 } else if (ibdm.ibdm_prev_iou) {
1518 1519 ibdm_ioc_info_t *ioc_list;
1519 1520
1520 1521 /*
1521 1522 * Get the list of IOCs which have changed.
1522 1523 * If any IOCs have changed, Notify IBNexus
1523 1524 */
1524 1525 ibdm.ibdm_prev_iou = 0;
1525 1526 ioc_list = ibdm_handle_prev_iou();
1526 1527 if (ioc_list) {
1527 1528 if (ibdm.ibdm_ibnex_callback != NULL) {
1528 1529 (*ibdm.ibdm_ibnex_callback)(
1529 1530 (void *)ioc_list,
1530 1531 IBDM_EVENT_IOC_PROP_UPDATE);
1531 1532 }
1532 1533 }
1533 1534 }
1534 1535
1535 1536 ibdm_dump_sweep_fabric_timestamp(1);
1536 1537
1537 1538 ibdm.ibdm_busy &= ~IBDM_BUSY;
1538 1539 cv_broadcast(&ibdm.ibdm_busy_cv);
1539 1540 IBTF_DPRINTF_L5("ibdm", "\tsweep_fabric: EXIT");
1540 1541 }
1541 1542
1542 1543
1543 1544 /*
1544 1545 * ibdm_is_cisco:
1545 1546 * Check if this is a Cisco device or not.
1546 1547 */
1547 1548 static boolean_t
1548 1549 ibdm_is_cisco(ib_guid_t guid)
1549 1550 {
1550 1551 if ((guid >> IBDM_OUI_GUID_SHIFT) == IBDM_CISCO_COMPANY_ID)
1551 1552 return (B_TRUE);
1552 1553 return (B_FALSE);
1553 1554 }
1554 1555
1555 1556
1556 1557 /*
1557 1558 * ibdm_is_cisco_switch:
1558 1559 * Check if this switch is a CISCO switch or not.
1559 1560 * Note that if this switch is already activated, ibdm_is_cisco_switch()
1560 1561 * returns B_FALSE not to re-activate it again.
1561 1562 */
1562 1563 static boolean_t
1563 1564 ibdm_is_cisco_switch(ibdm_dp_gidinfo_t *gid_info)
1564 1565 {
1565 1566 int company_id, device_id;
1566 1567 ASSERT(gid_info != 0);
1567 1568 ASSERT(MUTEX_HELD(&gid_info->gl_mutex));
1568 1569
1569 1570 /*
1570 1571 * If this switch is already activated, don't re-activate it.
1571 1572 */
1572 1573 if (gid_info->gl_flag & IBDM_CISCO_PROBE_DONE)
1573 1574 return (B_FALSE);
1574 1575
1575 1576 /*
1576 1577 * Check if this switch is a Cisco FC GW or not.
1577 1578 * Use the node guid (the OUI part) instead of the vendor id
1578 1579 * since the vendor id is zero in practice.
1579 1580 */
1580 1581 company_id = gid_info->gl_nodeguid >> IBDM_OUI_GUID_SHIFT;
1581 1582 device_id = gid_info->gl_devid;
1582 1583
1583 1584 if (company_id == IBDM_CISCO_COMPANY_ID &&
1584 1585 device_id == IBDM_CISCO_DEVICE_ID)
1585 1586 return (B_TRUE);
1586 1587 return (B_FALSE);
1587 1588 }
1588 1589
1589 1590
1590 1591 /*
1591 1592 * ibdm_probe_gid_thread:
1592 1593 * thread that does the actual work for sweeping the fabric
1593 1594 * for a given GID
1594 1595 */
1595 1596 static void
1596 1597 ibdm_probe_gid_thread(void *args)
1597 1598 {
1598 1599 int reprobe_flag;
1599 1600 ib_guid_t node_guid;
1600 1601 ib_guid_t port_guid;
1601 1602 ibdm_dp_gidinfo_t *gid_info;
1602 1603
1603 1604 gid_info = (ibdm_dp_gidinfo_t *)args;
1604 1605 reprobe_flag = gid_info->gl_reprobe_flag;
1605 1606 IBTF_DPRINTF_L4("ibdm", "\tprobe_gid_thread: gid_info = %p, flag = %d",
1606 1607 gid_info, reprobe_flag);
1607 1608 ASSERT(gid_info != NULL);
1608 1609 ASSERT(gid_info->gl_pending_cmds == 0);
1609 1610
1610 1611 if (gid_info->gl_state != IBDM_GID_PROBE_NOT_DONE &&
1611 1612 reprobe_flag == 0) {
1612 1613 /*
1613 1614 * This GID may have been already probed. Send
1614 1615 * in a CLP to check if IOUnitInfo changed?
1615 1616 * Explicitly set gl_reprobe_flag to 0 so that
1616 1617 * IBnex is not notified on completion
1617 1618 */
1618 1619 if (gid_info->gl_state == IBDM_GID_PROBING_COMPLETE) {
1619 1620 IBTF_DPRINTF_L4("ibdm", "\tprobe_gid_thread: "
1620 1621 "get new IOCs information");
1621 1622 mutex_enter(&gid_info->gl_mutex);
1622 1623 gid_info->gl_pending_cmds++;
1623 1624 gid_info->gl_state = IBDM_GET_IOUNITINFO;
1624 1625 gid_info->gl_reprobe_flag = 0;
1625 1626 mutex_exit(&gid_info->gl_mutex);
1626 1627 if (ibdm_send_iounitinfo(gid_info) != IBDM_SUCCESS) {
1627 1628 mutex_enter(&gid_info->gl_mutex);
1628 1629 --gid_info->gl_pending_cmds;
1629 1630 mutex_exit(&gid_info->gl_mutex);
1630 1631 mutex_enter(&ibdm.ibdm_mutex);
1631 1632 --ibdm.ibdm_ngid_probes_in_progress;
1632 1633 ibdm_wakeup_probe_gid_cv();
1633 1634 mutex_exit(&ibdm.ibdm_mutex);
1634 1635 }
1635 1636 } else {
1636 1637 mutex_enter(&ibdm.ibdm_mutex);
1637 1638 --ibdm.ibdm_ngid_probes_in_progress;
1638 1639 ibdm_wakeup_probe_gid_cv();
1639 1640 mutex_exit(&ibdm.ibdm_mutex);
1640 1641 }
1641 1642 return;
1642 1643 } else if (reprobe_flag && gid_info->gl_state ==
1643 1644 IBDM_GID_PROBING_COMPLETE) {
1644 1645 /*
1645 1646 * Reprobe all IOCs for the GID which has completed
1646 1647 * probe. Skip other port GIDs to same IOU.
1647 1648 * Explicitly set gl_reprobe_flag to 0 so that
1648 1649 * IBnex is not notified on completion
1649 1650 */
1650 1651 ibdm_ioc_info_t *ioc_info;
1651 1652 uint8_t niocs, ii;
1652 1653
1653 1654 ASSERT(gid_info->gl_iou);
1654 1655 mutex_enter(&gid_info->gl_mutex);
1655 1656 niocs = gid_info->gl_iou->iou_info.iou_num_ctrl_slots;
1656 1657 gid_info->gl_state = IBDM_GET_IOC_DETAILS;
1657 1658 gid_info->gl_pending_cmds += niocs;
1658 1659 gid_info->gl_reprobe_flag = 0;
1659 1660 mutex_exit(&gid_info->gl_mutex);
1660 1661 for (ii = 0; ii < niocs; ii++) {
1661 1662 uchar_t slot_info;
1662 1663 ib_dm_io_unitinfo_t *giou_info;
1663 1664
1664 1665 /*
1665 1666 * Check whether IOC is present in the slot
1666 1667 * Series of nibbles (in the field
1667 1668 * iou_ctrl_list) represents a slot in the
1668 1669 * IOU.
1669 1670 * Byte format: 76543210
1670 1671 * Bits 0-3 of first byte represent Slot 2
1671 1672 * bits 4-7 of first byte represent slot 1,
1672 1673 * bits 0-3 of second byte represent slot 4
1673 1674 * and so on
1674 1675 * Each 4-bit nibble has the following meaning
1675 1676 * 0x0 : IOC not installed
1676 1677 * 0x1 : IOC is present
1677 1678 * 0xf : Slot does not exist
1678 1679 * and all other values are reserved.
1679 1680 */
1680 1681 ioc_info = IBDM_GIDINFO2IOCINFO(gid_info, ii);
1681 1682 giou_info = &gid_info->gl_iou->iou_info;
1682 1683 slot_info = giou_info->iou_ctrl_list[(ii/2)];
1683 1684 if ((ii % 2) == 0)
1684 1685 slot_info = (slot_info >> 4);
1685 1686
1686 1687 if ((slot_info & 0xf) != 1) {
1687 1688 ioc_info->ioc_state =
1688 1689 IBDM_IOC_STATE_PROBE_FAILED;
1689 1690 ibdm_gid_decr_pending(gid_info);
1690 1691 continue;
1691 1692 }
1692 1693
1693 1694 if (ibdm_send_ioc_profile(gid_info, ii) !=
1694 1695 IBDM_SUCCESS) {
1695 1696 ibdm_gid_decr_pending(gid_info);
1696 1697 }
1697 1698 }
1698 1699
1699 1700 return;
1700 1701 } else if (gid_info->gl_state != IBDM_GID_PROBE_NOT_DONE) {
1701 1702 mutex_enter(&ibdm.ibdm_mutex);
1702 1703 --ibdm.ibdm_ngid_probes_in_progress;
1703 1704 ibdm_wakeup_probe_gid_cv();
1704 1705 mutex_exit(&ibdm.ibdm_mutex);
1705 1706 return;
1706 1707 }
1707 1708
1708 1709 /*
1709 1710 * Check whether the destination GID supports DM agents. If
1710 1711 * not, stop probing the GID and continue with the next GID
1711 1712 * in the list.
1712 1713 */
1713 1714 if (ibdm_is_dev_mgt_supported(gid_info) != IBDM_SUCCESS) {
1714 1715 mutex_enter(&gid_info->gl_mutex);
1715 1716 gid_info->gl_state = IBDM_GID_PROBING_FAILED;
1716 1717 gid_info->gl_is_dm_capable = B_FALSE;
1717 1718 mutex_exit(&gid_info->gl_mutex);
1718 1719 ibdm_delete_glhca_list(gid_info);
1719 1720 mutex_enter(&ibdm.ibdm_mutex);
1720 1721 --ibdm.ibdm_ngid_probes_in_progress;
1721 1722 ibdm_wakeup_probe_gid_cv();
1722 1723 mutex_exit(&ibdm.ibdm_mutex);
1723 1724 return;
1724 1725 }
1725 1726
1726 1727 /*
1727 1728 * This GID is Device management capable
1728 1729 */
1729 1730 mutex_enter(&gid_info->gl_mutex);
1730 1731 gid_info->gl_is_dm_capable = B_TRUE;
1731 1732 mutex_exit(&gid_info->gl_mutex);
1732 1733
1733 1734 /* Get the nodeguid and portguid of the port */
1734 1735 if (ibdm_get_node_port_guids(gid_info->gl_sa_hdl, gid_info->gl_dlid,
1735 1736 &node_guid, &port_guid) != IBDM_SUCCESS) {
1736 1737 mutex_enter(&gid_info->gl_mutex);
1737 1738 gid_info->gl_state = IBDM_GID_PROBING_FAILED;
1738 1739 mutex_exit(&gid_info->gl_mutex);
1739 1740 ibdm_delete_glhca_list(gid_info);
1740 1741 mutex_enter(&ibdm.ibdm_mutex);
1741 1742 --ibdm.ibdm_ngid_probes_in_progress;
1742 1743 ibdm_wakeup_probe_gid_cv();
1743 1744 mutex_exit(&ibdm.ibdm_mutex);
1744 1745 return;
1745 1746 }
1746 1747
1747 1748 /*
1748 1749 * Check whether we already knew about this NodeGuid
1749 1750 * If so, do not probe the GID and continue with the
1750 1751 * next GID in the gid list. Set the GID state to
1751 1752 * probing done.
1752 1753 */
1753 1754 mutex_enter(&ibdm.ibdm_mutex);
1754 1755 gid_info->gl_nodeguid = node_guid;
1755 1756 gid_info->gl_portguid = port_guid;
1756 1757 if (ibdm_check_dest_nodeguid(gid_info) != NULL) {
1757 1758 mutex_exit(&ibdm.ibdm_mutex);
1758 1759 mutex_enter(&gid_info->gl_mutex);
1759 1760 gid_info->gl_state = IBDM_GID_PROBING_SKIPPED;
1760 1761 mutex_exit(&gid_info->gl_mutex);
1761 1762 ibdm_delete_glhca_list(gid_info);
1762 1763 mutex_enter(&ibdm.ibdm_mutex);
1763 1764 --ibdm.ibdm_ngid_probes_in_progress;
1764 1765 ibdm_wakeup_probe_gid_cv();
1765 1766 mutex_exit(&ibdm.ibdm_mutex);
1766 1767 return;
1767 1768 }
1768 1769 ibdm_add_to_gl_gid(gid_info, gid_info);
1769 1770 mutex_exit(&ibdm.ibdm_mutex);
1770 1771
1771 1772 /*
1772 1773 * New or reinserted GID : Enable notification to IBnex
1773 1774 */
1774 1775 mutex_enter(&gid_info->gl_mutex);
1775 1776 gid_info->gl_reprobe_flag = 1;
1776 1777
1777 1778 /*
1778 1779 * A Cisco FC GW needs the special handling to get IOUnitInfo.
1779 1780 */
1780 1781 if (ibdm_is_cisco_switch(gid_info)) {
1781 1782 gid_info->gl_pending_cmds++;
1782 1783 gid_info->gl_state = IBDM_SET_CLASSPORTINFO;
1783 1784 mutex_exit(&gid_info->gl_mutex);
1784 1785
1785 1786 if (ibdm_set_classportinfo(gid_info) != IBDM_SUCCESS) {
1786 1787 mutex_enter(&gid_info->gl_mutex);
1787 1788 gid_info->gl_state = IBDM_GID_PROBING_FAILED;
1788 1789 --gid_info->gl_pending_cmds;
1789 1790 mutex_exit(&gid_info->gl_mutex);
1790 1791
1791 1792 /* free the hca_list on this gid_info */
1792 1793 ibdm_delete_glhca_list(gid_info);
1793 1794
1794 1795 mutex_enter(&ibdm.ibdm_mutex);
1795 1796 --ibdm.ibdm_ngid_probes_in_progress;
1796 1797 ibdm_wakeup_probe_gid_cv();
1797 1798 mutex_exit(&ibdm.ibdm_mutex);
1798 1799
1799 1800 return;
1800 1801 }
1801 1802
1802 1803 mutex_enter(&gid_info->gl_mutex);
1803 1804 ibdm_wait_cisco_probe_completion(gid_info);
1804 1805
1805 1806 IBTF_DPRINTF_L4("ibdm", "\tibdm_probe_gid_thread: "
1806 1807 "CISCO Wakeup signal received");
1807 1808 }
1808 1809
1809 1810 /* move on to the 'GET_CLASSPORTINFO' stage */
1810 1811 gid_info->gl_pending_cmds++;
1811 1812 gid_info->gl_state = IBDM_GET_CLASSPORTINFO;
1812 1813 mutex_exit(&gid_info->gl_mutex);
1813 1814
1814 1815 IBTF_DPRINTF_L3(ibdm_string, "\tibdm_probe_gid_thread: "
1815 1816 "%d: gid_info %p gl_state %d pending_cmds %d",
1816 1817 __LINE__, gid_info, gid_info->gl_state,
1817 1818 gid_info->gl_pending_cmds);
1818 1819
1819 1820 /*
1820 1821 * Send ClassPortInfo request to the GID asynchronously.
1821 1822 */
1822 1823 if (ibdm_send_classportinfo(gid_info) != IBDM_SUCCESS) {
1823 1824
1824 1825 mutex_enter(&gid_info->gl_mutex);
1825 1826 gid_info->gl_state = IBDM_GID_PROBING_FAILED;
1826 1827 --gid_info->gl_pending_cmds;
1827 1828 mutex_exit(&gid_info->gl_mutex);
1828 1829
1829 1830 /* free the hca_list on this gid_info */
1830 1831 ibdm_delete_glhca_list(gid_info);
1831 1832
1832 1833 mutex_enter(&ibdm.ibdm_mutex);
1833 1834 --ibdm.ibdm_ngid_probes_in_progress;
1834 1835 ibdm_wakeup_probe_gid_cv();
1835 1836 mutex_exit(&ibdm.ibdm_mutex);
1836 1837
1837 1838 return;
1838 1839 }
1839 1840 }
1840 1841
1841 1842
1842 1843 /*
1843 1844 * ibdm_check_dest_nodeguid
1844 1845 * Searches for the NodeGuid in the GID list
1845 1846 * Returns matching gid_info if found and otherwise NULL
1846 1847 *
1847 1848 * This function is called to handle new GIDs discovered
1848 1849 * during device sweep / probe or for GID_AVAILABLE event.
1849 1850 *
1850 1851 * Parameter :
1851 1852 * gid_info GID to check
1852 1853 */
1853 1854 static ibdm_dp_gidinfo_t *
1854 1855 ibdm_check_dest_nodeguid(ibdm_dp_gidinfo_t *gid_info)
1855 1856 {
1856 1857 ibdm_dp_gidinfo_t *gid_list;
1857 1858 ibdm_gid_t *tmp;
1858 1859
1859 1860 IBTF_DPRINTF_L4("ibdm", "\tcheck_dest_nodeguid");
1860 1861
1861 1862 gid_list = ibdm.ibdm_dp_gidlist_head;
1862 1863 while (gid_list) {
1863 1864 if ((gid_list != gid_info) &&
1864 1865 (gid_info->gl_nodeguid == gid_list->gl_nodeguid)) {
1865 1866 IBTF_DPRINTF_L4("ibdm",
1866 1867 "\tcheck_dest_nodeguid: NodeGuid is present");
1867 1868
1868 1869 /* Add to gid_list */
1869 1870 tmp = kmem_zalloc(sizeof (ibdm_gid_t),
1870 1871 KM_SLEEP);
1871 1872 tmp->gid_dgid_hi = gid_info->gl_dgid_hi;
1872 1873 tmp->gid_dgid_lo = gid_info->gl_dgid_lo;
1873 1874 tmp->gid_next = gid_list->gl_gid;
1874 1875 gid_list->gl_gid = tmp;
1875 1876 gid_list->gl_ngids++;
1876 1877 return (gid_list);
1877 1878 }
1878 1879
1879 1880 gid_list = gid_list->gl_next;
1880 1881 }
1881 1882
1882 1883 return (NULL);
1883 1884 }
1884 1885
1885 1886
1886 1887 /*
1887 1888 * ibdm_is_dev_mgt_supported
1888 1889 * Get the PortInfo attribute (SA Query)
1889 1890 * Check "CompatabilityMask" field in the Portinfo.
1890 1891 * Return IBDM_SUCCESS if DM MAD's supported (if bit 19 set)
1891 1892 * by the port, otherwise IBDM_FAILURE
1892 1893 */
1893 1894 static int
1894 1895 ibdm_is_dev_mgt_supported(ibdm_dp_gidinfo_t *gid_info)
1895 1896 {
1896 1897 int ret;
1897 1898 size_t length = 0;
1898 1899 sa_portinfo_record_t req, *resp = NULL;
1899 1900 ibmf_saa_access_args_t qargs;
1900 1901
1901 1902 bzero(&req, sizeof (sa_portinfo_record_t));
1902 1903 req.EndportLID = gid_info->gl_dlid;
1903 1904
1904 1905 qargs.sq_attr_id = SA_PORTINFORECORD_ATTRID;
1905 1906 qargs.sq_access_type = IBMF_SAA_RETRIEVE;
1906 1907 qargs.sq_component_mask = SA_PORTINFO_COMPMASK_PORTLID;
1907 1908 qargs.sq_template = &req;
1908 1909 qargs.sq_callback = NULL;
1909 1910 qargs.sq_callback_arg = NULL;
1910 1911
1911 1912 ret = ibmf_sa_access(gid_info->gl_sa_hdl,
1912 1913 &qargs, 0, &length, (void **)&resp);
1913 1914
1914 1915 if ((ret != IBMF_SUCCESS) || (length == 0) || (resp == NULL)) {
1915 1916 IBTF_DPRINTF_L2("ibdm", "\tis_dev_mgt_supported:"
1916 1917 "failed to get PORTINFO attribute %d", ret);
1917 1918 return (IBDM_FAILURE);
1918 1919 }
1919 1920
1920 1921 if (resp->PortInfo.CapabilityMask & SM_CAP_MASK_IS_DM_SUPPD) {
1921 1922 IBTF_DPRINTF_L4("ibdm", "\tis_dev_mgt_supported: SUPPD !!");
1922 1923 ret = IBDM_SUCCESS;
1923 1924 } else {
1924 1925 IBTF_DPRINTF_L4("ibdm", "\tis_dev_mgt_supported: "
1925 1926 "Not SUPPD !!, cap 0x%x", resp->PortInfo.CapabilityMask);
1926 1927 ret = IBDM_FAILURE;
1927 1928 }
1928 1929 kmem_free(resp, length);
1929 1930 return (ret);
1930 1931 }
1931 1932
1932 1933
1933 1934 /*
1934 1935 * ibdm_get_node_port_guids()
1935 1936 * Get the NodeInfoRecord of the port
1936 1937 * Save NodeGuid and PortGUID values in the GID list structure.
1937 1938 * Return IBDM_SUCCESS/IBDM_FAILURE
1938 1939 */
1939 1940 static int
1940 1941 ibdm_get_node_port_guids(ibmf_saa_handle_t sa_hdl, ib_lid_t dlid,
1941 1942 ib_guid_t *node_guid, ib_guid_t *port_guid)
1942 1943 {
1943 1944 int ret;
1944 1945 size_t length = 0;
1945 1946 sa_node_record_t req, *resp = NULL;
1946 1947 ibmf_saa_access_args_t qargs;
1947 1948
1948 1949 IBTF_DPRINTF_L4("ibdm", "\tget_node_port_guids");
1949 1950
1950 1951 bzero(&req, sizeof (sa_node_record_t));
1951 1952 req.LID = dlid;
1952 1953
1953 1954 qargs.sq_attr_id = SA_NODERECORD_ATTRID;
1954 1955 qargs.sq_access_type = IBMF_SAA_RETRIEVE;
1955 1956 qargs.sq_component_mask = SA_NODEINFO_COMPMASK_NODELID;
1956 1957 qargs.sq_template = &req;
1957 1958 qargs.sq_callback = NULL;
1958 1959 qargs.sq_callback_arg = NULL;
1959 1960
1960 1961 ret = ibmf_sa_access(sa_hdl, &qargs, 0, &length, (void **)&resp);
1961 1962 if ((ret != IBMF_SUCCESS) || (length == 0) || (resp == NULL)) {
1962 1963 IBTF_DPRINTF_L2("ibdm", "\tget_node_port_guids:"
1963 1964 " SA Retrieve Failed: %d", ret);
1964 1965 return (IBDM_FAILURE);
1965 1966 }
1966 1967 IBTF_DPRINTF_L4("ibdm", "\tget_node_port_guids: NodeGuid %llx Port"
1967 1968 "GUID %llx", resp->NodeInfo.NodeGUID, resp->NodeInfo.NodeGUID);
1968 1969
1969 1970 *node_guid = resp->NodeInfo.NodeGUID;
1970 1971 *port_guid = resp->NodeInfo.PortGUID;
1971 1972 kmem_free(resp, length);
1972 1973 return (IBDM_SUCCESS);
1973 1974 }
1974 1975
1975 1976
1976 1977 /*
1977 1978 * ibdm_get_reachable_ports()
1978 1979 * Get list of the destination GID (and its path records) by
1979 1980 * querying the SA access.
1980 1981 *
1981 1982 * Returns Number paths
1982 1983 */
1983 1984 static int
1984 1985 ibdm_get_reachable_ports(ibdm_port_attr_t *portinfo, ibdm_hca_list_t *hca)
1985 1986 {
1986 1987 uint_t ii, jj, nrecs;
1987 1988 uint_t npaths = 0;
1988 1989 size_t length;
1989 1990 ib_gid_t sgid;
1990 1991 ibdm_pkey_tbl_t *pkey_tbl;
1991 1992 sa_path_record_t *result;
1992 1993 sa_path_record_t *precp;
1993 1994 ibdm_dp_gidinfo_t *gid_info;
1994 1995
1995 1996 ASSERT(MUTEX_HELD(&ibdm.ibdm_hl_mutex));
1996 1997 IBTF_DPRINTF_L4("ibdm", "\tget_reachable_ports: portinfo %p", portinfo);
1997 1998
1998 1999 sgid.gid_prefix = portinfo->pa_sn_prefix;
1999 2000 sgid.gid_guid = portinfo->pa_port_guid;
2000 2001
2001 2002 /* get reversible paths */
2002 2003 if (portinfo->pa_sa_hdl && ibmf_saa_paths_from_gid(portinfo->pa_sa_hdl,
2003 2004 sgid, IBMF_SAA_PKEY_WC, B_TRUE, 0, &nrecs, &length, &result)
2004 2005 != IBMF_SUCCESS) {
2005 2006 IBTF_DPRINTF_L2("ibdm",
2006 2007 "\tget_reachable_ports: Getting path records failed");
2007 2008 return (0);
2008 2009 }
2009 2010
2010 2011 for (ii = 0; ii < nrecs; ii++) {
2011 2012 sa_node_record_t *nrec;
2012 2013 size_t length;
2013 2014
2014 2015 precp = &result[ii];
2015 2016 if ((gid_info = ibdm_check_dgid(precp->DGID.gid_guid,
2016 2017 precp->DGID.gid_prefix)) != NULL) {
2017 2018 IBTF_DPRINTF_L5("ibdm", "\tget_reachable_ports: "
2018 2019 "Already exists nrecs %d, ii %d", nrecs, ii);
2019 2020 ibdm_addto_glhcalist(gid_info, hca);
2020 2021 continue;
2021 2022 }
2022 2023 /*
2023 2024 * This is a new GID. Allocate a GID structure and
2024 2025 * initialize the structure
2025 2026 * gl_state is initialized to IBDM_GID_PROBE_NOT_DONE (0)
2026 2027 * by kmem_zalloc call
2027 2028 */
2028 2029 gid_info = kmem_zalloc(sizeof (ibdm_dp_gidinfo_t), KM_SLEEP);
2029 2030 mutex_init(&gid_info->gl_mutex, NULL, MUTEX_DEFAULT, NULL);
2030 2031 cv_init(&gid_info->gl_probe_cv, NULL, CV_DRIVER, NULL);
2031 2032 gid_info->gl_dgid_hi = precp->DGID.gid_prefix;
2032 2033 gid_info->gl_dgid_lo = precp->DGID.gid_guid;
2033 2034 gid_info->gl_sgid_hi = precp->SGID.gid_prefix;
2034 2035 gid_info->gl_sgid_lo = precp->SGID.gid_guid;
2035 2036 gid_info->gl_p_key = precp->P_Key;
2036 2037 gid_info->gl_sa_hdl = portinfo->pa_sa_hdl;
2037 2038 gid_info->gl_ibmf_hdl = portinfo->pa_ibmf_hdl;
2038 2039 gid_info->gl_slid = precp->SLID;
2039 2040 gid_info->gl_dlid = precp->DLID;
2040 2041 gid_info->gl_transactionID = (++ibdm.ibdm_transactionID)
2041 2042 << IBDM_GID_TRANSACTIONID_SHIFT;
2042 2043 gid_info->gl_min_transactionID = gid_info->gl_transactionID;
2043 2044 gid_info->gl_max_transactionID = (ibdm.ibdm_transactionID +1)
2044 2045 << IBDM_GID_TRANSACTIONID_SHIFT;
2045 2046 gid_info->gl_SL = precp->SL;
2046 2047
2047 2048 /*
2048 2049 * get the node record with this guid if the destination
2049 2050 * device is a Cisco one.
2050 2051 */
2051 2052 if (ibdm_is_cisco(precp->DGID.gid_guid) &&
2052 2053 (gid_info->gl_nodeguid == 0 || gid_info->gl_devid == 0) &&
2053 2054 ibdm_get_node_record_by_port(portinfo->pa_sa_hdl,
2054 2055 precp->DGID.gid_guid, &nrec, &length) == IBDM_SUCCESS) {
2055 2056 gid_info->gl_nodeguid = nrec->NodeInfo.NodeGUID;
2056 2057 gid_info->gl_devid = nrec->NodeInfo.DeviceID;
2057 2058 kmem_free(nrec, length);
2058 2059 }
2059 2060
2060 2061 ibdm_addto_glhcalist(gid_info, hca);
2061 2062
2062 2063 ibdm_dump_path_info(precp);
2063 2064
2064 2065 gid_info->gl_qp_hdl = NULL;
2065 2066 ASSERT(portinfo->pa_pkey_tbl != NULL &&
2066 2067 portinfo->pa_npkeys != 0);
2067 2068
2068 2069 for (jj = 0; jj < portinfo->pa_npkeys; jj++) {
2069 2070 pkey_tbl = &portinfo->pa_pkey_tbl[jj];
2070 2071 if ((gid_info->gl_p_key == pkey_tbl->pt_pkey) &&
2071 2072 (pkey_tbl->pt_qp_hdl != NULL)) {
2072 2073 gid_info->gl_qp_hdl = pkey_tbl->pt_qp_hdl;
2073 2074 break;
2074 2075 }
2075 2076 }
2076 2077
2077 2078 /*
2078 2079 * QP handle for GID not initialized. No matching Pkey
2079 2080 * was found!! ibdm should *not* hit this case. Flag an
2080 2081 * error and drop the GID if ibdm does encounter this.
2081 2082 */
2082 2083 if (gid_info->gl_qp_hdl == NULL) {
2083 2084 IBTF_DPRINTF_L2(ibdm_string,
2084 2085 "\tget_reachable_ports: No matching Pkey");
2085 2086 ibdm_delete_gidinfo(gid_info);
2086 2087 continue;
2087 2088 }
2088 2089 if (ibdm.ibdm_dp_gidlist_head == NULL) {
2089 2090 ibdm.ibdm_dp_gidlist_head = gid_info;
2090 2091 ibdm.ibdm_dp_gidlist_tail = gid_info;
2091 2092 } else {
2092 2093 ibdm.ibdm_dp_gidlist_tail->gl_next = gid_info;
2093 2094 gid_info->gl_prev = ibdm.ibdm_dp_gidlist_tail;
2094 2095 ibdm.ibdm_dp_gidlist_tail = gid_info;
2095 2096 }
2096 2097 npaths++;
2097 2098 }
2098 2099 kmem_free(result, length);
2099 2100 IBTF_DPRINTF_L4("ibdm", "\tget_reachable_ports: npaths = %d", npaths);
2100 2101 return (npaths);
2101 2102 }
2102 2103
2103 2104
2104 2105 /*
2105 2106 * ibdm_check_dgid()
2106 2107 * Look in the global list to check whether we know this DGID already
2107 2108 * Return IBDM_GID_PRESENT/IBDM_GID_NOT_PRESENT
2108 2109 */
2109 2110 static ibdm_dp_gidinfo_t *
2110 2111 ibdm_check_dgid(ib_guid_t guid, ib_sn_prefix_t prefix)
2111 2112 {
2112 2113 ibdm_dp_gidinfo_t *gid_list;
2113 2114
2114 2115 for (gid_list = ibdm.ibdm_dp_gidlist_head; gid_list;
2115 2116 gid_list = gid_list->gl_next) {
2116 2117 if ((guid == gid_list->gl_dgid_lo) &&
2117 2118 (prefix == gid_list->gl_dgid_hi)) {
2118 2119 break;
2119 2120 }
2120 2121 }
2121 2122 return (gid_list);
2122 2123 }
2123 2124
2124 2125
2125 2126 /*
2126 2127 * ibdm_find_gid()
2127 2128 * Look in the global list to find a GID entry with matching
2128 2129 * port & node GUID.
2129 2130 * Return pointer to gidinfo if found, else return NULL
2130 2131 */
2131 2132 static ibdm_dp_gidinfo_t *
2132 2133 ibdm_find_gid(ib_guid_t nodeguid, ib_guid_t portguid)
2133 2134 {
2134 2135 ibdm_dp_gidinfo_t *gid_list;
2135 2136
2136 2137 IBTF_DPRINTF_L4("ibdm", "ibdm_find_gid(%llx, %llx)\n",
2137 2138 nodeguid, portguid);
2138 2139
2139 2140 for (gid_list = ibdm.ibdm_dp_gidlist_head; gid_list;
2140 2141 gid_list = gid_list->gl_next) {
2141 2142 if ((portguid == gid_list->gl_portguid) &&
2142 2143 (nodeguid == gid_list->gl_nodeguid)) {
2143 2144 break;
2144 2145 }
2145 2146 }
2146 2147
2147 2148 IBTF_DPRINTF_L4("ibdm", "ibdm_find_gid : returned %p\n",
2148 2149 gid_list);
2149 2150 return (gid_list);
2150 2151 }
2151 2152
2152 2153
2153 2154 /*
2154 2155 * ibdm_set_classportinfo()
2155 2156 * ibdm_set_classportinfo() is a function to activate a Cisco FC GW
2156 2157 * by sending the setClassPortInfo request with the trapLID, trapGID
2157 2158 * and etc. to the gateway since the gateway doesn't provide the IO
2158 2159 * Unit Information othewise. This behavior is the Cisco specific one,
2159 2160 * and this function is called to a Cisco FC GW only.
2160 2161 * Returns IBDM_SUCCESS/IBDM_FAILURE
2161 2162 */
2162 2163 static int
2163 2164 ibdm_set_classportinfo(ibdm_dp_gidinfo_t *gid_info)
2164 2165 {
2165 2166 ibmf_msg_t *msg;
2166 2167 ib_mad_hdr_t *hdr;
2167 2168 ibdm_timeout_cb_args_t *cb_args;
2168 2169 void *data;
2169 2170 ib_mad_classportinfo_t *cpi;
2170 2171
2171 2172 IBTF_DPRINTF_L4("ibdm",
2172 2173 "\tset_classportinfo: gid info 0x%p", gid_info);
2173 2174
2174 2175 /*
2175 2176 * Send command to set classportinfo attribute. Allocate a IBMF
2176 2177 * packet and initialize the packet.
2177 2178 */
2178 2179 if (ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_SLEEP,
2179 2180 &msg) != IBMF_SUCCESS) {
2180 2181 IBTF_DPRINTF_L4("ibdm", "\tset_classportinfo: pkt alloc fail");
2181 2182 return (IBDM_FAILURE);
2182 2183 }
2183 2184
2184 2185 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
2185 2186 ibdm_alloc_send_buffers(msg);
2186 2187 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
2187 2188
2188 2189 msg->im_local_addr.ia_local_lid = gid_info->gl_slid;
2189 2190 msg->im_local_addr.ia_remote_lid = gid_info->gl_dlid;
2190 2191 msg->im_local_addr.ia_remote_qno = 1;
2191 2192 msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
2192 2193 msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
2193 2194 msg->im_local_addr.ia_service_level = gid_info->gl_SL;
2194 2195
2195 2196 hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
2196 2197 hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
2197 2198 hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
2198 2199 hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
2199 2200 hdr->R_Method = IB_DM_DEVMGT_METHOD_SET;
2200 2201 hdr->Status = 0;
2201 2202 hdr->TransactionID = h2b64(gid_info->gl_transactionID);
2202 2203 hdr->AttributeID = h2b16(IB_DM_ATTR_CLASSPORTINFO);
2203 2204 hdr->AttributeModifier = 0;
2204 2205
2205 2206 data = msg->im_msgbufs_send.im_bufs_cl_data;
2206 2207 cpi = (ib_mad_classportinfo_t *)data;
2207 2208
2208 2209 /*
2209 2210 * Set the classportinfo values to activate this Cisco FC GW.
2210 2211 */
2211 2212 cpi->TrapGID_hi = h2b64(gid_info->gl_sgid_hi);
2212 2213 cpi->TrapGID_lo = h2b64(gid_info->gl_sgid_lo);
2213 2214 cpi->TrapLID = h2b16(gid_info->gl_slid);
2214 2215 cpi->TrapSL = gid_info->gl_SL;
2215 2216 cpi->TrapP_Key = h2b16(gid_info->gl_p_key);
2216 2217 cpi->TrapQP = h2b32((((ibmf_alt_qp_t *)gid_info->gl_qp_hdl)->isq_qpn));
2217 2218 cpi->TrapQ_Key = h2b32((((ibmf_alt_qp_t *)
2218 2219 gid_info->gl_qp_hdl)->isq_qkey));
2219 2220
2220 2221 cb_args = &gid_info->gl_cpi_cb_args;
2221 2222 cb_args->cb_gid_info = gid_info;
2222 2223 cb_args->cb_retry_count = ibdm_dft_retry_cnt;
2223 2224 cb_args->cb_req_type = IBDM_REQ_TYPE_CLASSPORTINFO;
2224 2225
2225 2226 mutex_enter(&gid_info->gl_mutex);
2226 2227 gid_info->gl_timeout_id = timeout(ibdm_pkt_timeout_hdlr,
2227 2228 cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
2228 2229 mutex_exit(&gid_info->gl_mutex);
2229 2230
2230 2231 IBTF_DPRINTF_L5("ibdm", "\tset_classportinfo: "
2231 2232 "timeout id %x", gid_info->gl_timeout_id);
2232 2233
2233 2234 if (ibmf_msg_transport(gid_info->gl_ibmf_hdl, gid_info->gl_qp_hdl,
2234 2235 msg, NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
2235 2236 IBTF_DPRINTF_L2("ibdm",
2236 2237 "\tset_classportinfo: ibmf send failed");
2237 2238 ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl, msg, cb_args);
2238 2239 }
2239 2240
2240 2241 return (IBDM_SUCCESS);
2241 2242 }
2242 2243
2243 2244
2244 2245 /*
2245 2246 * ibdm_send_classportinfo()
2246 2247 * Send classportinfo request. When the request is completed
2247 2248 * IBMF calls ibdm_classportinfo_cb routine to inform about
2248 2249 * the completion.
2249 2250 * Returns IBDM_SUCCESS/IBDM_FAILURE
2250 2251 */
2251 2252 static int
2252 2253 ibdm_send_classportinfo(ibdm_dp_gidinfo_t *gid_info)
2253 2254 {
2254 2255 ibmf_msg_t *msg;
2255 2256 ib_mad_hdr_t *hdr;
2256 2257 ibdm_timeout_cb_args_t *cb_args;
2257 2258
2258 2259 IBTF_DPRINTF_L4("ibdm",
2259 2260 "\tsend_classportinfo: gid info 0x%p", gid_info);
2260 2261
2261 2262 /*
2262 2263 * Send command to get classportinfo attribute. Allocate a IBMF
2263 2264 * packet and initialize the packet.
2264 2265 */
2265 2266 if (ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_SLEEP,
2266 2267 &msg) != IBMF_SUCCESS) {
2267 2268 IBTF_DPRINTF_L4("ibdm", "\tsend_classportinfo: pkt alloc fail");
2268 2269 return (IBDM_FAILURE);
2269 2270 }
2270 2271
2271 2272 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
2272 2273 ibdm_alloc_send_buffers(msg);
2273 2274 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
2274 2275
2275 2276 msg->im_local_addr.ia_local_lid = gid_info->gl_slid;
2276 2277 msg->im_local_addr.ia_remote_lid = gid_info->gl_dlid;
2277 2278 msg->im_local_addr.ia_remote_qno = 1;
2278 2279 msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
2279 2280 msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
2280 2281 msg->im_local_addr.ia_service_level = gid_info->gl_SL;
2281 2282
2282 2283 hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
2283 2284 hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
2284 2285 hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
2285 2286 hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
2286 2287 hdr->R_Method = IB_DM_DEVMGT_METHOD_GET;
2287 2288 hdr->Status = 0;
2288 2289 hdr->TransactionID = h2b64(gid_info->gl_transactionID);
2289 2290 hdr->AttributeID = h2b16(IB_DM_ATTR_CLASSPORTINFO);
2290 2291 hdr->AttributeModifier = 0;
2291 2292
2292 2293 cb_args = &gid_info->gl_cpi_cb_args;
2293 2294 cb_args->cb_gid_info = gid_info;
2294 2295 cb_args->cb_retry_count = ibdm_dft_retry_cnt;
2295 2296 cb_args->cb_req_type = IBDM_REQ_TYPE_CLASSPORTINFO;
2296 2297
2297 2298 mutex_enter(&gid_info->gl_mutex);
2298 2299 gid_info->gl_timeout_id = timeout(ibdm_pkt_timeout_hdlr,
2299 2300 cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
2300 2301 mutex_exit(&gid_info->gl_mutex);
2301 2302
2302 2303 IBTF_DPRINTF_L5("ibdm", "\tsend_classportinfo: "
2303 2304 "timeout id %x", gid_info->gl_timeout_id);
2304 2305
2305 2306 if (ibmf_msg_transport(gid_info->gl_ibmf_hdl, gid_info->gl_qp_hdl,
2306 2307 msg, NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
2307 2308 IBTF_DPRINTF_L2("ibdm",
2308 2309 "\tsend_classportinfo: ibmf send failed");
2309 2310 ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl, msg, cb_args);
2310 2311 }
2311 2312
2312 2313 return (IBDM_SUCCESS);
2313 2314 }
2314 2315
2315 2316
2316 2317 /*
2317 2318 * ibdm_handle_setclassportinfo()
2318 2319 * Invoked by the IBMF when setClassPortInfo request is completed.
2319 2320 */
2320 2321 static void
2321 2322 ibdm_handle_setclassportinfo(ibmf_handle_t ibmf_hdl,
2322 2323 ibmf_msg_t *msg, ibdm_dp_gidinfo_t *gid_info, int *flag)
2323 2324 {
2324 2325 void *data;
2325 2326 timeout_id_t timeout_id;
2326 2327 ib_mad_classportinfo_t *cpi;
2327 2328
2328 2329 IBTF_DPRINTF_L4("ibdm", "\thandle_setclassportinfo:ibmf hdl "
2329 2330 "%p msg %p gid info %p", ibmf_hdl, msg, gid_info);
2330 2331
2331 2332 if (IBDM_IN_IBMFMSG_ATTR(msg) != IB_DM_ATTR_CLASSPORTINFO) {
2332 2333 IBTF_DPRINTF_L4("ibdm", "\thandle_setclassportinfo: "
2333 2334 "Not a ClassPortInfo resp");
2334 2335 *flag |= IBDM_IBMF_PKT_UNEXP_RESP;
2335 2336 return;
2336 2337 }
2337 2338
2338 2339 /*
2339 2340 * Verify whether timeout handler is created/active.
2340 2341 * If created/ active, cancel the timeout handler
2341 2342 */
2342 2343 mutex_enter(&gid_info->gl_mutex);
2343 2344 if (gid_info->gl_state != IBDM_SET_CLASSPORTINFO) {
2344 2345 IBTF_DPRINTF_L2("ibdm", "\thandle_setclassportinfo:DUP resp");
2345 2346 *flag |= IBDM_IBMF_PKT_DUP_RESP;
2346 2347 mutex_exit(&gid_info->gl_mutex);
2347 2348 return;
2348 2349 }
2349 2350 ibdm_bump_transactionID(gid_info);
2350 2351
2351 2352 gid_info->gl_iou_cb_args.cb_req_type = 0;
2352 2353 if (gid_info->gl_timeout_id) {
2353 2354 timeout_id = gid_info->gl_timeout_id;
2354 2355 mutex_exit(&gid_info->gl_mutex);
2355 2356 IBTF_DPRINTF_L5("ibdm", "handle_setlassportinfo: "
2356 2357 "gl_timeout_id = 0x%x", timeout_id);
2357 2358 if (untimeout(timeout_id) == -1) {
2358 2359 IBTF_DPRINTF_L2("ibdm", "handle_setclassportinfo: "
2359 2360 "untimeout gl_timeout_id failed");
2360 2361 }
2361 2362 mutex_enter(&gid_info->gl_mutex);
2362 2363 gid_info->gl_timeout_id = 0;
2363 2364 }
2364 2365 mutex_exit(&gid_info->gl_mutex);
2365 2366
2366 2367 data = msg->im_msgbufs_recv.im_bufs_cl_data;
2367 2368 cpi = (ib_mad_classportinfo_t *)data;
2368 2369
2369 2370 ibdm_dump_classportinfo(cpi);
2370 2371 }
2371 2372
2372 2373
2373 2374 /*
2374 2375 * ibdm_handle_classportinfo()
2375 2376 * Invoked by the IBMF when the classportinfo request is completed.
2376 2377 */
2377 2378 static void
2378 2379 ibdm_handle_classportinfo(ibmf_handle_t ibmf_hdl,
2379 2380 ibmf_msg_t *msg, ibdm_dp_gidinfo_t *gid_info, int *flag)
2380 2381 {
2381 2382 void *data;
2382 2383 timeout_id_t timeout_id;
2383 2384 ib_mad_hdr_t *hdr;
2384 2385 ib_mad_classportinfo_t *cpi;
2385 2386
2386 2387 IBTF_DPRINTF_L4("ibdm", "\thandle_classportinfo:ibmf hdl "
2387 2388 "%p msg %p gid info %p", ibmf_hdl, msg, gid_info);
2388 2389
2389 2390 if (IBDM_IN_IBMFMSG_ATTR(msg) != IB_DM_ATTR_CLASSPORTINFO) {
2390 2391 IBTF_DPRINTF_L4("ibdm", "\thandle_classportinfo: "
2391 2392 "Not a ClassPortInfo resp");
2392 2393 *flag |= IBDM_IBMF_PKT_UNEXP_RESP;
2393 2394 return;
2394 2395 }
2395 2396
2396 2397 /*
2397 2398 * Verify whether timeout handler is created/active.
2398 2399 * If created/ active, cancel the timeout handler
2399 2400 */
2400 2401 mutex_enter(&gid_info->gl_mutex);
2401 2402 ibdm_bump_transactionID(gid_info);
2402 2403 if (gid_info->gl_state != IBDM_GET_CLASSPORTINFO) {
2403 2404 IBTF_DPRINTF_L2("ibdm", "\thandle_classportinfo:DUP resp");
2404 2405 *flag |= IBDM_IBMF_PKT_DUP_RESP;
2405 2406 mutex_exit(&gid_info->gl_mutex);
2406 2407 return;
2407 2408 }
2408 2409 gid_info->gl_iou_cb_args.cb_req_type = 0;
2409 2410 if (gid_info->gl_timeout_id) {
2410 2411 timeout_id = gid_info->gl_timeout_id;
2411 2412 mutex_exit(&gid_info->gl_mutex);
2412 2413 IBTF_DPRINTF_L5("ibdm", "handle_ioclassportinfo: "
2413 2414 "gl_timeout_id = 0x%x", timeout_id);
2414 2415 if (untimeout(timeout_id) == -1) {
2415 2416 IBTF_DPRINTF_L2("ibdm", "handle_classportinfo: "
2416 2417 "untimeout gl_timeout_id failed");
2417 2418 }
2418 2419 mutex_enter(&gid_info->gl_mutex);
2419 2420 gid_info->gl_timeout_id = 0;
2420 2421 }
2421 2422 gid_info->gl_state = IBDM_GET_IOUNITINFO;
2422 2423 gid_info->gl_pending_cmds++;
2423 2424 mutex_exit(&gid_info->gl_mutex);
2424 2425
2425 2426 data = msg->im_msgbufs_recv.im_bufs_cl_data;
2426 2427 cpi = (ib_mad_classportinfo_t *)data;
2427 2428
2428 2429 /*
2429 2430 * Cache the "RespTimeValue" and redirection information in the
2430 2431 * global gid list data structure. This cached information will
2431 2432 * be used to send any further requests to the GID.
2432 2433 */
2433 2434 gid_info->gl_resp_timeout =
2434 2435 (b2h32(cpi->RespTimeValue) & 0x1F);
2435 2436
2436 2437 gid_info->gl_redirected = ((IBDM_IN_IBMFMSG_STATUS(msg) &
2437 2438 MAD_STATUS_REDIRECT_REQUIRED) ? B_TRUE: B_FALSE);
2438 2439 gid_info->gl_redirect_dlid = b2h16(cpi->RedirectLID);
2439 2440 gid_info->gl_redirect_QP = (b2h32(cpi->RedirectQP) & 0xffffff);
2440 2441 gid_info->gl_redirect_pkey = b2h16(cpi->RedirectP_Key);
2441 2442 gid_info->gl_redirect_qkey = b2h32(cpi->RedirectQ_Key);
2442 2443 gid_info->gl_redirectGID_hi = b2h64(cpi->RedirectGID_hi);
2443 2444 gid_info->gl_redirectGID_lo = b2h64(cpi->RedirectGID_lo);
2444 2445 gid_info->gl_redirectSL = cpi->RedirectSL;
2445 2446
2446 2447 ibdm_dump_classportinfo(cpi);
2447 2448
2448 2449 /*
2449 2450 * Send IOUnitInfo request
2450 2451 * Reuse previously allocated IBMF packet for sending ClassPortInfo
2451 2452 * Check whether DM agent on the remote node requested redirection
2452 2453 * If so, send the request to the redirect DGID/DLID/PKEY/QP.
2453 2454 */
2454 2455 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
2455 2456 ibdm_alloc_send_buffers(msg);
2456 2457 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
2457 2458 msg->im_local_addr.ia_local_lid = gid_info->gl_slid;
2458 2459 msg->im_local_addr.ia_remote_lid = gid_info->gl_dlid;
2459 2460
2460 2461 if (gid_info->gl_redirected == B_TRUE) {
2461 2462 if (gid_info->gl_redirect_dlid != 0) {
2462 2463 msg->im_local_addr.ia_remote_lid =
2463 2464 gid_info->gl_redirect_dlid;
2464 2465 }
2465 2466 msg->im_local_addr.ia_remote_qno = gid_info->gl_redirect_QP;
2466 2467 msg->im_local_addr.ia_p_key = gid_info->gl_redirect_pkey;
2467 2468 msg->im_local_addr.ia_q_key = gid_info->gl_redirect_qkey;
2468 2469 msg->im_local_addr.ia_service_level = gid_info->gl_redirectSL;
2469 2470 } else {
2470 2471 msg->im_local_addr.ia_remote_qno = 1;
2471 2472 msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
2472 2473 msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
2473 2474 msg->im_local_addr.ia_service_level = gid_info->gl_SL;
2474 2475 }
2475 2476
2476 2477 hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
2477 2478 hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
2478 2479 hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
2479 2480 hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
2480 2481 hdr->R_Method = IB_DM_DEVMGT_METHOD_GET;
2481 2482 hdr->Status = 0;
2482 2483 hdr->TransactionID = h2b64(gid_info->gl_transactionID);
2483 2484 hdr->AttributeID = h2b16(IB_DM_ATTR_IO_UNITINFO);
2484 2485 hdr->AttributeModifier = 0;
2485 2486
2486 2487 gid_info->gl_iou_cb_args.cb_req_type = IBDM_REQ_TYPE_IOUINFO;
2487 2488 gid_info->gl_iou_cb_args.cb_gid_info = gid_info;
2488 2489 gid_info->gl_iou_cb_args.cb_retry_count = ibdm_dft_retry_cnt;
2489 2490
2490 2491 mutex_enter(&gid_info->gl_mutex);
2491 2492 gid_info->gl_timeout_id = timeout(ibdm_pkt_timeout_hdlr,
2492 2493 &gid_info->gl_iou_cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
2493 2494 mutex_exit(&gid_info->gl_mutex);
2494 2495
2495 2496 IBTF_DPRINTF_L5("ibdm", "handle_classportinfo:"
2496 2497 "timeout %x", gid_info->gl_timeout_id);
2497 2498
2498 2499 if (ibmf_msg_transport(ibmf_hdl, gid_info->gl_qp_hdl, msg, NULL,
2499 2500 ibdm_ibmf_send_cb, &gid_info->gl_iou_cb_args, 0) != IBMF_SUCCESS) {
2500 2501 IBTF_DPRINTF_L2("ibdm",
2501 2502 "\thandle_classportinfo: msg transport failed");
2502 2503 ibdm_ibmf_send_cb(ibmf_hdl, msg, &gid_info->gl_iou_cb_args);
2503 2504 }
2504 2505 (*flag) |= IBDM_IBMF_PKT_REUSED;
2505 2506 }
2506 2507
2507 2508
2508 2509 /*
2509 2510 * ibdm_send_iounitinfo:
2510 2511 * Sends a DM request to get IOU unitinfo.
2511 2512 */
2512 2513 static int
2513 2514 ibdm_send_iounitinfo(ibdm_dp_gidinfo_t *gid_info)
2514 2515 {
2515 2516 ibmf_msg_t *msg;
2516 2517 ib_mad_hdr_t *hdr;
2517 2518
2518 2519 IBTF_DPRINTF_L4("ibdm", "\tsend_iounitinfo: gid info 0x%p", gid_info);
2519 2520
2520 2521 /*
2521 2522 * Send command to get iounitinfo attribute. Allocate a IBMF
2522 2523 * packet and initialize the packet.
2523 2524 */
2524 2525 if (ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_SLEEP, &msg) !=
2525 2526 IBMF_SUCCESS) {
2526 2527 IBTF_DPRINTF_L4("ibdm", "\tsend_iounitinfo: pkt alloc fail");
2527 2528 return (IBDM_FAILURE);
2528 2529 }
2529 2530
2530 2531 mutex_enter(&gid_info->gl_mutex);
2531 2532 ibdm_bump_transactionID(gid_info);
2532 2533 mutex_exit(&gid_info->gl_mutex);
2533 2534
2534 2535
2535 2536 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
2536 2537 ibdm_alloc_send_buffers(msg);
2537 2538 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
2538 2539 msg->im_local_addr.ia_local_lid = gid_info->gl_slid;
2539 2540 msg->im_local_addr.ia_remote_lid = gid_info->gl_dlid;
2540 2541 msg->im_local_addr.ia_remote_qno = 1;
2541 2542 msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
2542 2543 msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
2543 2544 msg->im_local_addr.ia_service_level = gid_info->gl_SL;
2544 2545
2545 2546 hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
2546 2547 hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
2547 2548 hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
2548 2549 hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
2549 2550 hdr->R_Method = IB_DM_DEVMGT_METHOD_GET;
2550 2551 hdr->Status = 0;
2551 2552 hdr->TransactionID = h2b64(gid_info->gl_transactionID);
2552 2553 hdr->AttributeID = h2b16(IB_DM_ATTR_IO_UNITINFO);
2553 2554 hdr->AttributeModifier = 0;
2554 2555
2555 2556 gid_info->gl_iou_cb_args.cb_gid_info = gid_info;
2556 2557 gid_info->gl_iou_cb_args.cb_retry_count = ibdm_dft_retry_cnt;
2557 2558 gid_info->gl_iou_cb_args.cb_req_type = IBDM_REQ_TYPE_IOUINFO;
2558 2559
2559 2560 mutex_enter(&gid_info->gl_mutex);
2560 2561 gid_info->gl_timeout_id = timeout(ibdm_pkt_timeout_hdlr,
2561 2562 &gid_info->gl_iou_cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
2562 2563 mutex_exit(&gid_info->gl_mutex);
2563 2564
2564 2565 IBTF_DPRINTF_L5("ibdm", "send_iouunitinfo:"
2565 2566 "timeout %x", gid_info->gl_timeout_id);
2566 2567
2567 2568 if (ibmf_msg_transport(gid_info->gl_ibmf_hdl, gid_info->gl_qp_hdl, msg,
2568 2569 NULL, ibdm_ibmf_send_cb, &gid_info->gl_iou_cb_args, 0) !=
2569 2570 IBMF_SUCCESS) {
2570 2571 IBTF_DPRINTF_L2("ibdm", "\tsend_iounitinfo: ibmf send failed");
2571 2572 ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl,
2572 2573 msg, &gid_info->gl_iou_cb_args);
2573 2574 }
2574 2575 return (IBDM_SUCCESS);
2575 2576 }
2576 2577
2577 2578 /*
2578 2579 * ibdm_handle_iounitinfo()
2579 2580 * Invoked by the IBMF when IO Unitinfo request is completed.
2580 2581 */
2581 2582 static void
2582 2583 ibdm_handle_iounitinfo(ibmf_handle_t ibmf_hdl,
2583 2584 ibmf_msg_t *msg, ibdm_dp_gidinfo_t *gid_info, int *flag)
2584 2585 {
2585 2586 int ii, first = B_TRUE;
2586 2587 int num_iocs;
2587 2588 size_t size;
2588 2589 uchar_t slot_info;
2589 2590 timeout_id_t timeout_id;
2590 2591 ib_mad_hdr_t *hdr;
2591 2592 ibdm_ioc_info_t *ioc_info;
2592 2593 ib_dm_io_unitinfo_t *iou_info;
2593 2594 ib_dm_io_unitinfo_t *giou_info;
2594 2595 ibdm_timeout_cb_args_t *cb_args;
2595 2596
2596 2597 IBTF_DPRINTF_L4("ibdm", "\thandle_iouintinfo:"
2597 2598 " ibmf hdl %p pkt %p gid info %p", ibmf_hdl, msg, gid_info);
2598 2599
2599 2600 if (IBDM_IN_IBMFMSG_ATTR(msg) != IB_DM_ATTR_IO_UNITINFO) {
2600 2601 IBTF_DPRINTF_L4("ibdm", "\thandle_iounitinfo: "
2601 2602 "Unexpected response");
2602 2603 (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
2603 2604 return;
2604 2605 }
2605 2606
2606 2607 mutex_enter(&gid_info->gl_mutex);
2607 2608 if (gid_info->gl_state != IBDM_GET_IOUNITINFO) {
2608 2609 IBTF_DPRINTF_L4("ibdm",
2609 2610 "\thandle_iounitinfo: DUP resp");
2610 2611 mutex_exit(&gid_info->gl_mutex);
2611 2612 (*flag) = IBDM_IBMF_PKT_DUP_RESP;
2612 2613 return;
2613 2614 }
2614 2615 gid_info->gl_iou_cb_args.cb_req_type = 0;
2615 2616 if (gid_info->gl_timeout_id) {
2616 2617 timeout_id = gid_info->gl_timeout_id;
2617 2618 mutex_exit(&gid_info->gl_mutex);
2618 2619 IBTF_DPRINTF_L5("ibdm", "handle_iounitinfo: "
2619 2620 "gl_timeout_id = 0x%x", timeout_id);
2620 2621 if (untimeout(timeout_id) == -1) {
2621 2622 IBTF_DPRINTF_L2("ibdm", "handle_iounitinfo: "
2622 2623 "untimeout gl_timeout_id failed");
2623 2624 }
2624 2625 mutex_enter(&gid_info->gl_mutex);
2625 2626 gid_info->gl_timeout_id = 0;
2626 2627 }
2627 2628 gid_info->gl_state = IBDM_GET_IOC_DETAILS;
2628 2629
2629 2630 iou_info = IBDM_IN_IBMFMSG2IOU(msg);
2630 2631 ibdm_dump_iounitinfo(iou_info);
2631 2632 num_iocs = iou_info->iou_num_ctrl_slots;
2632 2633 /*
2633 2634 * check if number of IOCs reported is zero? if yes, return.
2634 2635 * when num_iocs are reported zero internal IOC database needs
2635 2636 * to be updated. To ensure that save the number of IOCs in
2636 2637 * the new field "gl_num_iocs". Use a new field instead of
2637 2638 * "giou_info->iou_num_ctrl_slots" as that would prevent
2638 2639 * an unnecessary kmem_alloc/kmem_free when num_iocs is 0.
2639 2640 */
2640 2641 if (num_iocs == 0 && gid_info->gl_num_iocs == 0) {
2641 2642 IBTF_DPRINTF_L4("ibdm", "\thandle_iounitinfo: no IOC's");
2642 2643 mutex_exit(&gid_info->gl_mutex);
2643 2644 return;
2644 2645 }
2645 2646 IBTF_DPRINTF_L4("ibdm", "\thandle_iounitinfo: num_iocs = %d", num_iocs);
2646 2647
2647 2648 /*
2648 2649 * if there is an existing gl_iou (IOU has been probed before)
2649 2650 * check if the "iou_changeid" is same as saved entry in
2650 2651 * "giou_info->iou_changeid".
2651 2652 * (note: this logic can prevent IOC enumeration if a given
2652 2653 * vendor doesn't support setting iou_changeid field for its IOU)
2653 2654 *
2654 2655 * if there is an existing gl_iou and iou_changeid has changed :
2655 2656 * free up existing gl_iou info and its related structures.
2656 2657 * reallocate gl_iou info all over again.
2657 2658 * if we donot free this up; then this leads to memory leaks
2658 2659 */
2659 2660 if (gid_info->gl_iou) {
2660 2661 giou_info = &gid_info->gl_iou->iou_info;
2661 2662 if (b2h16(iou_info->iou_changeid) ==
2662 2663 giou_info->iou_changeid) {
2663 2664 IBTF_DPRINTF_L3("ibdm",
2664 2665 "\thandle_iounitinfo: no IOCs changed");
2665 2666 gid_info->gl_state = IBDM_GID_PROBING_COMPLETE;
2666 2667 mutex_exit(&gid_info->gl_mutex);
2667 2668 return;
2668 2669 }
2669 2670
2670 2671 /*
2671 2672 * Store the iou info as prev_iou to be used after
2672 2673 * sweep is done.
2673 2674 */
2674 2675 ASSERT(gid_info->gl_prev_iou == NULL);
2675 2676 IBTF_DPRINTF_L4(ibdm_string,
2676 2677 "\thandle_iounitinfo: setting gl_prev_iou %p",
2677 2678 gid_info->gl_prev_iou);
2678 2679 gid_info->gl_prev_iou = gid_info->gl_iou;
2679 2680 ibdm.ibdm_prev_iou = 1;
2680 2681 gid_info->gl_iou = NULL;
2681 2682 }
2682 2683
2683 2684 size = sizeof (ibdm_iou_info_t) + num_iocs * sizeof (ibdm_ioc_info_t);
2684 2685 gid_info->gl_iou = (ibdm_iou_info_t *)kmem_zalloc(size, KM_SLEEP);
2685 2686 giou_info = &gid_info->gl_iou->iou_info;
2686 2687 gid_info->gl_iou->iou_ioc_info = (ibdm_ioc_info_t *)
2687 2688 ((char *)gid_info->gl_iou + sizeof (ibdm_iou_info_t));
2688 2689
2689 2690 giou_info->iou_num_ctrl_slots = gid_info->gl_num_iocs = num_iocs;
2690 2691 giou_info->iou_flag = iou_info->iou_flag;
2691 2692 bcopy(iou_info->iou_ctrl_list, giou_info->iou_ctrl_list, 128);
2692 2693 giou_info->iou_changeid = b2h16(iou_info->iou_changeid);
2693 2694 gid_info->gl_pending_cmds++; /* for diag code */
2694 2695 mutex_exit(&gid_info->gl_mutex);
2695 2696
2696 2697 if (ibdm_get_diagcode(gid_info, 0) != IBDM_SUCCESS) {
2697 2698 mutex_enter(&gid_info->gl_mutex);
2698 2699 gid_info->gl_pending_cmds--;
2699 2700 mutex_exit(&gid_info->gl_mutex);
2700 2701 }
2701 2702 /*
2702 2703 * Parallelize getting IOC controller profiles from here.
2703 2704 * Allocate IBMF packets and send commands to get IOC profile for
2704 2705 * each IOC present on the IOU.
2705 2706 */
2706 2707 for (ii = 0; ii < num_iocs; ii++) {
2707 2708 /*
2708 2709 * Check whether IOC is present in the slot
2709 2710 * Series of nibbles (in the field iou_ctrl_list) represents
2710 2711 * a slot in the IOU.
2711 2712 * Byte format: 76543210
2712 2713 * Bits 0-3 of first byte represent Slot 2
2713 2714 * bits 4-7 of first byte represent slot 1,
2714 2715 * bits 0-3 of second byte represent slot 4 and so on
2715 2716 * Each 4-bit nibble has the following meaning
2716 2717 * 0x0 : IOC not installed
2717 2718 * 0x1 : IOC is present
2718 2719 * 0xf : Slot does not exist
2719 2720 * and all other values are reserved.
2720 2721 */
2721 2722 ioc_info = IBDM_GIDINFO2IOCINFO(gid_info, ii);
2722 2723 slot_info = giou_info->iou_ctrl_list[(ii/2)];
2723 2724 if ((ii % 2) == 0)
2724 2725 slot_info = (slot_info >> 4);
2725 2726
2726 2727 if ((slot_info & 0xf) != 1) {
2727 2728 IBTF_DPRINTF_L4("ibdm", "\thandle_iouintinfo: "
2728 2729 "No IOC is present in the slot = %d", ii);
2729 2730 ioc_info->ioc_state = IBDM_IOC_STATE_PROBE_FAILED;
2730 2731 continue;
2731 2732 }
2732 2733
2733 2734 mutex_enter(&gid_info->gl_mutex);
2734 2735 ibdm_bump_transactionID(gid_info);
2735 2736 mutex_exit(&gid_info->gl_mutex);
2736 2737
2737 2738 /*
2738 2739 * Re use the already allocated packet (for IOUnitinfo) to
2739 2740 * send the first IOC controller attribute. Allocate new
2740 2741 * IBMF packets for the rest of the IOC's
2741 2742 */
2742 2743 if (first != B_TRUE) {
2743 2744 msg = NULL;
2744 2745 if (ibmf_alloc_msg(ibmf_hdl, IBMF_ALLOC_SLEEP,
2745 2746 &msg) != IBMF_SUCCESS) {
2746 2747 IBTF_DPRINTF_L4("ibdm", "\thandle_iouintinfo: "
2747 2748 "IBMF packet allocation failed");
2748 2749 continue;
2749 2750 }
2750 2751
2751 2752 }
2752 2753
2753 2754 /* allocate send buffers for all messages */
2754 2755 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
2755 2756 ibdm_alloc_send_buffers(msg);
2756 2757 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
2757 2758
2758 2759 msg->im_local_addr.ia_local_lid = gid_info->gl_slid;
2759 2760 msg->im_local_addr.ia_remote_lid = gid_info->gl_dlid;
2760 2761 if (gid_info->gl_redirected == B_TRUE) {
2761 2762 if (gid_info->gl_redirect_dlid != 0) {
2762 2763 msg->im_local_addr.ia_remote_lid =
2763 2764 gid_info->gl_redirect_dlid;
2764 2765 }
2765 2766 msg->im_local_addr.ia_remote_qno =
2766 2767 gid_info->gl_redirect_QP;
2767 2768 msg->im_local_addr.ia_p_key =
2768 2769 gid_info->gl_redirect_pkey;
2769 2770 msg->im_local_addr.ia_q_key =
2770 2771 gid_info->gl_redirect_qkey;
2771 2772 msg->im_local_addr.ia_service_level =
2772 2773 gid_info->gl_redirectSL;
2773 2774 } else {
2774 2775 msg->im_local_addr.ia_remote_qno = 1;
2775 2776 msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
2776 2777 msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
2777 2778 msg->im_local_addr.ia_service_level = gid_info->gl_SL;
2778 2779 }
2779 2780
2780 2781 hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
2781 2782 hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
2782 2783 hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
2783 2784 hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
2784 2785 hdr->R_Method = IB_DM_DEVMGT_METHOD_GET;
2785 2786 hdr->Status = 0;
2786 2787 hdr->TransactionID = h2b64(gid_info->gl_transactionID);
2787 2788 hdr->AttributeID = h2b16(IB_DM_ATTR_IOC_CTRL_PROFILE);
2788 2789 hdr->AttributeModifier = h2b32(ii + 1);
2789 2790
2790 2791 ioc_info->ioc_state = IBDM_IOC_STATE_PROBE_INVALID;
2791 2792 cb_args = &ioc_info->ioc_cb_args;
2792 2793 cb_args->cb_gid_info = gid_info;
2793 2794 cb_args->cb_retry_count = ibdm_dft_retry_cnt;
2794 2795 cb_args->cb_req_type = IBDM_REQ_TYPE_IOCINFO;
2795 2796 cb_args->cb_ioc_num = ii;
2796 2797
2797 2798 mutex_enter(&gid_info->gl_mutex);
2798 2799 gid_info->gl_pending_cmds++; /* for diag code */
2799 2800
2800 2801 ioc_info->ioc_timeout_id = timeout(ibdm_pkt_timeout_hdlr,
2801 2802 cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
2802 2803 mutex_exit(&gid_info->gl_mutex);
2803 2804
2804 2805 IBTF_DPRINTF_L5("ibdm", "\thandle_iounitinfo:"
2805 2806 "timeout 0x%x, ioc_num %d", ioc_info->ioc_timeout_id, ii);
2806 2807
2807 2808 if (ibmf_msg_transport(ibmf_hdl, gid_info->gl_qp_hdl, msg,
2808 2809 NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
2809 2810 IBTF_DPRINTF_L2("ibdm",
2810 2811 "\thandle_iounitinfo: msg transport failed");
2811 2812 ibdm_ibmf_send_cb(ibmf_hdl, msg, cb_args);
2812 2813 }
2813 2814 (*flag) |= IBDM_IBMF_PKT_REUSED;
2814 2815 first = B_FALSE;
2815 2816 gid_info->gl_iou->iou_niocs_probe_in_progress++;
2816 2817 }
2817 2818 }
2818 2819
2819 2820
2820 2821 /*
2821 2822 * ibdm_handle_ioc_profile()
2822 2823 * Invoked by the IBMF when the IOCControllerProfile request
2823 2824 * gets completed
2824 2825 */
2825 2826 static void
2826 2827 ibdm_handle_ioc_profile(ibmf_handle_t ibmf_hdl,
2827 2828 ibmf_msg_t *msg, ibdm_dp_gidinfo_t *gid_info, int *flag)
2828 2829 {
2829 2830 int first = B_TRUE, reprobe = 0;
2830 2831 uint_t ii, ioc_no, srv_start;
2831 2832 uint_t nserv_entries;
2832 2833 timeout_id_t timeout_id;
2833 2834 ib_mad_hdr_t *hdr;
2834 2835 ibdm_ioc_info_t *ioc_info;
2835 2836 ibdm_timeout_cb_args_t *cb_args;
2836 2837 ib_dm_ioc_ctrl_profile_t *ioc, *gioc;
2837 2838
2838 2839 IBTF_DPRINTF_L4("ibdm", "\thandle_ioc_profile:"
2839 2840 " ibmf hdl %p msg %p gid info %p", ibmf_hdl, msg, gid_info);
2840 2841
2841 2842 ioc = IBDM_IN_IBMFMSG2IOC(msg);
2842 2843 /*
2843 2844 * Check whether we know this IOC already
2844 2845 * This will return NULL if reprobe is in progress
2845 2846 * IBDM_IOC_STATE_REPROBE_PROGRESS will be set.
2846 2847 * Do not hold mutexes here.
2847 2848 */
2848 2849 if (ibdm_is_ioc_present(ioc->ioc_guid, gid_info, flag) != NULL) {
2849 2850 IBTF_DPRINTF_L4("ibdm", "\thandle_ioc_profile:"
2850 2851 "IOC guid %llx is present", ioc->ioc_guid);
2851 2852 return;
2852 2853 }
2853 2854 ioc_no = IBDM_IN_IBMFMSG_ATTRMOD(msg);
2854 2855 IBTF_DPRINTF_L4("ibdm", "\thandle_ioc_profile: ioc_no = %d", ioc_no-1);
2855 2856
2856 2857 /* Make sure that IOC index is with the valid range */
2857 2858 if (IBDM_IS_IOC_NUM_INVALID(ioc_no, gid_info)) {
2858 2859 IBTF_DPRINTF_L2("ibdm", "\thandle_ioc_profile: "
2859 2860 "IOC index Out of range, index %d", ioc);
2860 2861 (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
2861 2862 return;
2862 2863 }
2863 2864 ioc_info = &gid_info->gl_iou->iou_ioc_info[ioc_no - 1];
2864 2865 ioc_info->ioc_iou_info = gid_info->gl_iou;
2865 2866
2866 2867 mutex_enter(&gid_info->gl_mutex);
2867 2868 if (ioc_info->ioc_state == IBDM_IOC_STATE_REPROBE_PROGRESS) {
2868 2869 reprobe = 1;
2869 2870 ioc_info->ioc_prev_serv = ioc_info->ioc_serv;
2870 2871 ioc_info->ioc_serv = NULL;
2871 2872 ioc_info->ioc_prev_serv_cnt =
2872 2873 ioc_info->ioc_profile.ioc_service_entries;
2873 2874 } else if (ioc_info->ioc_state != IBDM_IOC_STATE_PROBE_INVALID) {
2874 2875 IBTF_DPRINTF_L2("ibdm", "\thandle_ioc_profile: DUP response"
2875 2876 "ioc %d, ioc_state %x", ioc_no - 1, ioc_info->ioc_state);
2876 2877 mutex_exit(&gid_info->gl_mutex);
2877 2878 (*flag) |= IBDM_IBMF_PKT_DUP_RESP;
2878 2879 return;
2879 2880 }
2880 2881 ioc_info->ioc_cb_args.cb_req_type = 0;
2881 2882 if (ioc_info->ioc_timeout_id) {
2882 2883 timeout_id = ioc_info->ioc_timeout_id;
2883 2884 ioc_info->ioc_timeout_id = 0;
2884 2885 mutex_exit(&gid_info->gl_mutex);
2885 2886 IBTF_DPRINTF_L5("ibdm", "handle_ioc_profile: "
2886 2887 "ioc_timeout_id = 0x%x", timeout_id);
2887 2888 if (untimeout(timeout_id) == -1) {
2888 2889 IBTF_DPRINTF_L2("ibdm", "handle_ioc_profile: "
2889 2890 "untimeout ioc_timeout_id failed");
2890 2891 }
2891 2892 mutex_enter(&gid_info->gl_mutex);
2892 2893 }
2893 2894
2894 2895 ioc_info->ioc_state = IBDM_IOC_STATE_PROBE_SUCCESS;
2895 2896 if (reprobe == 0) {
2896 2897 ioc_info->ioc_iou_guid = gid_info->gl_nodeguid;
2897 2898 ioc_info->ioc_nodeguid = gid_info->gl_nodeguid;
2898 2899 }
2899 2900
2900 2901 /*
2901 2902 * Save all the IOC information in the global structures.
2902 2903 * Note the wire format is Big Endian and the Sparc process also
2903 2904 * big endian. So, there is no need to convert the data fields
2904 2905 * The conversion routines used below are ineffective on Sparc
2905 2906 * machines where as they will be effective on little endian
2906 2907 * machines such as Intel processors.
2907 2908 */
2908 2909 gioc = (ib_dm_ioc_ctrl_profile_t *)&ioc_info->ioc_profile;
2909 2910
2910 2911 /*
2911 2912 * Restrict updates to onlyport GIDs and service entries during reprobe
2912 2913 */
2913 2914 if (reprobe == 0) {
2914 2915 gioc->ioc_guid = b2h64(ioc->ioc_guid);
2915 2916 gioc->ioc_vendorid =
2916 2917 ((b2h32(ioc->ioc_vendorid) & IB_DM_VENDORID_MASK)
2917 2918 >> IB_DM_VENDORID_SHIFT);
2918 2919 gioc->ioc_deviceid = b2h32(ioc->ioc_deviceid);
2919 2920 gioc->ioc_device_ver = b2h16(ioc->ioc_device_ver);
2920 2921 gioc->ioc_subsys_vendorid =
2921 2922 ((b2h32(ioc->ioc_subsys_vendorid) & IB_DM_VENDORID_MASK)
2922 2923 >> IB_DM_VENDORID_SHIFT);
2923 2924 gioc->ioc_subsys_id = b2h32(ioc->ioc_subsys_id);
2924 2925 gioc->ioc_io_class = b2h16(ioc->ioc_io_class);
2925 2926 gioc->ioc_io_subclass = b2h16(ioc->ioc_io_subclass);
2926 2927 gioc->ioc_protocol = b2h16(ioc->ioc_protocol);
2927 2928 gioc->ioc_protocol_ver = b2h16(ioc->ioc_protocol_ver);
2928 2929 gioc->ioc_send_msg_qdepth =
2929 2930 b2h16(ioc->ioc_send_msg_qdepth);
2930 2931 gioc->ioc_rdma_read_qdepth =
2931 2932 b2h16(ioc->ioc_rdma_read_qdepth);
2932 2933 gioc->ioc_send_msg_sz = b2h32(ioc->ioc_send_msg_sz);
2933 2934 gioc->ioc_rdma_xfer_sz = b2h32(ioc->ioc_rdma_xfer_sz);
2934 2935 gioc->ioc_ctrl_opcap_mask = ioc->ioc_ctrl_opcap_mask;
2935 2936 bcopy(ioc->ioc_id_string, gioc->ioc_id_string,
2936 2937 IB_DM_IOC_ID_STRING_LEN);
2937 2938
2938 2939 ioc_info->ioc_iou_diagcode = gid_info->gl_iou->iou_diagcode;
2939 2940 ioc_info->ioc_iou_dc_valid = gid_info->gl_iou->iou_dc_valid;
2940 2941 ioc_info->ioc_diagdeviceid = (IB_DM_IOU_DEVICEID_MASK &
2941 2942 gid_info->gl_iou->iou_info.iou_flag) ? B_TRUE : B_FALSE;
2942 2943
2943 2944 if (ioc_info->ioc_diagdeviceid == B_TRUE) {
2944 2945 gid_info->gl_pending_cmds++;
2945 2946 IBTF_DPRINTF_L3(ibdm_string,
2946 2947 "\tibdm_handle_ioc_profile: "
2947 2948 "%d: gid_info %p gl_state %d pending_cmds %d",
2948 2949 __LINE__, gid_info, gid_info->gl_state,
2949 2950 gid_info->gl_pending_cmds);
2950 2951 }
2951 2952 }
2952 2953 gioc->ioc_service_entries = ioc->ioc_service_entries;
2953 2954 mutex_exit(&gid_info->gl_mutex);
2954 2955
2955 2956 ibdm_dump_ioc_profile(gioc);
2956 2957
2957 2958 if ((ioc_info->ioc_diagdeviceid == B_TRUE) && (reprobe == 0)) {
2958 2959 if (ibdm_get_diagcode(gid_info, ioc_no) != IBDM_SUCCESS) {
2959 2960 mutex_enter(&gid_info->gl_mutex);
2960 2961 gid_info->gl_pending_cmds--;
2961 2962 mutex_exit(&gid_info->gl_mutex);
2962 2963 }
2963 2964 }
2964 2965 ioc_info->ioc_serv = (ibdm_srvents_info_t *)kmem_zalloc(
2965 2966 (gioc->ioc_service_entries * sizeof (ibdm_srvents_info_t)),
2966 2967 KM_SLEEP);
2967 2968
2968 2969 /*
2969 2970 * In one single request, maximum number of requests that can be
2970 2971 * obtained is 4. If number of service entries are more than four,
2971 2972 * calculate number requests needed and send them parallelly.
2972 2973 */
2973 2974 nserv_entries = ioc->ioc_service_entries;
2974 2975 ii = 0;
2975 2976 while (nserv_entries) {
2976 2977 mutex_enter(&gid_info->gl_mutex);
2977 2978 gid_info->gl_pending_cmds++;
2978 2979 ibdm_bump_transactionID(gid_info);
2979 2980 mutex_exit(&gid_info->gl_mutex);
2980 2981
2981 2982 if (first != B_TRUE) {
2982 2983 if (ibmf_alloc_msg(ibmf_hdl, IBMF_ALLOC_SLEEP,
2983 2984 &msg) != IBMF_SUCCESS) {
2984 2985 continue;
2985 2986 }
2986 2987
2987 2988 }
2988 2989 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
2989 2990 ibdm_alloc_send_buffers(msg);
2990 2991 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
2991 2992 msg->im_local_addr.ia_local_lid = gid_info->gl_slid;
2992 2993 msg->im_local_addr.ia_remote_lid = gid_info->gl_dlid;
2993 2994 if (gid_info->gl_redirected == B_TRUE) {
2994 2995 if (gid_info->gl_redirect_dlid != 0) {
2995 2996 msg->im_local_addr.ia_remote_lid =
2996 2997 gid_info->gl_redirect_dlid;
2997 2998 }
2998 2999 msg->im_local_addr.ia_remote_qno =
2999 3000 gid_info->gl_redirect_QP;
3000 3001 msg->im_local_addr.ia_p_key =
3001 3002 gid_info->gl_redirect_pkey;
3002 3003 msg->im_local_addr.ia_q_key =
3003 3004 gid_info->gl_redirect_qkey;
3004 3005 msg->im_local_addr.ia_service_level =
3005 3006 gid_info->gl_redirectSL;
3006 3007 } else {
3007 3008 msg->im_local_addr.ia_remote_qno = 1;
3008 3009 msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
3009 3010 msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
3010 3011 msg->im_local_addr.ia_service_level = gid_info->gl_SL;
3011 3012 }
3012 3013
3013 3014 hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
3014 3015 hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
3015 3016 hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
3016 3017 hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
3017 3018 hdr->R_Method = IB_DM_DEVMGT_METHOD_GET;
3018 3019 hdr->Status = 0;
3019 3020 hdr->TransactionID = h2b64(gid_info->gl_transactionID);
3020 3021 hdr->AttributeID = h2b16(IB_DM_ATTR_SERVICE_ENTRIES);
3021 3022
3022 3023 srv_start = ii * 4;
3023 3024 cb_args = &ioc_info->ioc_serv[srv_start].se_cb_args;
3024 3025 cb_args->cb_gid_info = gid_info;
3025 3026 cb_args->cb_retry_count = ibdm_dft_retry_cnt;
3026 3027 cb_args->cb_req_type = IBDM_REQ_TYPE_SRVENTS;
3027 3028 cb_args->cb_srvents_start = srv_start;
3028 3029 cb_args->cb_ioc_num = ioc_no - 1;
3029 3030
3030 3031 if (nserv_entries >= IBDM_MAX_SERV_ENTRIES_PER_REQ) {
3031 3032 nserv_entries -= IBDM_MAX_SERV_ENTRIES_PER_REQ;
3032 3033 cb_args->cb_srvents_end = (cb_args->cb_srvents_start +
3033 3034 IBDM_MAX_SERV_ENTRIES_PER_REQ - 1);
3034 3035 } else {
3035 3036 cb_args->cb_srvents_end =
3036 3037 (cb_args->cb_srvents_start + nserv_entries - 1);
3037 3038 nserv_entries = 0;
3038 3039 }
3039 3040 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*hdr))
3040 3041 ibdm_fill_srv_attr_mod(hdr, cb_args);
3041 3042 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*hdr))
3042 3043
3043 3044 mutex_enter(&gid_info->gl_mutex);
3044 3045 ioc_info->ioc_serv[srv_start].se_timeout_id = timeout(
3045 3046 ibdm_pkt_timeout_hdlr, cb_args,
3046 3047 IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
3047 3048 mutex_exit(&gid_info->gl_mutex);
3048 3049
3049 3050 IBTF_DPRINTF_L5("ibdm", "\thandle_ioc_profile:"
3050 3051 "timeout %x, ioc %d srv %d",
3051 3052 ioc_info->ioc_serv[srv_start].se_timeout_id,
3052 3053 ioc_no - 1, srv_start);
3053 3054
3054 3055 if (ibmf_msg_transport(ibmf_hdl, gid_info->gl_qp_hdl, msg,
3055 3056 NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
3056 3057 IBTF_DPRINTF_L2("ibdm",
3057 3058 "\thandle_ioc_profile: msg send failed");
3058 3059 ibdm_ibmf_send_cb(ibmf_hdl, msg, cb_args);
3059 3060 }
3060 3061 (*flag) |= IBDM_IBMF_PKT_REUSED;
3061 3062 first = B_FALSE;
3062 3063 ii++;
3063 3064 }
3064 3065 }
3065 3066
3066 3067
3067 3068 /*
3068 3069 * ibdm_handle_srventry_mad()
3069 3070 */
3070 3071 static void
3071 3072 ibdm_handle_srventry_mad(ibmf_msg_t *msg,
3072 3073 ibdm_dp_gidinfo_t *gid_info, int *flag)
3073 3074 {
3074 3075 uint_t ii, ioc_no, attrmod;
3075 3076 uint_t nentries, start, end;
3076 3077 timeout_id_t timeout_id;
3077 3078 ib_dm_srv_t *srv_ents;
3078 3079 ibdm_ioc_info_t *ioc_info;
3079 3080 ibdm_srvents_info_t *gsrv_ents;
3080 3081
3081 3082 IBTF_DPRINTF_L4("ibdm", "\thandle_srventry_mad:"
3082 3083 " IBMF msg %p gid info %p", msg, gid_info);
3083 3084
3084 3085 srv_ents = IBDM_IN_IBMFMSG2SRVENT(msg);
3085 3086 /*
3086 3087 * Get the start and end index of the service entries
3087 3088 * Upper 16 bits identify the IOC
3088 3089 * Lower 16 bits specify the range of service entries
3089 3090 * LSB specifies (Big endian) end of the range
3090 3091 * MSB specifies (Big endian) start of the range
3091 3092 */
3092 3093 attrmod = IBDM_IN_IBMFMSG_ATTRMOD(msg);
3093 3094 ioc_no = ((attrmod >> 16) & IBDM_16_BIT_MASK);
3094 3095 end = ((attrmod >> 8) & IBDM_8_BIT_MASK);
3095 3096 start = (attrmod & IBDM_8_BIT_MASK);
3096 3097
3097 3098 /* Make sure that IOC index is with the valid range */
3098 3099 if ((ioc_no < 1) |
3099 3100 (ioc_no > gid_info->gl_iou->iou_info.iou_num_ctrl_slots)) {
3100 3101 IBTF_DPRINTF_L2("ibdm", "\thandle_srventry_mad: "
3101 3102 "IOC index Out of range, index %d", ioc_no);
3102 3103 (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
3103 3104 return;
3104 3105 }
3105 3106 ioc_info = IBDM_GIDINFO2IOCINFO(gid_info, (ioc_no -1));
3106 3107
3107 3108 /*
3108 3109 * Make sure that the "start" and "end" service indexes are
3109 3110 * with in the valid range
3110 3111 */
3111 3112 nentries = ioc_info->ioc_profile.ioc_service_entries;
3112 3113 if ((start > end) | (start >= nentries) | (end >= nentries)) {
3113 3114 IBTF_DPRINTF_L2("ibdm", "\thandle_srventry_mad: "
3114 3115 "Attr modifier 0x%x, #Serv entries %d", attrmod, nentries);
3115 3116 (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
3116 3117 return;
3117 3118 }
3118 3119 gsrv_ents = &ioc_info->ioc_serv[start];
3119 3120 mutex_enter(&gid_info->gl_mutex);
3120 3121 if (gsrv_ents->se_state != IBDM_SE_INVALID) {
3121 3122 IBTF_DPRINTF_L2("ibdm", "\thandle_srventry_mad: "
3122 3123 "already known, ioc %d, srv %d, se_state %x",
3123 3124 ioc_no - 1, start, gsrv_ents->se_state);
3124 3125 mutex_exit(&gid_info->gl_mutex);
3125 3126 (*flag) |= IBDM_IBMF_PKT_DUP_RESP;
3126 3127 return;
3127 3128 }
3128 3129 ioc_info->ioc_serv[start].se_cb_args.cb_req_type = 0;
3129 3130 if (ioc_info->ioc_serv[start].se_timeout_id) {
3130 3131 IBTF_DPRINTF_L2("ibdm",
3131 3132 "\thandle_srventry_mad: ioc %d start %d", ioc_no, start);
3132 3133 timeout_id = ioc_info->ioc_serv[start].se_timeout_id;
3133 3134 ioc_info->ioc_serv[start].se_timeout_id = 0;
3134 3135 mutex_exit(&gid_info->gl_mutex);
3135 3136 IBTF_DPRINTF_L5("ibdm", "handle_srverntry_mad: "
3136 3137 "se_timeout_id = 0x%x", timeout_id);
3137 3138 if (untimeout(timeout_id) == -1) {
3138 3139 IBTF_DPRINTF_L2("ibdm", "handle_srventry_mad: "
3139 3140 "untimeout se_timeout_id failed");
3140 3141 }
3141 3142 mutex_enter(&gid_info->gl_mutex);
3142 3143 }
3143 3144
3144 3145 gsrv_ents->se_state = IBDM_SE_VALID;
3145 3146 mutex_exit(&gid_info->gl_mutex);
3146 3147 for (ii = start; ii <= end; ii++, srv_ents++, gsrv_ents++) {
3147 3148 gsrv_ents->se_attr.srv_id = b2h64(srv_ents->srv_id);
3148 3149 bcopy(srv_ents->srv_name,
3149 3150 gsrv_ents->se_attr.srv_name, IB_DM_MAX_SVC_NAME_LEN);
3150 3151 ibdm_dump_service_entries(&gsrv_ents->se_attr);
3151 3152 }
3152 3153 }
3153 3154
3154 3155
3155 3156 /*
3156 3157 * ibdm_get_diagcode:
3157 3158 * Send request to get IOU/IOC diag code
3158 3159 * Returns IBDM_SUCCESS/IBDM_FAILURE
3159 3160 */
3160 3161 static int
3161 3162 ibdm_get_diagcode(ibdm_dp_gidinfo_t *gid_info, int attr)
3162 3163 {
3163 3164 ibmf_msg_t *msg;
3164 3165 ib_mad_hdr_t *hdr;
3165 3166 ibdm_ioc_info_t *ioc;
3166 3167 ibdm_timeout_cb_args_t *cb_args;
3167 3168 timeout_id_t *timeout_id;
3168 3169
3169 3170 IBTF_DPRINTF_L4("ibdm", "\tget_diagcode: gid info %p, attr = %d",
3170 3171 gid_info, attr);
3171 3172
3172 3173 if (ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_SLEEP,
3173 3174 &msg) != IBMF_SUCCESS) {
3174 3175 IBTF_DPRINTF_L4("ibdm", "\tget_diagcode: pkt alloc fail");
3175 3176 return (IBDM_FAILURE);
3176 3177 }
3177 3178
3178 3179 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
3179 3180 ibdm_alloc_send_buffers(msg);
3180 3181 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
3181 3182
3182 3183 mutex_enter(&gid_info->gl_mutex);
3183 3184 ibdm_bump_transactionID(gid_info);
3184 3185 mutex_exit(&gid_info->gl_mutex);
3185 3186
3186 3187 msg->im_local_addr.ia_local_lid = gid_info->gl_slid;
3187 3188 msg->im_local_addr.ia_remote_lid = gid_info->gl_dlid;
3188 3189 if (gid_info->gl_redirected == B_TRUE) {
3189 3190 if (gid_info->gl_redirect_dlid != 0) {
3190 3191 msg->im_local_addr.ia_remote_lid =
3191 3192 gid_info->gl_redirect_dlid;
3192 3193 }
3193 3194
3194 3195 msg->im_local_addr.ia_remote_qno = gid_info->gl_redirect_QP;
3195 3196 msg->im_local_addr.ia_p_key = gid_info->gl_redirect_pkey;
3196 3197 msg->im_local_addr.ia_q_key = gid_info->gl_redirect_qkey;
3197 3198 msg->im_local_addr.ia_service_level = gid_info->gl_redirectSL;
3198 3199 } else {
3199 3200 msg->im_local_addr.ia_remote_qno = 1;
3200 3201 msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
3201 3202 msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
3202 3203 msg->im_local_addr.ia_service_level = gid_info->gl_SL;
3203 3204 }
3204 3205
3205 3206 hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
3206 3207 hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
3207 3208 hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
3208 3209 hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
3209 3210 hdr->R_Method = IB_DM_DEVMGT_METHOD_GET;
3210 3211 hdr->Status = 0;
3211 3212 hdr->TransactionID = h2b64(gid_info->gl_transactionID);
3212 3213
3213 3214 hdr->AttributeID = h2b16(IB_DM_ATTR_DIAG_CODE);
3214 3215 hdr->AttributeModifier = h2b32(attr);
3215 3216
3216 3217 if (attr == 0) {
3217 3218 cb_args = &gid_info->gl_iou_cb_args;
3218 3219 gid_info->gl_iou->iou_dc_valid = B_FALSE;
3219 3220 cb_args->cb_ioc_num = 0;
3220 3221 cb_args->cb_req_type = IBDM_REQ_TYPE_IOU_DIAGCODE;
3221 3222 timeout_id = &gid_info->gl_timeout_id;
3222 3223 } else {
3223 3224 ioc = IBDM_GIDINFO2IOCINFO(gid_info, (attr - 1));
3224 3225 ioc->ioc_dc_valid = B_FALSE;
3225 3226 cb_args = &ioc->ioc_dc_cb_args;
3226 3227 cb_args->cb_ioc_num = attr - 1;
3227 3228 cb_args->cb_req_type = IBDM_REQ_TYPE_IOC_DIAGCODE;
3228 3229 timeout_id = &ioc->ioc_dc_timeout_id;
3229 3230 }
3230 3231 cb_args->cb_gid_info = gid_info;
3231 3232 cb_args->cb_retry_count = ibdm_dft_retry_cnt;
3232 3233 cb_args->cb_srvents_start = 0;
3233 3234
3234 3235 mutex_enter(&gid_info->gl_mutex);
3235 3236 *timeout_id = timeout(ibdm_pkt_timeout_hdlr,
3236 3237 cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
3237 3238 mutex_exit(&gid_info->gl_mutex);
3238 3239
3239 3240 IBTF_DPRINTF_L5("ibdm", "\tget_diagcode:"
3240 3241 "timeout %x, ioc %d", *timeout_id, cb_args->cb_ioc_num);
3241 3242
3242 3243 if (ibmf_msg_transport(gid_info->gl_ibmf_hdl, gid_info->gl_qp_hdl,
3243 3244 msg, NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
3244 3245 IBTF_DPRINTF_L2("ibdm", "\tget_diagcode: ibmf send failed");
3245 3246 ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl, msg, cb_args);
3246 3247 }
3247 3248 return (IBDM_SUCCESS);
3248 3249 }
3249 3250
3250 3251 /*
3251 3252 * ibdm_handle_diagcode:
3252 3253 * Process the DiagCode MAD response and update local DM
3253 3254 * data structure.
3254 3255 */
3255 3256 static void
3256 3257 ibdm_handle_diagcode(ibmf_msg_t *ibmf_msg,
3257 3258 ibdm_dp_gidinfo_t *gid_info, int *flag)
3258 3259 {
3259 3260 uint16_t attrmod, *diagcode;
3260 3261 ibdm_iou_info_t *iou;
3261 3262 ibdm_ioc_info_t *ioc;
3262 3263 timeout_id_t timeout_id;
3263 3264 ibdm_timeout_cb_args_t *cb_args;
3264 3265
3265 3266 diagcode = (uint16_t *)ibmf_msg->im_msgbufs_recv.im_bufs_cl_data;
3266 3267
3267 3268 mutex_enter(&gid_info->gl_mutex);
3268 3269 attrmod = IBDM_IN_IBMFMSG_ATTRMOD(ibmf_msg);
3269 3270 iou = gid_info->gl_iou;
3270 3271 if (attrmod == 0) {
3271 3272 if (iou->iou_dc_valid != B_FALSE) {
3272 3273 (*flag) |= IBDM_IBMF_PKT_DUP_RESP;
3273 3274 IBTF_DPRINTF_L4("ibdm",
3274 3275 "\thandle_diagcode: Duplicate IOU DiagCode");
3275 3276 mutex_exit(&gid_info->gl_mutex);
3276 3277 return;
3277 3278 }
3278 3279 cb_args = &gid_info->gl_iou_cb_args;
3279 3280 cb_args->cb_req_type = 0;
3280 3281 iou->iou_diagcode = b2h16(*diagcode);
3281 3282 iou->iou_dc_valid = B_TRUE;
3282 3283 if (gid_info->gl_timeout_id) {
3283 3284 timeout_id = gid_info->gl_timeout_id;
3284 3285 mutex_exit(&gid_info->gl_mutex);
3285 3286 IBTF_DPRINTF_L5("ibdm", "\thandle_diagcode: "
3286 3287 "gl_timeout_id = 0x%x", timeout_id);
3287 3288 if (untimeout(timeout_id) == -1) {
3288 3289 IBTF_DPRINTF_L2("ibdm", "handle_diagcode: "
3289 3290 "untimeout gl_timeout_id failed");
3290 3291 }
3291 3292 mutex_enter(&gid_info->gl_mutex);
3292 3293 gid_info->gl_timeout_id = 0;
3293 3294 }
3294 3295 } else {
3295 3296 ioc = IBDM_GIDINFO2IOCINFO(gid_info, (attrmod - 1));
3296 3297 if (ioc->ioc_dc_valid != B_FALSE) {
3297 3298 (*flag) |= IBDM_IBMF_PKT_DUP_RESP;
3298 3299 IBTF_DPRINTF_L4("ibdm",
3299 3300 "\thandle_diagcode: Duplicate IOC DiagCode");
3300 3301 mutex_exit(&gid_info->gl_mutex);
3301 3302 return;
3302 3303 }
3303 3304 cb_args = &ioc->ioc_dc_cb_args;
3304 3305 cb_args->cb_req_type = 0;
3305 3306 ioc->ioc_diagcode = b2h16(*diagcode);
3306 3307 ioc->ioc_dc_valid = B_TRUE;
3307 3308 timeout_id = iou->iou_ioc_info[attrmod - 1].ioc_dc_timeout_id;
3308 3309 if (timeout_id) {
3309 3310 iou->iou_ioc_info[attrmod - 1].ioc_dc_timeout_id = 0;
3310 3311 mutex_exit(&gid_info->gl_mutex);
3311 3312 IBTF_DPRINTF_L5("ibdm", "handle_diagcode: "
3312 3313 "timeout_id = 0x%x", timeout_id);
3313 3314 if (untimeout(timeout_id) == -1) {
3314 3315 IBTF_DPRINTF_L2("ibdm", "\thandle_diagcode: "
3315 3316 "untimeout ioc_dc_timeout_id failed");
3316 3317 }
3317 3318 mutex_enter(&gid_info->gl_mutex);
3318 3319 }
3319 3320 }
3320 3321 mutex_exit(&gid_info->gl_mutex);
3321 3322
3322 3323 IBTF_DPRINTF_L4("ibdm", "\thandle_diagcode: DiagCode : 0x%x"
3323 3324 "attrmod : 0x%x", b2h16(*diagcode), attrmod);
3324 3325 }
3325 3326
3326 3327
3327 3328 /*
3328 3329 * ibdm_is_ioc_present()
3329 3330 * Return ibdm_ioc_info_t if IOC guid is found in the global gid list
3330 3331 */
3331 3332 static ibdm_ioc_info_t *
3332 3333 ibdm_is_ioc_present(ib_guid_t ioc_guid,
3333 3334 ibdm_dp_gidinfo_t *gid_info, int *flag)
3334 3335 {
3335 3336 int ii;
3336 3337 ibdm_ioc_info_t *ioc;
3337 3338 ibdm_dp_gidinfo_t *head;
3338 3339 ib_dm_io_unitinfo_t *iou;
3339 3340
3340 3341 mutex_enter(&ibdm.ibdm_mutex);
3341 3342 head = ibdm.ibdm_dp_gidlist_head;
3342 3343 while (head) {
3343 3344 mutex_enter(&head->gl_mutex);
3344 3345 if (head->gl_iou == NULL) {
3345 3346 mutex_exit(&head->gl_mutex);
3346 3347 head = head->gl_next;
3347 3348 continue;
3348 3349 }
3349 3350 iou = &head->gl_iou->iou_info;
3350 3351 for (ii = 0; ii < iou->iou_num_ctrl_slots; ii++) {
3351 3352 ioc = IBDM_GIDINFO2IOCINFO(head, ii);
3352 3353 if ((ioc->ioc_state == IBDM_IOC_STATE_PROBE_SUCCESS) &&
3353 3354 (ioc->ioc_profile.ioc_guid == ioc_guid)) {
3354 3355 if (gid_info == head) {
3355 3356 *flag |= IBDM_IBMF_PKT_DUP_RESP;
3356 3357 } else if (ibdm_check_dgid(head->gl_dgid_lo,
3357 3358 head->gl_dgid_hi) != NULL) {
3358 3359 IBTF_DPRINTF_L4("ibdm", "\tis_ioc_"
3359 3360 "present: gid not present");
3360 3361 ibdm_add_to_gl_gid(gid_info, head);
3361 3362 }
3362 3363 mutex_exit(&head->gl_mutex);
3363 3364 mutex_exit(&ibdm.ibdm_mutex);
3364 3365 return (ioc);
3365 3366 }
3366 3367 }
3367 3368 mutex_exit(&head->gl_mutex);
3368 3369 head = head->gl_next;
3369 3370 }
3370 3371 mutex_exit(&ibdm.ibdm_mutex);
3371 3372 return (NULL);
3372 3373 }
3373 3374
3374 3375
3375 3376 /*
3376 3377 * ibdm_ibmf_send_cb()
3377 3378 * IBMF invokes this callback routine after posting the DM MAD to
3378 3379 * the HCA.
3379 3380 */
3380 3381 /*ARGSUSED*/
3381 3382 static void
3382 3383 ibdm_ibmf_send_cb(ibmf_handle_t ibmf_hdl, ibmf_msg_t *ibmf_msg, void *arg)
3383 3384 {
3384 3385 ibdm_dump_ibmf_msg(ibmf_msg, 1);
3385 3386 ibdm_free_send_buffers(ibmf_msg);
3386 3387 if (ibmf_free_msg(ibmf_hdl, &ibmf_msg) != IBMF_SUCCESS) {
3387 3388 IBTF_DPRINTF_L4("ibdm",
3388 3389 "\tibmf_send_cb: IBMF free msg failed");
3389 3390 }
3390 3391 }
3391 3392
3392 3393
3393 3394 /*
3394 3395 * ibdm_ibmf_recv_cb()
3395 3396 * Invoked by the IBMF when a response to the one of the DM requests
3396 3397 * is received.
3397 3398 */
3398 3399 /*ARGSUSED*/
3399 3400 static void
3400 3401 ibdm_ibmf_recv_cb(ibmf_handle_t ibmf_hdl, ibmf_msg_t *msg, void *arg)
3401 3402 {
3402 3403 ibdm_taskq_args_t *taskq_args;
3403 3404
3404 3405 /*
3405 3406 * If the taskq enable is set then dispatch a taskq to process
3406 3407 * the MAD, otherwise just process it on this thread
3407 3408 */
3408 3409 if (ibdm_taskq_enable != IBDM_ENABLE_TASKQ_HANDLING) {
3409 3410 ibdm_process_incoming_mad(ibmf_hdl, msg, arg);
3410 3411 return;
3411 3412 }
3412 3413
3413 3414 /*
3414 3415 * create a taskq and dispatch it to process the incoming MAD
3415 3416 */
3416 3417 taskq_args = kmem_alloc(sizeof (ibdm_taskq_args_t), KM_NOSLEEP);
3417 3418 if (taskq_args == NULL) {
3418 3419 IBTF_DPRINTF_L2("ibdm", "ibmf_recv_cb: kmem_alloc failed for"
3419 3420 "taskq_args");
3420 3421 if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
3421 3422 IBTF_DPRINTF_L4("ibmf_recv_cb",
3422 3423 "\tibmf_recv_cb: IBMF free msg failed");
3423 3424 }
3424 3425 return;
3425 3426 }
3426 3427 taskq_args->tq_ibmf_handle = ibmf_hdl;
3427 3428 taskq_args->tq_ibmf_msg = msg;
3428 3429 taskq_args->tq_args = arg;
3429 3430
3430 3431 if (taskq_dispatch(system_taskq, ibdm_recv_incoming_mad, taskq_args,
3431 3432 TQ_NOSLEEP) == 0) {
3432 3433 IBTF_DPRINTF_L2("ibdm", "ibmf_recv_cb: taskq_dispatch failed");
3433 3434 if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
3434 3435 IBTF_DPRINTF_L4("ibmf_recv_cb",
3435 3436 "\tibmf_recv_cb: IBMF free msg failed");
3436 3437 }
3437 3438 kmem_free(taskq_args, sizeof (ibdm_taskq_args_t));
3438 3439 return;
3439 3440 }
3440 3441
3441 3442 /* taskq_args are deleted in ibdm_recv_incoming_mad() */
3442 3443 }
3443 3444
3444 3445
3445 3446 void
3446 3447 ibdm_recv_incoming_mad(void *args)
3447 3448 {
3448 3449 ibdm_taskq_args_t *taskq_args;
3449 3450
3450 3451 taskq_args = (ibdm_taskq_args_t *)args;
3451 3452
3452 3453 IBTF_DPRINTF_L4("ibdm", "\tibdm_recv_incoming_mad: "
3453 3454 "Processing incoming MAD via taskq");
3454 3455
3455 3456 ibdm_process_incoming_mad(taskq_args->tq_ibmf_handle,
3456 3457 taskq_args->tq_ibmf_msg, taskq_args->tq_args);
3457 3458
3458 3459 kmem_free(taskq_args, sizeof (ibdm_taskq_args_t));
3459 3460 }
3460 3461
3461 3462
3462 3463 /*
3463 3464 * Calls ibdm_process_incoming_mad with all function arguments extracted
3464 3465 * from args
3465 3466 */
3466 3467 /*ARGSUSED*/
3467 3468 static void
3468 3469 ibdm_process_incoming_mad(ibmf_handle_t ibmf_hdl, ibmf_msg_t *msg, void *arg)
3469 3470 {
3470 3471 int flag = 0;
3471 3472 int ret;
3472 3473 uint64_t transaction_id;
3473 3474 ib_mad_hdr_t *hdr;
3474 3475 ibdm_dp_gidinfo_t *gid_info = NULL;
3475 3476
3476 3477 IBTF_DPRINTF_L4("ibdm",
3477 3478 "\tprocess_incoming_mad: ibmf hdl %p pkt %p", ibmf_hdl, msg);
3478 3479 ibdm_dump_ibmf_msg(msg, 0);
3479 3480
3480 3481 /*
3481 3482 * IBMF calls this routine for every DM MAD that arrives at this port.
3482 3483 * But we handle only the responses for requests we sent. We drop all
3483 3484 * the DM packets that does not have response bit set in the MAD
3484 3485 * header(this eliminates all the requests sent to this port).
3485 3486 * We handle only DM class version 1 MAD's
3486 3487 */
3487 3488 hdr = IBDM_IN_IBMFMSG_MADHDR(msg);
3488 3489 if (ibdm_verify_mad_status(hdr) != IBDM_SUCCESS) {
3489 3490 if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
3490 3491 IBTF_DPRINTF_L2("ibdm", "\tprocess_incoming_mad: "
3491 3492 "IBMF free msg failed DM request drop it");
3492 3493 }
3493 3494 return;
3494 3495 }
3495 3496
3496 3497 transaction_id = b2h64(hdr->TransactionID);
3497 3498
3498 3499 mutex_enter(&ibdm.ibdm_mutex);
3499 3500 gid_info = ibdm.ibdm_dp_gidlist_head;
3500 3501 while (gid_info) {
3501 3502 if ((gid_info->gl_transactionID &
3502 3503 IBDM_GID_TRANSACTIONID_MASK) ==
3503 3504 (transaction_id & IBDM_GID_TRANSACTIONID_MASK))
3504 3505 break;
3505 3506 gid_info = gid_info->gl_next;
3506 3507 }
3507 3508 mutex_exit(&ibdm.ibdm_mutex);
3508 3509
3509 3510 if (gid_info == NULL) {
3510 3511 /* Drop the packet */
3511 3512 IBTF_DPRINTF_L2("ibdm", "process_incoming_mad: transaction ID"
3512 3513 " does not match: 0x%llx", transaction_id);
3513 3514 if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
3514 3515 IBTF_DPRINTF_L2("ibdm", "process_incoming_mad: "
3515 3516 "IBMF free msg failed DM request drop it");
3516 3517 }
3517 3518 return;
3518 3519 }
3519 3520
3520 3521 /* Handle redirection for all the MAD's, except ClassPortInfo */
3521 3522 if (((IBDM_IN_IBMFMSG_STATUS(msg) & MAD_STATUS_REDIRECT_REQUIRED)) &&
3522 3523 (IBDM_IN_IBMFMSG_ATTR(msg) != IB_DM_ATTR_CLASSPORTINFO)) {
3523 3524 ret = ibdm_handle_redirection(msg, gid_info, &flag);
3524 3525 if (ret == IBDM_SUCCESS) {
3525 3526 return;
3526 3527 }
3527 3528 } else {
3528 3529 uint_t gl_state;
3529 3530
3530 3531 mutex_enter(&gid_info->gl_mutex);
3531 3532 gl_state = gid_info->gl_state;
3532 3533 mutex_exit(&gid_info->gl_mutex);
3533 3534
3534 3535 switch (gl_state) {
3535 3536
3536 3537 case IBDM_SET_CLASSPORTINFO:
3537 3538 ibdm_handle_setclassportinfo(
3538 3539 ibmf_hdl, msg, gid_info, &flag);
3539 3540 break;
3540 3541
3541 3542 case IBDM_GET_CLASSPORTINFO:
3542 3543 ibdm_handle_classportinfo(
3543 3544 ibmf_hdl, msg, gid_info, &flag);
3544 3545 break;
3545 3546
3546 3547 case IBDM_GET_IOUNITINFO:
3547 3548 ibdm_handle_iounitinfo(ibmf_hdl, msg, gid_info, &flag);
3548 3549 break;
3549 3550
3550 3551 case IBDM_GET_IOC_DETAILS:
3551 3552 switch (IBDM_IN_IBMFMSG_ATTR(msg)) {
3552 3553
3553 3554 case IB_DM_ATTR_SERVICE_ENTRIES:
3554 3555 ibdm_handle_srventry_mad(msg, gid_info, &flag);
3555 3556 break;
3556 3557
3557 3558 case IB_DM_ATTR_IOC_CTRL_PROFILE:
3558 3559 ibdm_handle_ioc_profile(
3559 3560 ibmf_hdl, msg, gid_info, &flag);
3560 3561 break;
3561 3562
3562 3563 case IB_DM_ATTR_DIAG_CODE:
3563 3564 ibdm_handle_diagcode(msg, gid_info, &flag);
3564 3565 break;
3565 3566
3566 3567 default:
3567 3568 IBTF_DPRINTF_L2("ibdm", "process_incoming_mad: "
3568 3569 "Error state, wrong attribute :-(");
3569 3570 (void) ibmf_free_msg(ibmf_hdl, &msg);
3570 3571 return;
3571 3572 }
3572 3573 break;
3573 3574 default:
3574 3575 IBTF_DPRINTF_L2("ibdm",
3575 3576 "process_incoming_mad: Dropping the packet"
3576 3577 " gl_state %x", gl_state);
3577 3578 if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
3578 3579 IBTF_DPRINTF_L2("ibdm", "process_incoming_mad: "
3579 3580 "IBMF free msg failed DM request drop it");
3580 3581 }
3581 3582 return;
3582 3583 }
3583 3584 }
3584 3585
3585 3586 if ((flag & IBDM_IBMF_PKT_DUP_RESP) ||
3586 3587 (flag & IBDM_IBMF_PKT_UNEXP_RESP)) {
3587 3588 IBTF_DPRINTF_L2("ibdm",
3588 3589 "\tprocess_incoming_mad:Dup/unexp resp : 0x%x", flag);
3589 3590 if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
3590 3591 IBTF_DPRINTF_L2("ibdm", "process_incoming_mad: "
3591 3592 "IBMF free msg failed DM request drop it");
3592 3593 }
3593 3594 return;
3594 3595 }
3595 3596
3596 3597 mutex_enter(&gid_info->gl_mutex);
3597 3598 if (gid_info->gl_pending_cmds < 1) {
3598 3599 IBTF_DPRINTF_L2("ibdm",
3599 3600 "\tprocess_incoming_mad: pending commands negative");
3600 3601 }
3601 3602 if (--gid_info->gl_pending_cmds) {
3602 3603 IBTF_DPRINTF_L4("ibdm", "\tprocess_incoming_mad: "
3603 3604 "gid_info %p pending cmds %d",
3604 3605 gid_info, gid_info->gl_pending_cmds);
3605 3606 mutex_exit(&gid_info->gl_mutex);
3606 3607 } else {
3607 3608 uint_t prev_state;
3608 3609 IBTF_DPRINTF_L4("ibdm", "\tprocess_incoming_mad: Probing DONE");
3609 3610 prev_state = gid_info->gl_state;
3610 3611 gid_info->gl_state = IBDM_GID_PROBING_COMPLETE;
3611 3612 if (prev_state == IBDM_SET_CLASSPORTINFO) {
3612 3613 IBTF_DPRINTF_L4("ibdm",
3613 3614 "\tprocess_incoming_mad: "
3614 3615 "Setclassportinfo for Cisco FC GW is done.");
3615 3616 gid_info->gl_flag &= ~IBDM_CISCO_PROBE;
3616 3617 gid_info->gl_flag |= IBDM_CISCO_PROBE_DONE;
3617 3618 mutex_exit(&gid_info->gl_mutex);
3618 3619 cv_broadcast(&gid_info->gl_probe_cv);
3619 3620 } else {
3620 3621 mutex_exit(&gid_info->gl_mutex);
3621 3622 ibdm_notify_newgid_iocs(gid_info);
3622 3623 mutex_enter(&ibdm.ibdm_mutex);
3623 3624 if (--ibdm.ibdm_ngid_probes_in_progress == 0) {
3624 3625 IBTF_DPRINTF_L4("ibdm",
3625 3626 "\tprocess_incoming_mad: Wakeup");
3626 3627 ibdm.ibdm_busy &= ~IBDM_PROBE_IN_PROGRESS;
3627 3628 cv_broadcast(&ibdm.ibdm_probe_cv);
3628 3629 }
3629 3630 mutex_exit(&ibdm.ibdm_mutex);
3630 3631 }
3631 3632 }
3632 3633
3633 3634 /*
3634 3635 * Do not deallocate the IBMF packet if atleast one request
3635 3636 * is posted. IBMF packet is reused.
3636 3637 */
3637 3638 if (!(flag & IBDM_IBMF_PKT_REUSED)) {
3638 3639 if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
3639 3640 IBTF_DPRINTF_L2("ibdm", "\tprocess_incoming_mad: "
3640 3641 "IBMF free msg failed DM request drop it");
3641 3642 }
3642 3643 }
3643 3644 }
3644 3645
3645 3646
3646 3647 /*
3647 3648 * ibdm_verify_mad_status()
3648 3649 * Verifies the MAD status
3649 3650 * Returns IBDM_SUCCESS if status is correct
3650 3651 * Returns IBDM_FAILURE for bogus MAD status
3651 3652 */
3652 3653 static int
3653 3654 ibdm_verify_mad_status(ib_mad_hdr_t *hdr)
3654 3655 {
3655 3656 int ret = 0;
3656 3657
3657 3658 if ((hdr->R_Method != IB_DM_DEVMGT_METHOD_GET_RESP) ||
3658 3659 (hdr->ClassVersion != IB_DM_CLASS_VERSION_1)) {
3659 3660 return (IBDM_FAILURE);
3660 3661 }
3661 3662
3662 3663 if (b2h16(hdr->Status) == 0)
3663 3664 ret = IBDM_SUCCESS;
3664 3665 else if ((b2h16(hdr->Status) & 0x1f) == MAD_STATUS_REDIRECT_REQUIRED)
3665 3666 ret = IBDM_SUCCESS;
3666 3667 else {
3667 3668 IBTF_DPRINTF_L2("ibdm",
3668 3669 "\tverify_mad_status: Status : 0x%x", b2h16(hdr->Status));
3669 3670 ret = IBDM_FAILURE;
3670 3671 }
3671 3672 return (ret);
3672 3673 }
3673 3674
3674 3675
3675 3676
3676 3677 /*
3677 3678 * ibdm_handle_redirection()
3678 3679 * Returns IBDM_SUCCESS/IBDM_FAILURE
3679 3680 */
3680 3681 static int
3681 3682 ibdm_handle_redirection(ibmf_msg_t *msg,
3682 3683 ibdm_dp_gidinfo_t *gid_info, int *flag)
3683 3684 {
3684 3685 int attrmod, ioc_no, start;
3685 3686 void *data;
3686 3687 timeout_id_t *timeout_id;
3687 3688 ib_mad_hdr_t *hdr;
3688 3689 ibdm_ioc_info_t *ioc = NULL;
3689 3690 ibdm_timeout_cb_args_t *cb_args;
3690 3691 ib_mad_classportinfo_t *cpi;
3691 3692
3692 3693 IBTF_DPRINTF_L4("ibdm", "\thandle_redirection: Enter");
3693 3694 mutex_enter(&gid_info->gl_mutex);
3694 3695 switch (gid_info->gl_state) {
3695 3696 case IBDM_GET_IOUNITINFO:
3696 3697 cb_args = &gid_info->gl_iou_cb_args;
3697 3698 timeout_id = &gid_info->gl_timeout_id;
3698 3699 break;
3699 3700
3700 3701 case IBDM_GET_IOC_DETAILS:
3701 3702 attrmod = IBDM_IN_IBMFMSG_ATTRMOD(msg);
3702 3703 switch (IBDM_IN_IBMFMSG_ATTR(msg)) {
3703 3704
3704 3705 case IB_DM_ATTR_DIAG_CODE:
3705 3706 if (attrmod == 0) {
3706 3707 cb_args = &gid_info->gl_iou_cb_args;
3707 3708 timeout_id = &gid_info->gl_timeout_id;
3708 3709 break;
3709 3710 }
3710 3711 if (IBDM_IS_IOC_NUM_INVALID(attrmod, gid_info)) {
3711 3712 IBTF_DPRINTF_L2("ibdm", "\thandle_redirction:"
3712 3713 "IOC# Out of range %d", attrmod);
3713 3714 (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
3714 3715 mutex_exit(&gid_info->gl_mutex);
3715 3716 return (IBDM_FAILURE);
3716 3717 }
3717 3718 ioc = IBDM_GIDINFO2IOCINFO(gid_info, (attrmod -1));
3718 3719 cb_args = &ioc->ioc_dc_cb_args;
3719 3720 timeout_id = &ioc->ioc_dc_timeout_id;
3720 3721 break;
3721 3722
3722 3723 case IB_DM_ATTR_IOC_CTRL_PROFILE:
3723 3724 if (IBDM_IS_IOC_NUM_INVALID(attrmod, gid_info)) {
3724 3725 IBTF_DPRINTF_L2("ibdm", "\thandle_redirction:"
3725 3726 "IOC# Out of range %d", attrmod);
3726 3727 (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
3727 3728 mutex_exit(&gid_info->gl_mutex);
3728 3729 return (IBDM_FAILURE);
3729 3730 }
3730 3731 ioc = IBDM_GIDINFO2IOCINFO(gid_info, (attrmod -1));
3731 3732 cb_args = &ioc->ioc_cb_args;
3732 3733 timeout_id = &ioc->ioc_timeout_id;
3733 3734 break;
3734 3735
3735 3736 case IB_DM_ATTR_SERVICE_ENTRIES:
3736 3737 ioc_no = ((attrmod >> 16) & IBDM_16_BIT_MASK);
3737 3738 if (IBDM_IS_IOC_NUM_INVALID(ioc_no, gid_info)) {
3738 3739 IBTF_DPRINTF_L2("ibdm", "\thandle_redirction:"
3739 3740 "IOC# Out of range %d", ioc_no);
3740 3741 (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
3741 3742 mutex_exit(&gid_info->gl_mutex);
3742 3743 return (IBDM_FAILURE);
3743 3744 }
3744 3745 start = (attrmod & IBDM_8_BIT_MASK);
3745 3746 ioc = IBDM_GIDINFO2IOCINFO(gid_info, (ioc_no -1));
3746 3747 if (start > ioc->ioc_profile.ioc_service_entries) {
3747 3748 IBTF_DPRINTF_L2("ibdm", "\thandle_redirction:"
3748 3749 " SE index Out of range %d", start);
3749 3750 (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
3750 3751 mutex_exit(&gid_info->gl_mutex);
3751 3752 return (IBDM_FAILURE);
3752 3753 }
3753 3754 cb_args = &ioc->ioc_serv[start].se_cb_args;
3754 3755 timeout_id = &ioc->ioc_serv[start].se_timeout_id;
3755 3756 break;
3756 3757
3757 3758 default:
3758 3759 /* ERROR State */
3759 3760 IBTF_DPRINTF_L2("ibdm",
3760 3761 "\thandle_redirection: wrong attribute :-(");
3761 3762 (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
3762 3763 mutex_exit(&gid_info->gl_mutex);
3763 3764 return (IBDM_FAILURE);
3764 3765 }
3765 3766 break;
3766 3767 default:
3767 3768 /* ERROR State */
3768 3769 IBTF_DPRINTF_L2("ibdm",
3769 3770 "\thandle_redirection: Error state :-(");
3770 3771 (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
3771 3772 mutex_exit(&gid_info->gl_mutex);
3772 3773 return (IBDM_FAILURE);
3773 3774 }
3774 3775 if ((*timeout_id) != 0) {
3775 3776 mutex_exit(&gid_info->gl_mutex);
3776 3777 if (untimeout(*timeout_id) == -1) {
3777 3778 IBTF_DPRINTF_L2("ibdm", "\thandle_redirection: "
3778 3779 "untimeout failed %x", *timeout_id);
3779 3780 } else {
3780 3781 IBTF_DPRINTF_L5("ibdm",
3781 3782 "\thandle_redirection: timeout %x", *timeout_id);
3782 3783 }
3783 3784 mutex_enter(&gid_info->gl_mutex);
3784 3785 *timeout_id = 0;
3785 3786 }
3786 3787
3787 3788 data = msg->im_msgbufs_recv.im_bufs_cl_data;
3788 3789 cpi = (ib_mad_classportinfo_t *)data;
3789 3790
3790 3791 gid_info->gl_resp_timeout =
3791 3792 (b2h32(cpi->RespTimeValue) & 0x1F);
3792 3793
3793 3794 gid_info->gl_redirected = B_TRUE;
3794 3795 gid_info->gl_redirect_dlid = b2h16(cpi->RedirectLID);
3795 3796 gid_info->gl_redirect_QP = (b2h32(cpi->RedirectQP) & 0xffffff);
3796 3797 gid_info->gl_redirect_pkey = b2h16(cpi->RedirectP_Key);
3797 3798 gid_info->gl_redirect_qkey = b2h32(cpi->RedirectQ_Key);
3798 3799 gid_info->gl_redirectGID_hi = b2h64(cpi->RedirectGID_hi);
3799 3800 gid_info->gl_redirectGID_lo = b2h64(cpi->RedirectGID_lo);
3800 3801 gid_info->gl_redirectSL = cpi->RedirectSL;
3801 3802
3802 3803 if (gid_info->gl_redirect_dlid != 0) {
3803 3804 msg->im_local_addr.ia_remote_lid =
3804 3805 gid_info->gl_redirect_dlid;
3805 3806 }
3806 3807 ibdm_bump_transactionID(gid_info);
3807 3808 mutex_exit(&gid_info->gl_mutex);
3808 3809
3809 3810 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg, *hdr))
3810 3811 ibdm_alloc_send_buffers(msg);
3811 3812
3812 3813 hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
3813 3814 hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
3814 3815 hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
3815 3816 hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
3816 3817 hdr->R_Method = IB_DM_DEVMGT_METHOD_GET;
3817 3818 hdr->Status = 0;
3818 3819 hdr->TransactionID = h2b64(gid_info->gl_transactionID);
3819 3820 hdr->AttributeID =
3820 3821 msg->im_msgbufs_recv.im_bufs_mad_hdr->AttributeID;
3821 3822 hdr->AttributeModifier =
3822 3823 msg->im_msgbufs_recv.im_bufs_mad_hdr->AttributeModifier;
3823 3824 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg, *hdr))
3824 3825
3825 3826 msg->im_local_addr.ia_remote_qno = gid_info->gl_redirect_QP;
3826 3827 msg->im_local_addr.ia_p_key = gid_info->gl_redirect_pkey;
3827 3828 msg->im_local_addr.ia_q_key = gid_info->gl_redirect_qkey;
3828 3829 msg->im_local_addr.ia_service_level = gid_info->gl_redirectSL;
3829 3830
3830 3831 mutex_enter(&gid_info->gl_mutex);
3831 3832 *timeout_id = timeout(ibdm_pkt_timeout_hdlr,
3832 3833 cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
3833 3834 mutex_exit(&gid_info->gl_mutex);
3834 3835
3835 3836 IBTF_DPRINTF_L5("ibdm", "\thandle_redirect:"
3836 3837 "timeout %x", *timeout_id);
3837 3838
3838 3839 if (ibmf_msg_transport(gid_info->gl_ibmf_hdl, gid_info->gl_qp_hdl,
3839 3840 msg, NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
3840 3841 IBTF_DPRINTF_L4("ibdm", "\thandle_redirection:"
3841 3842 "message transport failed");
3842 3843 ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl, msg, cb_args);
3843 3844 }
3844 3845 (*flag) |= IBDM_IBMF_PKT_REUSED;
3845 3846 IBTF_DPRINTF_L4("ibdm", "\thandle_redirection: Exit");
3846 3847 return (IBDM_SUCCESS);
3847 3848 }
3848 3849
3849 3850
3850 3851 /*
3851 3852 * ibdm_pkt_timeout_hdlr
3852 3853 * This timeout handler is registed for every IBMF packet that is
3853 3854 * sent through the IBMF. It gets called when no response is received
3854 3855 * within the specified time for the packet. No retries for the failed
3855 3856 * commands currently. Drops the failed IBMF packet and update the
3856 3857 * pending list commands.
3857 3858 */
3858 3859 static void
3859 3860 ibdm_pkt_timeout_hdlr(void *arg)
3860 3861 {
3861 3862 ibdm_iou_info_t *iou;
3862 3863 ibdm_ioc_info_t *ioc;
3863 3864 ibdm_timeout_cb_args_t *cb_args = arg;
3864 3865 ibdm_dp_gidinfo_t *gid_info;
3865 3866 int srv_ent;
3866 3867 uint_t new_gl_state;
3867 3868
3868 3869 IBTF_DPRINTF_L2("ibdm", "\tpkt_timeout_hdlr: gid_info: %p "
3869 3870 "rtype 0x%x iocidx 0x%x srvidx %d", cb_args->cb_gid_info,
3870 3871 cb_args->cb_req_type, cb_args->cb_ioc_num,
3871 3872 cb_args->cb_srvents_start);
3872 3873
3873 3874 gid_info = cb_args->cb_gid_info;
3874 3875 mutex_enter(&gid_info->gl_mutex);
3875 3876
3876 3877 if ((gid_info->gl_state == IBDM_GID_PROBING_COMPLETE) ||
3877 3878 (cb_args->cb_req_type == 0)) {
3878 3879
3879 3880 IBTF_DPRINTF_L2("ibdm", "\tpkt_timeout_hdlr: req completed"
3880 3881 "rtype 0x%x iocidx 0x%x srvidx %d", cb_args->cb_req_type,
3881 3882 cb_args->cb_ioc_num, cb_args->cb_srvents_start);
3882 3883
3883 3884 if (gid_info->gl_timeout_id)
3884 3885 gid_info->gl_timeout_id = 0;
3885 3886 mutex_exit(&gid_info->gl_mutex);
3886 3887 return;
3887 3888 }
3888 3889 if (cb_args->cb_retry_count) {
3889 3890 cb_args->cb_retry_count--;
3890 3891 /*
3891 3892 * A new timeout_id is set inside ibdm_retry_command().
3892 3893 * When the function returns an error, the timeout_id
3893 3894 * is reset (to zero) in the switch statement below.
3894 3895 */
3895 3896 if (ibdm_retry_command(cb_args) == IBDM_SUCCESS) {
3896 3897 mutex_exit(&gid_info->gl_mutex);
3897 3898 return;
3898 3899 }
3899 3900 cb_args->cb_retry_count = 0;
3900 3901 }
3901 3902
3902 3903 IBTF_DPRINTF_L2("ibdm", "\tpkt_timeout_hdlr: command failed: gid %p"
3903 3904 " rtype 0x%x iocidx 0x%x srvidx %d", cb_args->cb_gid_info,
3904 3905 cb_args->cb_req_type, cb_args->cb_ioc_num,
3905 3906 cb_args->cb_srvents_start);
3906 3907
3907 3908 switch (cb_args->cb_req_type) {
3908 3909
3909 3910 case IBDM_REQ_TYPE_CLASSPORTINFO:
3910 3911 case IBDM_REQ_TYPE_IOUINFO:
3911 3912 new_gl_state = IBDM_GID_PROBING_FAILED;
3912 3913 if (gid_info->gl_timeout_id)
3913 3914 gid_info->gl_timeout_id = 0;
3914 3915 break;
3915 3916
3916 3917 case IBDM_REQ_TYPE_IOCINFO:
3917 3918 new_gl_state = IBDM_GID_PROBING_COMPLETE;
3918 3919 iou = gid_info->gl_iou;
3919 3920 ioc = &iou->iou_ioc_info[cb_args->cb_ioc_num];
3920 3921 ioc->ioc_state = IBDM_IOC_STATE_PROBE_FAILED;
3921 3922 if (ioc->ioc_timeout_id)
3922 3923 ioc->ioc_timeout_id = 0;
3923 3924 break;
3924 3925
3925 3926 case IBDM_REQ_TYPE_SRVENTS:
3926 3927 new_gl_state = IBDM_GID_PROBING_COMPLETE;
3927 3928 iou = gid_info->gl_iou;
3928 3929 ioc = &iou->iou_ioc_info[cb_args->cb_ioc_num];
3929 3930 ioc->ioc_state = IBDM_IOC_STATE_PROBE_FAILED;
3930 3931 srv_ent = cb_args->cb_srvents_start;
3931 3932 if (ioc->ioc_serv[srv_ent].se_timeout_id)
3932 3933 ioc->ioc_serv[srv_ent].se_timeout_id = 0;
3933 3934 break;
3934 3935
3935 3936 case IBDM_REQ_TYPE_IOU_DIAGCODE:
3936 3937 new_gl_state = IBDM_GID_PROBING_COMPLETE;
3937 3938 iou = gid_info->gl_iou;
3938 3939 iou->iou_dc_valid = B_FALSE;
3939 3940 if (gid_info->gl_timeout_id)
3940 3941 gid_info->gl_timeout_id = 0;
3941 3942 break;
3942 3943
3943 3944 case IBDM_REQ_TYPE_IOC_DIAGCODE:
3944 3945 new_gl_state = IBDM_GID_PROBING_COMPLETE;
3945 3946 iou = gid_info->gl_iou;
3946 3947 ioc = &iou->iou_ioc_info[cb_args->cb_ioc_num];
3947 3948 ioc->ioc_dc_valid = B_FALSE;
3948 3949 if (ioc->ioc_dc_timeout_id)
3949 3950 ioc->ioc_dc_timeout_id = 0;
3950 3951 break;
3951 3952
3952 3953 default: /* ERROR State */
3953 3954 new_gl_state = IBDM_GID_PROBING_FAILED;
3954 3955 if (gid_info->gl_timeout_id)
3955 3956 gid_info->gl_timeout_id = 0;
3956 3957 IBTF_DPRINTF_L2("ibdm",
3957 3958 "\tpkt_timeout_hdlr: wrong request type.");
3958 3959 break;
3959 3960 }
3960 3961
3961 3962 --gid_info->gl_pending_cmds; /* decrease the counter */
3962 3963
3963 3964 if (gid_info->gl_pending_cmds == 0) {
3964 3965 gid_info->gl_state = new_gl_state;
3965 3966 mutex_exit(&gid_info->gl_mutex);
3966 3967 /*
3967 3968 * Delete this gid_info if the gid probe fails.
3968 3969 */
3969 3970 if (new_gl_state == IBDM_GID_PROBING_FAILED) {
3970 3971 ibdm_delete_glhca_list(gid_info);
3971 3972 }
3972 3973 ibdm_notify_newgid_iocs(gid_info);
3973 3974 mutex_enter(&ibdm.ibdm_mutex);
3974 3975 if (--ibdm.ibdm_ngid_probes_in_progress == 0) {
3975 3976 IBTF_DPRINTF_L4("ibdm", "\tpkt_timeout_hdlr: Wakeup");
3976 3977 ibdm.ibdm_busy &= ~IBDM_PROBE_IN_PROGRESS;
3977 3978 cv_broadcast(&ibdm.ibdm_probe_cv);
3978 3979 }
3979 3980 mutex_exit(&ibdm.ibdm_mutex);
3980 3981 } else {
3981 3982 /*
3982 3983 * Reset gl_pending_cmd if the extra timeout happens since
3983 3984 * gl_pending_cmd becomes negative as a result.
3984 3985 */
3985 3986 if (gid_info->gl_pending_cmds < 0) {
3986 3987 gid_info->gl_pending_cmds = 0;
3987 3988 IBTF_DPRINTF_L2("ibdm",
3988 3989 "\tpkt_timeout_hdlr: extra timeout request."
3989 3990 " reset gl_pending_cmds");
3990 3991 }
3991 3992 mutex_exit(&gid_info->gl_mutex);
3992 3993 /*
3993 3994 * Delete this gid_info if the gid probe fails.
3994 3995 */
3995 3996 if (new_gl_state == IBDM_GID_PROBING_FAILED) {
3996 3997 ibdm_delete_glhca_list(gid_info);
3997 3998 }
3998 3999 }
3999 4000 }
4000 4001
4001 4002
4002 4003 /*
4003 4004 * ibdm_retry_command()
4004 4005 * Retries the failed command.
4005 4006 * Returns IBDM_FAILURE/IBDM_SUCCESS
4006 4007 */
4007 4008 static int
4008 4009 ibdm_retry_command(ibdm_timeout_cb_args_t *cb_args)
4009 4010 {
4010 4011 int ret;
4011 4012 ibmf_msg_t *msg;
4012 4013 ib_mad_hdr_t *hdr;
4013 4014 ibdm_dp_gidinfo_t *gid_info = cb_args->cb_gid_info;
4014 4015 timeout_id_t *timeout_id;
4015 4016 ibdm_ioc_info_t *ioc;
4016 4017 int ioc_no;
4017 4018 ASSERT(MUTEX_HELD(&gid_info->gl_mutex));
4018 4019
4019 4020 IBTF_DPRINTF_L2("ibdm", "\tretry_command: gid_info: %p "
4020 4021 "rtype 0x%x iocidx 0x%x srvidx %d", cb_args->cb_gid_info,
4021 4022 cb_args->cb_req_type, cb_args->cb_ioc_num,
4022 4023 cb_args->cb_srvents_start);
4023 4024
4024 4025 ret = ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_NOSLEEP, &msg);
4025 4026
4026 4027
4027 4028 /*
4028 4029 * Reset the gid if alloc_msg failed with BAD_HANDLE
4029 4030 * ibdm_reset_gidinfo reinits the gid_info
4030 4031 */
4031 4032 if (ret == IBMF_BAD_HANDLE) {
4032 4033 IBTF_DPRINTF_L3(ibdm_string, "\tretry_command: gid %p hdl bad",
4033 4034 gid_info);
4034 4035
4035 4036 mutex_exit(&gid_info->gl_mutex);
4036 4037 ibdm_reset_gidinfo(gid_info);
4037 4038 mutex_enter(&gid_info->gl_mutex);
4038 4039
4039 4040 /* Retry alloc */
4040 4041 ret = ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_NOSLEEP,
4041 4042 &msg);
4042 4043 }
4043 4044
4044 4045 if (ret != IBDM_SUCCESS) {
4045 4046 IBTF_DPRINTF_L2("ibdm", "\tretry_command: alloc failed: %p "
4046 4047 "rtype 0x%x iocidx 0x%x srvidx %d", cb_args->cb_gid_info,
4047 4048 cb_args->cb_req_type, cb_args->cb_ioc_num,
4048 4049 cb_args->cb_srvents_start);
4049 4050 return (IBDM_FAILURE);
4050 4051 }
4051 4052
4052 4053 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
4053 4054 ibdm_alloc_send_buffers(msg);
4054 4055 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
4055 4056
4056 4057 ibdm_bump_transactionID(gid_info);
4057 4058
4058 4059 msg->im_local_addr.ia_local_lid = gid_info->gl_slid;
4059 4060 msg->im_local_addr.ia_remote_lid = gid_info->gl_dlid;
4060 4061 if (gid_info->gl_redirected == B_TRUE) {
4061 4062 if (gid_info->gl_redirect_dlid != 0) {
4062 4063 msg->im_local_addr.ia_remote_lid =
4063 4064 gid_info->gl_redirect_dlid;
4064 4065 }
4065 4066 msg->im_local_addr.ia_remote_qno = gid_info->gl_redirect_QP;
4066 4067 msg->im_local_addr.ia_p_key = gid_info->gl_redirect_pkey;
4067 4068 msg->im_local_addr.ia_q_key = gid_info->gl_redirect_qkey;
4068 4069 msg->im_local_addr.ia_service_level = gid_info->gl_redirectSL;
4069 4070 } else {
4070 4071 msg->im_local_addr.ia_remote_qno = 1;
4071 4072 msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
4072 4073 msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
4073 4074 msg->im_local_addr.ia_service_level = gid_info->gl_SL;
4074 4075 }
4075 4076 hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
4076 4077 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*hdr))
4077 4078 hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
4078 4079 hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
4079 4080 hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
4080 4081 hdr->R_Method = IB_DM_DEVMGT_METHOD_GET;
4081 4082 hdr->Status = 0;
4082 4083 hdr->TransactionID = h2b64(gid_info->gl_transactionID);
4083 4084
4084 4085 switch (cb_args->cb_req_type) {
4085 4086 case IBDM_REQ_TYPE_CLASSPORTINFO:
4086 4087 hdr->AttributeID = h2b16(IB_DM_ATTR_CLASSPORTINFO);
4087 4088 hdr->AttributeModifier = 0;
4088 4089 timeout_id = &gid_info->gl_timeout_id;
4089 4090 break;
4090 4091 case IBDM_REQ_TYPE_IOUINFO:
4091 4092 hdr->AttributeID = h2b16(IB_DM_ATTR_IO_UNITINFO);
4092 4093 hdr->AttributeModifier = 0;
4093 4094 timeout_id = &gid_info->gl_timeout_id;
4094 4095 break;
4095 4096 case IBDM_REQ_TYPE_IOCINFO:
4096 4097 hdr->AttributeID = h2b16(IB_DM_ATTR_IOC_CTRL_PROFILE);
4097 4098 hdr->AttributeModifier = h2b32(cb_args->cb_ioc_num + 1);
4098 4099 ioc = IBDM_GIDINFO2IOCINFO(gid_info, cb_args->cb_ioc_num);
4099 4100 timeout_id = &ioc->ioc_timeout_id;
4100 4101 break;
4101 4102 case IBDM_REQ_TYPE_SRVENTS:
4102 4103 hdr->AttributeID = h2b16(IB_DM_ATTR_SERVICE_ENTRIES);
4103 4104 ibdm_fill_srv_attr_mod(hdr, cb_args);
4104 4105 ioc = IBDM_GIDINFO2IOCINFO(gid_info, cb_args->cb_ioc_num);
4105 4106 timeout_id =
4106 4107 &ioc->ioc_serv[cb_args->cb_srvents_start].se_timeout_id;
4107 4108 break;
4108 4109 case IBDM_REQ_TYPE_IOU_DIAGCODE:
4109 4110 hdr->AttributeID = h2b16(IB_DM_ATTR_DIAG_CODE);
4110 4111 hdr->AttributeModifier = 0;
4111 4112 timeout_id = &gid_info->gl_timeout_id;
4112 4113 break;
4113 4114 case IBDM_REQ_TYPE_IOC_DIAGCODE:
4114 4115 hdr->AttributeID = h2b16(IB_DM_ATTR_DIAG_CODE);
4115 4116 hdr->AttributeModifier = h2b32(cb_args->cb_ioc_num + 1);
4116 4117 ioc_no = cb_args->cb_ioc_num;
4117 4118 ioc = &gid_info->gl_iou->iou_ioc_info[ioc_no];
4118 4119 timeout_id = &ioc->ioc_dc_timeout_id;
4119 4120 break;
4120 4121 }
4121 4122 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*hdr))
4122 4123
4123 4124 *timeout_id = timeout(ibdm_pkt_timeout_hdlr,
4124 4125 cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
4125 4126
4126 4127 mutex_exit(&gid_info->gl_mutex);
4127 4128
4128 4129 IBTF_DPRINTF_L5("ibdm", "\tretry_command: %p,%x,%d,%d:"
4129 4130 "timeout %x", cb_args->cb_req_type, cb_args->cb_ioc_num,
4130 4131 cb_args->cb_srvents_start, *timeout_id);
4131 4132
4132 4133 if (ibmf_msg_transport(gid_info->gl_ibmf_hdl,
4133 4134 gid_info->gl_qp_hdl, msg, NULL, ibdm_ibmf_send_cb,
4134 4135 cb_args, 0) != IBMF_SUCCESS) {
4135 4136 IBTF_DPRINTF_L2("ibdm", "\tretry_command: send failed: %p "
4136 4137 "rtype 0x%x iocidx 0x%x srvidx %d", cb_args->cb_gid_info,
4137 4138 cb_args->cb_req_type, cb_args->cb_ioc_num,
4138 4139 cb_args->cb_srvents_start);
4139 4140 ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl, msg, cb_args);
4140 4141 }
4141 4142 mutex_enter(&gid_info->gl_mutex);
4142 4143 return (IBDM_SUCCESS);
4143 4144 }
4144 4145
4145 4146
4146 4147 /*
4147 4148 * ibdm_update_ioc_port_gidlist()
4148 4149 */
4149 4150 static void
4150 4151 ibdm_update_ioc_port_gidlist(ibdm_ioc_info_t *dest,
4151 4152 ibdm_dp_gidinfo_t *gid_info)
4152 4153 {
4153 4154 int ii, ngid_ents;
4154 4155 ibdm_gid_t *tmp;
4155 4156 ibdm_hca_list_t *gid_hca_head, *temp;
4156 4157 ibdm_hca_list_t *ioc_head = NULL;
4157 4158 ASSERT(MUTEX_HELD(&gid_info->gl_mutex));
4158 4159
4159 4160 IBTF_DPRINTF_L5("ibdm", "\tupdate_ioc_port_gidlist: Enter");
4160 4161
4161 4162 ngid_ents = gid_info->gl_ngids;
4162 4163 dest->ioc_nportgids = ngid_ents;
4163 4164 dest->ioc_gid_list = kmem_zalloc(sizeof (ibdm_gid_t) *
4164 4165 ngid_ents, KM_SLEEP);
4165 4166 tmp = gid_info->gl_gid;
4166 4167 for (ii = 0; (ii < ngid_ents) && (tmp); ii++) {
4167 4168 dest->ioc_gid_list[ii].gid_dgid_hi = tmp->gid_dgid_hi;
4168 4169 dest->ioc_gid_list[ii].gid_dgid_lo = tmp->gid_dgid_lo;
4169 4170 tmp = tmp->gid_next;
4170 4171 }
4171 4172
4172 4173 gid_hca_head = gid_info->gl_hca_list;
4173 4174 while (gid_hca_head) {
4174 4175 temp = ibdm_dup_hca_attr(gid_hca_head);
4175 4176 temp->hl_next = ioc_head;
4176 4177 ioc_head = temp;
4177 4178 gid_hca_head = gid_hca_head->hl_next;
4178 4179 }
4179 4180 dest->ioc_hca_list = ioc_head;
4180 4181 }
4181 4182
4182 4183
4183 4184 /*
4184 4185 * ibdm_alloc_send_buffers()
4185 4186 * Allocates memory for the IBMF send buffer to send and/or receive
4186 4187 * the Device Management MAD packet.
4187 4188 */
4188 4189 static void
4189 4190 ibdm_alloc_send_buffers(ibmf_msg_t *msgp)
4190 4191 {
4191 4192 msgp->im_msgbufs_send.im_bufs_mad_hdr =
4192 4193 kmem_zalloc(IBDM_MAD_SIZE, KM_SLEEP);
4193 4194
4194 4195 msgp->im_msgbufs_send.im_bufs_cl_hdr = (uchar_t *)
4195 4196 msgp->im_msgbufs_send.im_bufs_mad_hdr + sizeof (ib_mad_hdr_t);
4196 4197 msgp->im_msgbufs_send.im_bufs_cl_hdr_len = IBDM_DM_MAD_HDR_SZ;
4197 4198
4198 4199 msgp->im_msgbufs_send.im_bufs_cl_data =
4199 4200 ((char *)msgp->im_msgbufs_send.im_bufs_cl_hdr + IBDM_DM_MAD_HDR_SZ);
4200 4201 msgp->im_msgbufs_send.im_bufs_cl_data_len =
4201 4202 IBDM_MAD_SIZE - sizeof (ib_mad_hdr_t) - IBDM_DM_MAD_HDR_SZ;
4202 4203 }
4203 4204
4204 4205
4205 4206 /*
4206 4207 * ibdm_alloc_send_buffers()
4207 4208 * De-allocates memory for the IBMF send buffer
4208 4209 */
4209 4210 static void
4210 4211 ibdm_free_send_buffers(ibmf_msg_t *msgp)
4211 4212 {
4212 4213 if (msgp->im_msgbufs_send.im_bufs_mad_hdr != NULL)
4213 4214 kmem_free(msgp->im_msgbufs_send.im_bufs_mad_hdr, IBDM_MAD_SIZE);
4214 4215 }
4215 4216
4216 4217 /*
4217 4218 * ibdm_probe_ioc()
4218 4219 * 1. Gets the node records for the port GUID. This detects all the port
4219 4220 * to the IOU.
4220 4221 * 2. Selectively probes all the IOC, given it's node GUID
4221 4222 * 3. In case of reprobe, only the IOC to be reprobed is send the IOC
4222 4223 * Controller Profile asynchronously
4223 4224 */
4224 4225 /*ARGSUSED*/
4225 4226 static void
4226 4227 ibdm_probe_ioc(ib_guid_t nodeguid, ib_guid_t ioc_guid, int reprobe_flag)
4227 4228 {
4228 4229 int ii, nrecords;
4229 4230 size_t nr_len = 0, pi_len = 0;
4230 4231 ib_gid_t sgid, dgid;
4231 4232 ibdm_hca_list_t *hca_list = NULL;
4232 4233 sa_node_record_t *nr, *tmp;
4233 4234 ibdm_port_attr_t *port = NULL;
4234 4235 ibdm_dp_gidinfo_t *reprobe_gid, *new_gid, *node_gid;
4235 4236 ibdm_dp_gidinfo_t *temp_gidinfo;
4236 4237 ibdm_gid_t *temp_gid;
4237 4238 sa_portinfo_record_t *pi;
4238 4239
4239 4240 IBTF_DPRINTF_L4("ibdm", "\tprobe_ioc(%llx, %llx, %x): Begin",
4240 4241 nodeguid, ioc_guid, reprobe_flag);
4241 4242
4242 4243 /* Rescan the GID list for any removed GIDs for reprobe */
4243 4244 if (reprobe_flag)
4244 4245 ibdm_rescan_gidlist(&ioc_guid);
4245 4246
4246 4247 mutex_enter(&ibdm.ibdm_hl_mutex);
4247 4248 for (ibdm_get_next_port(&hca_list, &port, 1); port;
4248 4249 ibdm_get_next_port(&hca_list, &port, 1)) {
4249 4250 reprobe_gid = new_gid = node_gid = NULL;
4250 4251
4251 4252 nr = ibdm_get_node_records(port->pa_sa_hdl, &nr_len, nodeguid);
4252 4253 if (nr == NULL) {
4253 4254 IBTF_DPRINTF_L4("ibdm", "\tprobe_ioc: no records");
4254 4255 continue;
4255 4256 }
4256 4257 nrecords = (nr_len / sizeof (sa_node_record_t));
4257 4258 for (tmp = nr, ii = 0; (ii < nrecords); ii++, tmp++) {
4258 4259 if ((pi = ibdm_get_portinfo(
4259 4260 port->pa_sa_hdl, &pi_len, tmp->LID)) == NULL) {
4260 4261 IBTF_DPRINTF_L4("ibdm",
4261 4262 "\tibdm_get_portinfo: no portinfo recs");
4262 4263 continue;
4263 4264 }
4264 4265
4265 4266 /*
4266 4267 * If Device Management is not supported on
4267 4268 * this port, skip the rest.
4268 4269 */
4269 4270 if (!(pi->PortInfo.CapabilityMask &
4270 4271 SM_CAP_MASK_IS_DM_SUPPD)) {
4271 4272 kmem_free(pi, pi_len);
4272 4273 continue;
4273 4274 }
4274 4275
4275 4276 /*
4276 4277 * For reprobes: Check if GID, already in
4277 4278 * the list. If so, set the state to SKIPPED
4278 4279 */
4279 4280 if (((temp_gidinfo = ibdm_find_gid(nodeguid,
4280 4281 tmp->NodeInfo.PortGUID)) != NULL) &&
4281 4282 temp_gidinfo->gl_state ==
4282 4283 IBDM_GID_PROBING_COMPLETE) {
4283 4284 ASSERT(reprobe_gid == NULL);
4284 4285 ibdm_addto_glhcalist(temp_gidinfo,
4285 4286 hca_list);
4286 4287 reprobe_gid = temp_gidinfo;
4287 4288 kmem_free(pi, pi_len);
4288 4289 continue;
4289 4290 } else if (temp_gidinfo != NULL) {
4290 4291 kmem_free(pi, pi_len);
4291 4292 ibdm_addto_glhcalist(temp_gidinfo,
4292 4293 hca_list);
4293 4294 continue;
4294 4295 }
4295 4296
4296 4297 IBTF_DPRINTF_L4("ibdm", "\tprobe_ioc : "
4297 4298 "create_gid : prefix %llx, guid %llx\n",
4298 4299 pi->PortInfo.GidPrefix,
4299 4300 tmp->NodeInfo.PortGUID);
4300 4301
4301 4302 sgid.gid_prefix = port->pa_sn_prefix;
4302 4303 sgid.gid_guid = port->pa_port_guid;
4303 4304 dgid.gid_prefix = pi->PortInfo.GidPrefix;
4304 4305 dgid.gid_guid = tmp->NodeInfo.PortGUID;
4305 4306 new_gid = ibdm_create_gid_info(port, sgid,
4306 4307 dgid);
4307 4308 if (new_gid == NULL) {
4308 4309 IBTF_DPRINTF_L2("ibdm", "\tprobe_ioc: "
4309 4310 "create_gid_info failed\n");
4310 4311 kmem_free(pi, pi_len);
4311 4312 continue;
4312 4313 }
4313 4314 if (node_gid == NULL) {
4314 4315 node_gid = new_gid;
4315 4316 ibdm_add_to_gl_gid(node_gid, node_gid);
4316 4317 } else {
4317 4318 IBTF_DPRINTF_L4("ibdm",
4318 4319 "\tprobe_ioc: new gid");
4319 4320 temp_gid = kmem_zalloc(
4320 4321 sizeof (ibdm_gid_t), KM_SLEEP);
4321 4322 temp_gid->gid_dgid_hi =
4322 4323 new_gid->gl_dgid_hi;
4323 4324 temp_gid->gid_dgid_lo =
4324 4325 new_gid->gl_dgid_lo;
4325 4326 temp_gid->gid_next = node_gid->gl_gid;
4326 4327 node_gid->gl_gid = temp_gid;
4327 4328 node_gid->gl_ngids++;
4328 4329 }
4329 4330 new_gid->gl_is_dm_capable = B_TRUE;
4330 4331 new_gid->gl_nodeguid = nodeguid;
4331 4332 new_gid->gl_portguid = dgid.gid_guid;
4332 4333 ibdm_addto_glhcalist(new_gid, hca_list);
4333 4334
4334 4335 /*
4335 4336 * Set the state to skipped as all these
4336 4337 * gids point to the same node.
4337 4338 * We (re)probe only one GID below and reset
4338 4339 * state appropriately
4339 4340 */
4340 4341 new_gid->gl_state = IBDM_GID_PROBING_SKIPPED;
4341 4342 new_gid->gl_devid = (*tmp).NodeInfo.DeviceID;
4342 4343 kmem_free(pi, pi_len);
4343 4344 }
4344 4345 kmem_free(nr, nr_len);
4345 4346
4346 4347 IBTF_DPRINTF_L4("ibdm", "\tprobe_ioc : reprobe_flag %d "
4347 4348 "reprobe_gid %p new_gid %p node_gid %p",
4348 4349 reprobe_flag, reprobe_gid, new_gid, node_gid);
4349 4350
4350 4351 if (reprobe_flag != 0 && reprobe_gid != NULL) {
4351 4352 int niocs, jj;
4352 4353 ibdm_ioc_info_t *tmp_ioc;
4353 4354 int ioc_matched = 0;
4354 4355
4355 4356 mutex_exit(&ibdm.ibdm_hl_mutex);
4356 4357 mutex_enter(&reprobe_gid->gl_mutex);
4357 4358 reprobe_gid->gl_state = IBDM_GET_IOC_DETAILS;
4358 4359 niocs =
4359 4360 reprobe_gid->gl_iou->iou_info.iou_num_ctrl_slots;
4360 4361 reprobe_gid->gl_pending_cmds++;
4361 4362 mutex_exit(&reprobe_gid->gl_mutex);
4362 4363
4363 4364 for (jj = 0; jj < niocs; jj++) {
4364 4365 tmp_ioc =
4365 4366 IBDM_GIDINFO2IOCINFO(reprobe_gid, jj);
4366 4367 if (tmp_ioc->ioc_profile.ioc_guid != ioc_guid)
4367 4368 continue;
4368 4369
4369 4370 ioc_matched = 1;
4370 4371
4371 4372 /*
4372 4373 * Explicitly set gl_reprobe_flag to 0 so that
4373 4374 * IBnex is not notified on completion
4374 4375 */
4375 4376 mutex_enter(&reprobe_gid->gl_mutex);
4376 4377 reprobe_gid->gl_reprobe_flag = 0;
4377 4378 mutex_exit(&reprobe_gid->gl_mutex);
4378 4379
4379 4380 mutex_enter(&ibdm.ibdm_mutex);
4380 4381 ibdm.ibdm_ngid_probes_in_progress++;
4381 4382 mutex_exit(&ibdm.ibdm_mutex);
4382 4383 if (ibdm_send_ioc_profile(reprobe_gid, jj) !=
4383 4384 IBDM_SUCCESS) {
4384 4385 IBTF_DPRINTF_L4("ibdm",
4385 4386 "\tprobe_ioc: "
4386 4387 "send_ioc_profile failed "
4387 4388 "for ioc %d", jj);
4388 4389 ibdm_gid_decr_pending(reprobe_gid);
4389 4390 break;
4390 4391 }
4391 4392 mutex_enter(&ibdm.ibdm_mutex);
4392 4393 ibdm_wait_probe_completion();
4393 4394 mutex_exit(&ibdm.ibdm_mutex);
4394 4395 break;
4395 4396 }
4396 4397 if (ioc_matched == 0)
4397 4398 ibdm_gid_decr_pending(reprobe_gid);
4398 4399 else {
4399 4400 mutex_enter(&ibdm.ibdm_hl_mutex);
4400 4401 break;
4401 4402 }
4402 4403 } else if (new_gid != NULL) {
4403 4404 mutex_exit(&ibdm.ibdm_hl_mutex);
4404 4405 node_gid = node_gid ? node_gid : new_gid;
4405 4406
4406 4407 /*
4407 4408 * New or reinserted GID : Enable notification
4408 4409 * to IBnex
4409 4410 */
4410 4411 mutex_enter(&node_gid->gl_mutex);
4411 4412 node_gid->gl_reprobe_flag = 1;
4412 4413 mutex_exit(&node_gid->gl_mutex);
4413 4414
4414 4415 ibdm_probe_gid(node_gid);
4415 4416
4416 4417 mutex_enter(&ibdm.ibdm_hl_mutex);
4417 4418 }
4418 4419 }
4419 4420 mutex_exit(&ibdm.ibdm_hl_mutex);
4420 4421 IBTF_DPRINTF_L4("ibdm", "\tprobe_ioc : End\n");
4421 4422 }
4422 4423
4423 4424
4424 4425 /*
4425 4426 * ibdm_probe_gid()
4426 4427 * Selectively probes the GID
4427 4428 */
4428 4429 static void
4429 4430 ibdm_probe_gid(ibdm_dp_gidinfo_t *gid_info)
4430 4431 {
4431 4432 IBTF_DPRINTF_L4("ibdm", "\tprobe_gid:");
4432 4433
4433 4434 /*
4434 4435 * A Cisco FC GW needs the special handling to get IOUnitInfo.
4435 4436 */
4436 4437 mutex_enter(&gid_info->gl_mutex);
4437 4438 if (ibdm_is_cisco_switch(gid_info)) {
4438 4439 gid_info->gl_pending_cmds++;
4439 4440 gid_info->gl_state = IBDM_SET_CLASSPORTINFO;
4440 4441 mutex_exit(&gid_info->gl_mutex);
4441 4442
4442 4443 if (ibdm_set_classportinfo(gid_info) != IBDM_SUCCESS) {
4443 4444
4444 4445 mutex_enter(&gid_info->gl_mutex);
4445 4446 gid_info->gl_state = IBDM_GID_PROBING_FAILED;
4446 4447 --gid_info->gl_pending_cmds;
4447 4448 mutex_exit(&gid_info->gl_mutex);
4448 4449
4449 4450 /* free the hca_list on this gid_info */
4450 4451 ibdm_delete_glhca_list(gid_info);
4451 4452 gid_info = gid_info->gl_next;
4452 4453 return;
4453 4454 }
4454 4455
4455 4456 mutex_enter(&gid_info->gl_mutex);
4456 4457 ibdm_wait_cisco_probe_completion(gid_info);
4457 4458
4458 4459 IBTF_DPRINTF_L4("ibdm",
4459 4460 "\tprobe_gid: CISCO Wakeup signal received");
4460 4461 }
4461 4462
4462 4463 /* move on to the 'GET_CLASSPORTINFO' stage */
4463 4464 gid_info->gl_pending_cmds++;
4464 4465 gid_info->gl_state = IBDM_GET_CLASSPORTINFO;
4465 4466 mutex_exit(&gid_info->gl_mutex);
4466 4467
4467 4468 if (ibdm_send_classportinfo(gid_info) != IBDM_SUCCESS) {
4468 4469
4469 4470 mutex_enter(&gid_info->gl_mutex);
4470 4471 gid_info->gl_state = IBDM_GID_PROBING_FAILED;
4471 4472 --gid_info->gl_pending_cmds;
4472 4473 mutex_exit(&gid_info->gl_mutex);
4473 4474
4474 4475 /* free the hca_list on this gid_info */
4475 4476 ibdm_delete_glhca_list(gid_info);
4476 4477 gid_info = gid_info->gl_next;
4477 4478 return;
4478 4479 }
4479 4480
4480 4481 mutex_enter(&ibdm.ibdm_mutex);
4481 4482 ibdm.ibdm_ngid_probes_in_progress++;
4482 4483 gid_info = gid_info->gl_next;
4483 4484 ibdm_wait_probe_completion();
4484 4485 mutex_exit(&ibdm.ibdm_mutex);
4485 4486
4486 4487 IBTF_DPRINTF_L4("ibdm", "\tprobe_gid: Wakeup signal received");
4487 4488 }
4488 4489
4489 4490
4490 4491 /*
4491 4492 * ibdm_create_gid_info()
4492 4493 * Allocates a gid_info structure and initializes
4493 4494 * Returns pointer to the structure on success
4494 4495 * and NULL on failure
4495 4496 */
4496 4497 static ibdm_dp_gidinfo_t *
4497 4498 ibdm_create_gid_info(ibdm_port_attr_t *port, ib_gid_t sgid, ib_gid_t dgid)
4498 4499 {
4499 4500 uint8_t ii, npaths;
4500 4501 sa_path_record_t *path;
4501 4502 size_t len;
4502 4503 ibdm_pkey_tbl_t *pkey_tbl;
4503 4504 ibdm_dp_gidinfo_t *gid_info = NULL;
4504 4505 int ret;
4505 4506
4506 4507 IBTF_DPRINTF_L4("ibdm", "\tcreate_gid_info: Begin");
4507 4508 npaths = 1;
4508 4509
4509 4510 /* query for reversible paths */
4510 4511 if (port->pa_sa_hdl)
4511 4512 ret = ibmf_saa_gid_to_pathrecords(port->pa_sa_hdl,
4512 4513 sgid, dgid, IBMF_SAA_PKEY_WC, 0, B_TRUE, &npaths, 0,
4513 4514 &len, &path);
4514 4515 else
4515 4516 return (NULL);
4516 4517
4517 4518 if (ret == IBMF_SUCCESS && path) {
4518 4519 ibdm_dump_path_info(path);
4519 4520
4520 4521 gid_info = kmem_zalloc(
4521 4522 sizeof (ibdm_dp_gidinfo_t), KM_SLEEP);
4522 4523 mutex_init(&gid_info->gl_mutex, NULL, MUTEX_DEFAULT, NULL);
4523 4524 cv_init(&gid_info->gl_probe_cv, NULL, CV_DRIVER, NULL);
4524 4525 gid_info->gl_dgid_hi = path->DGID.gid_prefix;
4525 4526 gid_info->gl_dgid_lo = path->DGID.gid_guid;
4526 4527 gid_info->gl_sgid_hi = path->SGID.gid_prefix;
4527 4528 gid_info->gl_sgid_lo = path->SGID.gid_guid;
4528 4529 gid_info->gl_p_key = path->P_Key;
4529 4530 gid_info->gl_sa_hdl = port->pa_sa_hdl;
4530 4531 gid_info->gl_ibmf_hdl = port->pa_ibmf_hdl;
4531 4532 gid_info->gl_slid = path->SLID;
4532 4533 gid_info->gl_dlid = path->DLID;
4533 4534 gid_info->gl_transactionID = (++ibdm.ibdm_transactionID)
4534 4535 << IBDM_GID_TRANSACTIONID_SHIFT;
4535 4536 gid_info->gl_min_transactionID = gid_info->gl_transactionID;
4536 4537 gid_info->gl_max_transactionID = (ibdm.ibdm_transactionID +1)
4537 4538 << IBDM_GID_TRANSACTIONID_SHIFT;
4538 4539 gid_info->gl_SL = path->SL;
4539 4540
4540 4541 gid_info->gl_qp_hdl = IBMF_QP_HANDLE_DEFAULT;
4541 4542 for (ii = 0; ii < port->pa_npkeys; ii++) {
4542 4543 if (port->pa_pkey_tbl == NULL)
4543 4544 break;
4544 4545
4545 4546 pkey_tbl = &port->pa_pkey_tbl[ii];
4546 4547 if ((gid_info->gl_p_key == pkey_tbl->pt_pkey) &&
4547 4548 (pkey_tbl->pt_qp_hdl != NULL)) {
4548 4549 gid_info->gl_qp_hdl = pkey_tbl->pt_qp_hdl;
4549 4550 break;
4550 4551 }
4551 4552 }
4552 4553 kmem_free(path, len);
4553 4554
4554 4555 /*
4555 4556 * QP handle for GID not initialized. No matching Pkey
4556 4557 * was found!! ibdm should *not* hit this case. Flag an
4557 4558 * error and drop the GID if ibdm does encounter this.
4558 4559 */
4559 4560 if (gid_info->gl_qp_hdl == NULL) {
4560 4561 IBTF_DPRINTF_L2(ibdm_string,
4561 4562 "\tcreate_gid_info: No matching Pkey");
4562 4563 ibdm_delete_gidinfo(gid_info);
4563 4564 return (NULL);
4564 4565 }
4565 4566
4566 4567 ibdm.ibdm_ngids++;
4567 4568 if (ibdm.ibdm_dp_gidlist_head == NULL) {
4568 4569 ibdm.ibdm_dp_gidlist_head = gid_info;
4569 4570 ibdm.ibdm_dp_gidlist_tail = gid_info;
4570 4571 } else {
4571 4572 ibdm.ibdm_dp_gidlist_tail->gl_next = gid_info;
4572 4573 gid_info->gl_prev = ibdm.ibdm_dp_gidlist_tail;
4573 4574 ibdm.ibdm_dp_gidlist_tail = gid_info;
4574 4575 }
4575 4576 }
4576 4577
4577 4578 return (gid_info);
4578 4579 }
4579 4580
4580 4581
4581 4582 /*
4582 4583 * ibdm_get_node_records
4583 4584 * Sends a SA query to get the NODE record
4584 4585 * Returns pointer to the sa_node_record_t on success
4585 4586 * and NULL on failure
4586 4587 */
4587 4588 static sa_node_record_t *
4588 4589 ibdm_get_node_records(ibmf_saa_handle_t sa_hdl, size_t *length, ib_guid_t guid)
4589 4590 {
4590 4591 sa_node_record_t req, *resp = NULL;
4591 4592 ibmf_saa_access_args_t args;
4592 4593 int ret;
4593 4594
4594 4595 IBTF_DPRINTF_L4("ibdm", "\tget_node_records: Begin");
4595 4596
4596 4597 bzero(&req, sizeof (sa_node_record_t));
4597 4598 req.NodeInfo.NodeGUID = guid;
4598 4599
4599 4600 args.sq_attr_id = SA_NODERECORD_ATTRID;
4600 4601 args.sq_access_type = IBMF_SAA_RETRIEVE;
4601 4602 args.sq_component_mask = SA_NODEINFO_COMPMASK_NODEGUID;
4602 4603 args.sq_template = &req;
4603 4604 args.sq_callback = NULL;
4604 4605 args.sq_callback_arg = NULL;
4605 4606
4606 4607 ret = ibmf_sa_access(sa_hdl, &args, 0, length, (void **) &resp);
4607 4608 if (ret != IBMF_SUCCESS) {
4608 4609 IBTF_DPRINTF_L2("ibdm", "\tget_node_records:"
4609 4610 " SA Retrieve Failed: %d", ret);
4610 4611 return (NULL);
4611 4612 }
4612 4613 if ((resp == NULL) || (*length == 0)) {
4613 4614 IBTF_DPRINTF_L2("ibdm", "\tget_node_records: No records");
4614 4615 return (NULL);
4615 4616 }
4616 4617
4617 4618 IBTF_DPRINTF_L4("ibdm", "\tget_node_records: NodeGuid %llx "
4618 4619 "PortGUID %llx", resp->NodeInfo.NodeGUID, resp->NodeInfo.PortGUID);
4619 4620
4620 4621 return (resp);
4621 4622 }
4622 4623
4623 4624
4624 4625 /*
4625 4626 * ibdm_get_portinfo()
4626 4627 * Sends a SA query to get the PortInfo record
4627 4628 * Returns pointer to the sa_portinfo_record_t on success
4628 4629 * and NULL on failure
4629 4630 */
4630 4631 static sa_portinfo_record_t *
4631 4632 ibdm_get_portinfo(ibmf_saa_handle_t sa_hdl, size_t *length, ib_lid_t lid)
4632 4633 {
4633 4634 sa_portinfo_record_t req, *resp = NULL;
4634 4635 ibmf_saa_access_args_t args;
4635 4636 int ret;
4636 4637
4637 4638 IBTF_DPRINTF_L4("ibdm", "\tget_portinfo: Begin");
4638 4639
4639 4640 bzero(&req, sizeof (sa_portinfo_record_t));
4640 4641 req.EndportLID = lid;
4641 4642
4642 4643 args.sq_attr_id = SA_PORTINFORECORD_ATTRID;
4643 4644 args.sq_access_type = IBMF_SAA_RETRIEVE;
4644 4645 args.sq_component_mask = SA_PORTINFO_COMPMASK_PORTLID;
4645 4646 args.sq_template = &req;
4646 4647 args.sq_callback = NULL;
4647 4648 args.sq_callback_arg = NULL;
4648 4649
4649 4650 ret = ibmf_sa_access(sa_hdl, &args, 0, length, (void **) &resp);
4650 4651 if (ret != IBMF_SUCCESS) {
4651 4652 IBTF_DPRINTF_L2("ibdm", "\tget_portinfo:"
4652 4653 " SA Retrieve Failed: 0x%X", ret);
4653 4654 return (NULL);
4654 4655 }
4655 4656 if ((*length == 0) || (resp == NULL))
4656 4657 return (NULL);
4657 4658
4658 4659 IBTF_DPRINTF_L4("ibdm", "\tget_portinfo: GidPrefix %llx Cap 0x%x",
4659 4660 resp->PortInfo.GidPrefix, resp->PortInfo.CapabilityMask);
4660 4661 return (resp);
4661 4662 }
4662 4663
4663 4664
4664 4665 /*
4665 4666 * ibdm_ibnex_register_callback
4666 4667 * IB nexus callback routine for HCA attach and detach notification
4667 4668 */
4668 4669 void
4669 4670 ibdm_ibnex_register_callback(ibdm_callback_t ibnex_dm_callback)
4670 4671 {
4671 4672 IBTF_DPRINTF_L4("ibdm", "\tibnex_register_callbacks");
4672 4673 mutex_enter(&ibdm.ibdm_ibnex_mutex);
4673 4674 ibdm.ibdm_ibnex_callback = ibnex_dm_callback;
4674 4675 mutex_exit(&ibdm.ibdm_ibnex_mutex);
4675 4676 }
4676 4677
4677 4678
4678 4679 /*
4679 4680 * ibdm_ibnex_unregister_callbacks
4680 4681 */
4681 4682 void
4682 4683 ibdm_ibnex_unregister_callback()
4683 4684 {
↓ open down ↓ |
3699 lines elided |
↑ open up ↑ |
4684 4685 IBTF_DPRINTF_L4("ibdm", "\tibnex_unregister_callbacks");
4685 4686 mutex_enter(&ibdm.ibdm_ibnex_mutex);
4686 4687 ibdm.ibdm_ibnex_callback = NULL;
4687 4688 mutex_exit(&ibdm.ibdm_ibnex_mutex);
4688 4689 }
4689 4690
4690 4691 /*
4691 4692 * ibdm_get_waittime()
4692 4693 * Calculates the wait time based on the last HCA attach time
4693 4694 */
4694 -static time_t
4695 -ibdm_get_waittime(ib_guid_t hca_guid, int dft_wait)
4695 +static clock_t
4696 +ibdm_get_waittime(ib_guid_t hca_guid, time_t dft_wait_sec)
4696 4697 {
4697 - int ii;
4698 - time_t temp, wait_time = 0;
4698 + const hrtime_t dft_wait = dft_wait_sec * NANOSEC;
4699 + hrtime_t temp, wait_time = 0;
4700 + clock_t usecs;
4701 + int i;
4699 4702 ibdm_hca_list_t *hca;
4700 4703
4701 4704 IBTF_DPRINTF_L4("ibdm", "\tget_waittime hcaguid:%llx"
4702 4705 "\tport settling time %d", hca_guid, dft_wait);
4703 4706
4704 4707 ASSERT(mutex_owned(&ibdm.ibdm_hl_mutex));
4705 4708
4706 4709 hca = ibdm.ibdm_hca_list_head;
4707 4710
4708 - if (hca_guid) {
4709 - for (ii = 0; ii < ibdm.ibdm_hca_count; ii++) {
4710 - if ((hca_guid == hca->hl_hca_guid) &&
4711 - (hca->hl_nports != hca->hl_nports_active)) {
4712 - wait_time =
4713 - ddi_get_time() - hca->hl_attach_time;
4714 - wait_time = ((wait_time >= dft_wait) ?
4715 - 0 : (dft_wait - wait_time));
4716 - break;
4717 - }
4718 - hca = hca->hl_next;
4711 + for (i = 0; i < ibdm.ibdm_hca_count; i++, hca = hca->hl_next) {
4712 + if (hca->hl_nports == hca->hl_nports_active)
4713 + continue;
4714 +
4715 + if (hca_guid && (hca_guid != hca->hl_hca_guid))
4716 + continue;
4717 +
4718 + temp = gethrtime() - hca->hl_attach_time;
4719 + temp = MAX(0, (dft_wait - temp));
4720 +
4721 + if (hca_guid) {
4722 + wait_time = temp;
4723 + break;
4719 4724 }
4720 - IBTF_DPRINTF_L2("ibdm", "\tget_waittime: wait_time = %ld secs",
4721 - (long)wait_time);
4722 - return (wait_time);
4725 +
4726 + wait_time = MAX(temp, wait_time);
4723 4727 }
4724 4728
4725 - for (ii = 0; ii < ibdm.ibdm_hca_count; ii++) {
4726 - if (hca->hl_nports != hca->hl_nports_active) {
4727 - temp = ddi_get_time() - hca->hl_attach_time;
4728 - temp = ((temp >= dft_wait) ? 0 : (dft_wait - temp));
4729 - wait_time = (temp > wait_time) ? temp : wait_time;
4730 - }
4731 - hca = hca->hl_next;
4732 - }
4733 - IBTF_DPRINTF_L2("ibdm", "\tget_waittime: wait_time = %ld secs",
4734 - (long)wait_time);
4735 - return (wait_time);
4729 + /* convert to microseconds */
4730 + usecs = MIN(wait_time, dft_wait) / (NANOSEC / MICROSEC);
4731 +
4732 + IBTF_DPRINTF_L2("ibdm", "\tget_waittime: wait_time = %ld usecs",
4733 + (long) usecs);
4734 +
4735 + return (drv_usectohz(usecs));
4736 4736 }
4737 4737
4738 4738 void
4739 -ibdm_ibnex_port_settle_wait(ib_guid_t hca_guid, int dft_wait)
4739 +ibdm_ibnex_port_settle_wait(ib_guid_t hca_guid, time_t dft_wait)
4740 4740 {
4741 - time_t wait_time;
4742 - clock_t delta;
4741 + clock_t wait_time;
4743 4742
4744 4743 mutex_enter(&ibdm.ibdm_hl_mutex);
4745 4744
4746 - while ((wait_time = ibdm_get_waittime(hca_guid, dft_wait)) > 0) {
4747 - if (wait_time > dft_wait) {
4748 - IBTF_DPRINTF_L1("ibdm",
4749 - "\tibnex_port_settle_wait: wait_time = %ld secs; "
4750 - "Resetting to %d secs",
4751 - (long)wait_time, dft_wait);
4752 - wait_time = dft_wait;
4753 - }
4754 - delta = drv_usectohz(wait_time * 1000000);
4745 + while ((wait_time = ibdm_get_waittime(hca_guid, dft_wait)) > 0)
4755 4746 (void) cv_reltimedwait(&ibdm.ibdm_port_settle_cv,
4756 - &ibdm.ibdm_hl_mutex, delta, TR_CLOCK_TICK);
4757 - }
4747 + &ibdm.ibdm_hl_mutex, wait_time, TR_CLOCK_TICK);
4758 4748
4759 4749 mutex_exit(&ibdm.ibdm_hl_mutex);
4760 4750 }
4761 4751
4762 4752
4763 4753 /*
4764 4754 * ibdm_ibnex_probe_hcaport
4765 4755 * Probes the presence of HCA port (with HCA dip and port number)
4766 4756 * Returns port attributes structure on SUCCESS
4767 4757 */
4768 4758 ibdm_port_attr_t *
4769 4759 ibdm_ibnex_probe_hcaport(ib_guid_t hca_guid, uint8_t port_num)
4770 4760 {
4771 4761 int ii, jj;
4772 4762 ibdm_hca_list_t *hca_list;
4773 4763 ibdm_port_attr_t *port_attr;
4774 4764
4775 4765 IBTF_DPRINTF_L4("ibdm", "\tibnex_probe_hcaport:");
4776 4766
4777 4767 mutex_enter(&ibdm.ibdm_hl_mutex);
4778 4768 hca_list = ibdm.ibdm_hca_list_head;
4779 4769 for (ii = 0; ii < ibdm.ibdm_hca_count; ii++) {
4780 4770 if (hca_list->hl_hca_guid == hca_guid) {
4781 4771 for (jj = 0; jj < hca_list->hl_nports; jj++) {
4782 4772 if (hca_list->hl_port_attr[jj].pa_port_num ==
4783 4773 port_num) {
4784 4774 break;
4785 4775 }
4786 4776 }
4787 4777 if (jj != hca_list->hl_nports)
4788 4778 break;
4789 4779 }
4790 4780 hca_list = hca_list->hl_next;
4791 4781 }
4792 4782 if (ii == ibdm.ibdm_hca_count) {
4793 4783 IBTF_DPRINTF_L2("ibdm", "\tibnex_probe_hcaport: not found");
4794 4784 mutex_exit(&ibdm.ibdm_hl_mutex);
4795 4785 return (NULL);
4796 4786 }
4797 4787 port_attr = (ibdm_port_attr_t *)kmem_zalloc(
4798 4788 sizeof (ibdm_port_attr_t), KM_SLEEP);
4799 4789 bcopy((char *)&hca_list->hl_port_attr[jj],
4800 4790 port_attr, sizeof (ibdm_port_attr_t));
4801 4791 ibdm_update_port_attr(port_attr);
4802 4792
4803 4793 mutex_exit(&ibdm.ibdm_hl_mutex);
4804 4794 return (port_attr);
4805 4795 }
4806 4796
4807 4797
4808 4798 /*
4809 4799 * ibdm_ibnex_get_port_attrs
4810 4800 * Scan all HCAs for a matching port_guid.
4811 4801 * Returns "port attributes" structure on success.
4812 4802 */
4813 4803 ibdm_port_attr_t *
4814 4804 ibdm_ibnex_get_port_attrs(ib_guid_t port_guid)
4815 4805 {
4816 4806 int ii, jj;
4817 4807 ibdm_hca_list_t *hca_list;
4818 4808 ibdm_port_attr_t *port_attr;
4819 4809
4820 4810 IBTF_DPRINTF_L4("ibdm", "\tibnex_get_port_attrs:");
4821 4811
4822 4812 mutex_enter(&ibdm.ibdm_hl_mutex);
4823 4813 hca_list = ibdm.ibdm_hca_list_head;
4824 4814
4825 4815 for (ii = 0; ii < ibdm.ibdm_hca_count; ii++) {
4826 4816 for (jj = 0; jj < hca_list->hl_nports; jj++) {
4827 4817 if (hca_list->hl_port_attr[jj].pa_port_guid ==
4828 4818 port_guid) {
4829 4819 break;
4830 4820 }
4831 4821 }
4832 4822 if (jj != hca_list->hl_nports)
4833 4823 break;
4834 4824 hca_list = hca_list->hl_next;
4835 4825 }
4836 4826
4837 4827 if (ii == ibdm.ibdm_hca_count) {
4838 4828 IBTF_DPRINTF_L2("ibdm", "\tibnex_get_port_attrs: not found");
4839 4829 mutex_exit(&ibdm.ibdm_hl_mutex);
4840 4830 return (NULL);
4841 4831 }
4842 4832
4843 4833 port_attr = (ibdm_port_attr_t *)kmem_alloc(sizeof (ibdm_port_attr_t),
4844 4834 KM_SLEEP);
4845 4835 bcopy((char *)&hca_list->hl_port_attr[jj], port_attr,
4846 4836 sizeof (ibdm_port_attr_t));
4847 4837 ibdm_update_port_attr(port_attr);
4848 4838
4849 4839 mutex_exit(&ibdm.ibdm_hl_mutex);
4850 4840 return (port_attr);
4851 4841 }
4852 4842
4853 4843
4854 4844 /*
4855 4845 * ibdm_ibnex_free_port_attr()
4856 4846 */
4857 4847 void
4858 4848 ibdm_ibnex_free_port_attr(ibdm_port_attr_t *port_attr)
4859 4849 {
4860 4850 IBTF_DPRINTF_L4("ibdm", "\tibnex_free_port_attr:");
4861 4851 if (port_attr) {
4862 4852 if (port_attr->pa_pkey_tbl != NULL) {
4863 4853 kmem_free(port_attr->pa_pkey_tbl,
4864 4854 (port_attr->pa_npkeys * sizeof (ibdm_pkey_tbl_t)));
4865 4855 }
4866 4856 kmem_free(port_attr, sizeof (ibdm_port_attr_t));
4867 4857 }
4868 4858 }
4869 4859
4870 4860
4871 4861 /*
4872 4862 * ibdm_ibnex_get_hca_list()
4873 4863 * Returns portinfo for all the port for all the HCA's
4874 4864 */
4875 4865 void
4876 4866 ibdm_ibnex_get_hca_list(ibdm_hca_list_t **hca, int *count)
4877 4867 {
4878 4868 ibdm_hca_list_t *head = NULL, *temp, *temp1;
4879 4869 int ii;
4880 4870
4881 4871 IBTF_DPRINTF_L4("ibdm", "\tibnex_get_hca_list:");
4882 4872
4883 4873 mutex_enter(&ibdm.ibdm_hl_mutex);
4884 4874 temp = ibdm.ibdm_hca_list_head;
4885 4875 for (ii = 0; ii < ibdm.ibdm_hca_count; ii++) {
4886 4876 temp1 = ibdm_dup_hca_attr(temp);
4887 4877 temp1->hl_next = head;
4888 4878 head = temp1;
4889 4879 temp = temp->hl_next;
4890 4880 }
4891 4881 *count = ibdm.ibdm_hca_count;
4892 4882 *hca = head;
4893 4883 mutex_exit(&ibdm.ibdm_hl_mutex);
4894 4884 }
4895 4885
4896 4886
4897 4887 /*
4898 4888 * ibdm_ibnex_get_hca_info_by_guid()
4899 4889 */
4900 4890 ibdm_hca_list_t *
4901 4891 ibdm_ibnex_get_hca_info_by_guid(ib_guid_t hca_guid)
4902 4892 {
4903 4893 ibdm_hca_list_t *head = NULL, *hca = NULL;
4904 4894
4905 4895 IBTF_DPRINTF_L4("ibdm", "\tibnex_get_hca_info_by_dip");
4906 4896
4907 4897 mutex_enter(&ibdm.ibdm_hl_mutex);
4908 4898 head = ibdm.ibdm_hca_list_head;
4909 4899 while (head) {
4910 4900 if (head->hl_hca_guid == hca_guid) {
4911 4901 hca = ibdm_dup_hca_attr(head);
4912 4902 hca->hl_next = NULL;
4913 4903 break;
4914 4904 }
4915 4905 head = head->hl_next;
4916 4906 }
4917 4907 mutex_exit(&ibdm.ibdm_hl_mutex);
4918 4908 IBTF_DPRINTF_L4("ibdm", "\tibnex_get_hca_info_by_dip %p", hca);
4919 4909 return (hca);
4920 4910 }
4921 4911
4922 4912
4923 4913 /*
4924 4914 * ibdm_dup_hca_attr()
4925 4915 * Allocate a new HCA attribute strucuture and initialize
4926 4916 * hca attribute structure with the incoming HCA attributes
4927 4917 * returned the allocated hca attributes.
4928 4918 */
4929 4919 static ibdm_hca_list_t *
4930 4920 ibdm_dup_hca_attr(ibdm_hca_list_t *in_hca)
4931 4921 {
4932 4922 int len;
4933 4923 ibdm_hca_list_t *out_hca;
4934 4924
4935 4925 len = sizeof (ibdm_hca_list_t) +
4936 4926 (in_hca->hl_nports * sizeof (ibdm_port_attr_t));
4937 4927 IBTF_DPRINTF_L4("ibdm", "\tdup_hca_attr len %d", len);
4938 4928 out_hca = (ibdm_hca_list_t *)kmem_alloc(len, KM_SLEEP);
4939 4929 bcopy((char *)in_hca,
4940 4930 (char *)out_hca, sizeof (ibdm_hca_list_t));
4941 4931 if (in_hca->hl_nports) {
4942 4932 out_hca->hl_port_attr = (ibdm_port_attr_t *)
4943 4933 ((char *)out_hca + sizeof (ibdm_hca_list_t));
4944 4934 bcopy((char *)in_hca->hl_port_attr,
4945 4935 (char *)out_hca->hl_port_attr,
4946 4936 (in_hca->hl_nports * sizeof (ibdm_port_attr_t)));
4947 4937 for (len = 0; len < out_hca->hl_nports; len++)
4948 4938 ibdm_update_port_attr(&out_hca->hl_port_attr[len]);
4949 4939 }
4950 4940 return (out_hca);
4951 4941 }
4952 4942
4953 4943
4954 4944 /*
4955 4945 * ibdm_ibnex_free_hca_list()
4956 4946 * Free one/more HCA lists
4957 4947 */
4958 4948 void
4959 4949 ibdm_ibnex_free_hca_list(ibdm_hca_list_t *hca_list)
4960 4950 {
4961 4951 int ii;
4962 4952 size_t len;
4963 4953 ibdm_hca_list_t *temp;
4964 4954 ibdm_port_attr_t *port;
4965 4955
4966 4956 IBTF_DPRINTF_L4("ibdm", "\tibnex_free_hca_list:");
4967 4957 ASSERT(hca_list);
4968 4958 while (hca_list) {
4969 4959 temp = hca_list;
4970 4960 hca_list = hca_list->hl_next;
4971 4961 for (ii = 0; ii < temp->hl_nports; ii++) {
4972 4962 port = &temp->hl_port_attr[ii];
4973 4963 len = (port->pa_npkeys * sizeof (ibdm_pkey_tbl_t));
4974 4964 if (len != 0)
4975 4965 kmem_free(port->pa_pkey_tbl, len);
4976 4966 }
4977 4967 len = sizeof (ibdm_hca_list_t) + (temp->hl_nports *
4978 4968 sizeof (ibdm_port_attr_t));
4979 4969 kmem_free(temp, len);
4980 4970 }
4981 4971 }
4982 4972
4983 4973
4984 4974 /*
4985 4975 * ibdm_ibnex_probe_iocguid()
4986 4976 * Probes the IOC on the fabric and returns the IOC information
4987 4977 * if present. Otherwise, NULL is returned
4988 4978 */
4989 4979 /* ARGSUSED */
4990 4980 ibdm_ioc_info_t *
4991 4981 ibdm_ibnex_probe_ioc(ib_guid_t iou, ib_guid_t ioc_guid, int reprobe_flag)
4992 4982 {
4993 4983 int k;
4994 4984 ibdm_ioc_info_t *ioc_info;
4995 4985 ibdm_dp_gidinfo_t *gid_info; /* used as index and arg */
4996 4986 timeout_id_t *timeout_id;
4997 4987
4998 4988 IBTF_DPRINTF_L4("ibdm", "\tibnex_probe_ioc: (%llX, %llX, %d) Begin",
4999 4989 iou, ioc_guid, reprobe_flag);
5000 4990
5001 4991 if (ibdm_enumerate_iocs == 0)
5002 4992 return (NULL);
5003 4993
5004 4994 /* Check whether we know this already */
5005 4995 ioc_info = ibdm_get_ioc_info_with_gid(ioc_guid, &gid_info);
5006 4996 if (ioc_info == NULL) {
5007 4997 mutex_enter(&ibdm.ibdm_mutex);
5008 4998 while (ibdm.ibdm_busy & IBDM_BUSY)
5009 4999 cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
5010 5000 ibdm.ibdm_busy |= IBDM_BUSY;
5011 5001 mutex_exit(&ibdm.ibdm_mutex);
5012 5002 ibdm_probe_ioc(iou, ioc_guid, 0);
5013 5003 mutex_enter(&ibdm.ibdm_mutex);
5014 5004 ibdm.ibdm_busy &= ~IBDM_BUSY;
5015 5005 cv_broadcast(&ibdm.ibdm_busy_cv);
5016 5006 mutex_exit(&ibdm.ibdm_mutex);
5017 5007 ioc_info = ibdm_get_ioc_info_with_gid(ioc_guid, &gid_info);
5018 5008 } else if (reprobe_flag) { /* Handle Reprobe for the IOC */
5019 5009 ASSERT(gid_info != NULL);
5020 5010 /* Free the ioc_list before reprobe; and cancel any timers */
5021 5011 mutex_enter(&ibdm.ibdm_mutex);
5022 5012 mutex_enter(&gid_info->gl_mutex);
5023 5013 if (ioc_info->ioc_timeout_id) {
5024 5014 timeout_id = ioc_info->ioc_timeout_id;
5025 5015 ioc_info->ioc_timeout_id = 0;
5026 5016 mutex_exit(&gid_info->gl_mutex);
5027 5017 IBTF_DPRINTF_L5("ibdm", "\tprobe_ioc: "
5028 5018 "ioc_timeout_id = 0x%x", timeout_id);
5029 5019 if (untimeout(timeout_id) == -1) {
5030 5020 IBTF_DPRINTF_L2("ibdm", "\tprobe_ioc: "
5031 5021 "untimeout ioc_timeout_id failed");
5032 5022 }
5033 5023 mutex_enter(&gid_info->gl_mutex);
5034 5024 }
5035 5025 if (ioc_info->ioc_dc_timeout_id) {
5036 5026 timeout_id = ioc_info->ioc_dc_timeout_id;
5037 5027 ioc_info->ioc_dc_timeout_id = 0;
5038 5028 mutex_exit(&gid_info->gl_mutex);
5039 5029 IBTF_DPRINTF_L5("ibdm", "\tprobe_ioc: "
5040 5030 "ioc_dc_timeout_id = 0x%x", timeout_id);
5041 5031 if (untimeout(timeout_id) == -1) {
5042 5032 IBTF_DPRINTF_L2("ibdm", "\tprobe_ioc: "
5043 5033 "untimeout ioc_dc_timeout_id failed");
5044 5034 }
5045 5035 mutex_enter(&gid_info->gl_mutex);
5046 5036 }
5047 5037 for (k = 0; k < ioc_info->ioc_profile.ioc_service_entries; k++)
5048 5038 if (ioc_info->ioc_serv[k].se_timeout_id) {
5049 5039 timeout_id = ioc_info->ioc_serv[k].
5050 5040 se_timeout_id;
5051 5041 ioc_info->ioc_serv[k].se_timeout_id = 0;
5052 5042 mutex_exit(&gid_info->gl_mutex);
5053 5043 IBTF_DPRINTF_L5("ibdm", "\tprobe_ioc: "
5054 5044 "ioc_info->ioc_serv[k].se_timeout_id = %x",
5055 5045 k, timeout_id);
5056 5046 if (untimeout(timeout_id) == -1) {
5057 5047 IBTF_DPRINTF_L2("ibdm", "\tprobe_ioc: "
5058 5048 "untimeout se_timeout_id %d "
5059 5049 "failed", k);
5060 5050 }
5061 5051 mutex_enter(&gid_info->gl_mutex);
5062 5052 }
5063 5053 mutex_exit(&gid_info->gl_mutex);
5064 5054 mutex_exit(&ibdm.ibdm_mutex);
5065 5055 ibdm_ibnex_free_ioc_list(ioc_info);
5066 5056
5067 5057 mutex_enter(&ibdm.ibdm_mutex);
5068 5058 while (ibdm.ibdm_busy & IBDM_BUSY)
5069 5059 cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
5070 5060 ibdm.ibdm_busy |= IBDM_BUSY;
5071 5061 mutex_exit(&ibdm.ibdm_mutex);
5072 5062
5073 5063 ibdm_probe_ioc(iou, ioc_guid, 1);
5074 5064
5075 5065 /*
5076 5066 * Skip if gl_reprobe_flag is set, this will be
5077 5067 * a re-inserted / new GID, for which notifications
5078 5068 * have already been send.
5079 5069 */
5080 5070 for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info;
5081 5071 gid_info = gid_info->gl_next) {
5082 5072 uint8_t ii, niocs;
5083 5073 ibdm_ioc_info_t *ioc;
5084 5074
5085 5075 if (gid_info->gl_iou == NULL)
5086 5076 continue;
5087 5077
5088 5078 if (gid_info->gl_reprobe_flag) {
5089 5079 gid_info->gl_reprobe_flag = 0;
5090 5080 continue;
5091 5081 }
5092 5082
5093 5083 niocs = gid_info->gl_iou->iou_info.iou_num_ctrl_slots;
5094 5084 for (ii = 0; ii < niocs; ii++) {
5095 5085 ioc = IBDM_GIDINFO2IOCINFO(gid_info, ii);
5096 5086 if (ioc->ioc_profile.ioc_guid == ioc_guid) {
5097 5087 mutex_enter(&ibdm.ibdm_mutex);
5098 5088 ibdm_reprobe_update_port_srv(ioc,
5099 5089 gid_info);
5100 5090 mutex_exit(&ibdm.ibdm_mutex);
5101 5091 }
5102 5092 }
5103 5093 }
5104 5094 mutex_enter(&ibdm.ibdm_mutex);
5105 5095 ibdm.ibdm_busy &= ~IBDM_BUSY;
5106 5096 cv_broadcast(&ibdm.ibdm_busy_cv);
5107 5097 mutex_exit(&ibdm.ibdm_mutex);
5108 5098
5109 5099 ioc_info = ibdm_get_ioc_info_with_gid(ioc_guid, &gid_info);
5110 5100 }
5111 5101 return (ioc_info);
5112 5102 }
5113 5103
5114 5104
5115 5105 /*
5116 5106 * ibdm_get_ioc_info_with_gid()
5117 5107 * Returns pointer to ibdm_ioc_info_t if it finds
5118 5108 * matching record for the ioc_guid. Otherwise NULL is returned.
5119 5109 * The pointer to gid_info is set to the second argument in case that
5120 5110 * the non-NULL value returns (and the second argument is not NULL).
5121 5111 *
5122 5112 * Note. use the same strings as "ibnex_get_ioc_info" in
5123 5113 * IBTF_DPRINTF() to keep compatibility.
5124 5114 */
5125 5115 static ibdm_ioc_info_t *
5126 5116 ibdm_get_ioc_info_with_gid(ib_guid_t ioc_guid,
5127 5117 ibdm_dp_gidinfo_t **gid_info)
5128 5118 {
5129 5119 int ii;
5130 5120 ibdm_ioc_info_t *ioc = NULL, *tmp = NULL;
5131 5121 ibdm_dp_gidinfo_t *gid_list;
5132 5122 ib_dm_io_unitinfo_t *iou;
5133 5123
5134 5124 IBTF_DPRINTF_L4("ibdm", "\tibnex_get_ioc_info: GUID %llx", ioc_guid);
5135 5125
5136 5126 mutex_enter(&ibdm.ibdm_mutex);
5137 5127 while (ibdm.ibdm_busy & IBDM_BUSY)
5138 5128 cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
5139 5129 ibdm.ibdm_busy |= IBDM_BUSY;
5140 5130
5141 5131 if (gid_info)
5142 5132 *gid_info = NULL; /* clear the value of gid_info */
5143 5133
5144 5134 gid_list = ibdm.ibdm_dp_gidlist_head;
5145 5135 while (gid_list) {
5146 5136 mutex_enter(&gid_list->gl_mutex);
5147 5137 if (gid_list->gl_state != IBDM_GID_PROBING_COMPLETE) {
5148 5138 mutex_exit(&gid_list->gl_mutex);
5149 5139 gid_list = gid_list->gl_next;
5150 5140 continue;
5151 5141 }
5152 5142 if (gid_list->gl_iou == NULL) {
5153 5143 IBTF_DPRINTF_L2("ibdm",
5154 5144 "\tget_ioc_info: No IOU info");
5155 5145 mutex_exit(&gid_list->gl_mutex);
5156 5146 gid_list = gid_list->gl_next;
5157 5147 continue;
5158 5148 }
5159 5149 iou = &gid_list->gl_iou->iou_info;
5160 5150 for (ii = 0; ii < iou->iou_num_ctrl_slots; ii++) {
5161 5151 tmp = IBDM_GIDINFO2IOCINFO(gid_list, ii);
5162 5152 if ((tmp->ioc_profile.ioc_guid == ioc_guid) &&
5163 5153 (tmp->ioc_state == IBDM_IOC_STATE_PROBE_SUCCESS)) {
5164 5154 ioc = ibdm_dup_ioc_info(tmp, gid_list);
5165 5155 if (gid_info)
5166 5156 *gid_info = gid_list; /* set this ptr */
5167 5157 mutex_exit(&gid_list->gl_mutex);
5168 5158 ibdm.ibdm_busy &= ~IBDM_BUSY;
5169 5159 cv_broadcast(&ibdm.ibdm_busy_cv);
5170 5160 mutex_exit(&ibdm.ibdm_mutex);
5171 5161 IBTF_DPRINTF_L4("ibdm", "\tget_ioc_info: End");
5172 5162 return (ioc);
5173 5163 }
5174 5164 }
5175 5165 if (ii == iou->iou_num_ctrl_slots)
5176 5166 ioc = NULL;
5177 5167
5178 5168 mutex_exit(&gid_list->gl_mutex);
5179 5169 gid_list = gid_list->gl_next;
5180 5170 }
5181 5171
5182 5172 ibdm.ibdm_busy &= ~IBDM_BUSY;
5183 5173 cv_broadcast(&ibdm.ibdm_busy_cv);
5184 5174 mutex_exit(&ibdm.ibdm_mutex);
5185 5175 IBTF_DPRINTF_L4("ibdm", "\tget_ioc_info: failure End");
5186 5176 return (ioc);
5187 5177 }
5188 5178
5189 5179 /*
5190 5180 * ibdm_ibnex_get_ioc_info()
5191 5181 * Returns pointer to ibdm_ioc_info_t if it finds
5192 5182 * matching record for the ioc_guid, otherwise NULL
5193 5183 * is returned
5194 5184 *
5195 5185 * Note. this is a wrapper function to ibdm_get_ioc_info_with_gid() now.
5196 5186 */
5197 5187 ibdm_ioc_info_t *
5198 5188 ibdm_ibnex_get_ioc_info(ib_guid_t ioc_guid)
5199 5189 {
5200 5190 if (ibdm_enumerate_iocs == 0)
5201 5191 return (NULL);
5202 5192
5203 5193 /* will not use the gid_info pointer, so the second arg is NULL */
5204 5194 return (ibdm_get_ioc_info_with_gid(ioc_guid, NULL));
5205 5195 }
5206 5196
5207 5197 /*
5208 5198 * ibdm_ibnex_get_ioc_count()
5209 5199 * Returns number of ibdm_ioc_info_t it finds
5210 5200 */
5211 5201 int
5212 5202 ibdm_ibnex_get_ioc_count(void)
5213 5203 {
5214 5204 int count = 0, k;
5215 5205 ibdm_ioc_info_t *ioc;
5216 5206 ibdm_dp_gidinfo_t *gid_list;
5217 5207
5218 5208 if (ibdm_enumerate_iocs == 0)
5219 5209 return (0);
5220 5210
5221 5211 mutex_enter(&ibdm.ibdm_mutex);
5222 5212 ibdm_sweep_fabric(0);
5223 5213
5224 5214 while (ibdm.ibdm_busy & IBDM_BUSY)
5225 5215 cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
5226 5216 ibdm.ibdm_busy |= IBDM_BUSY;
5227 5217
5228 5218 for (gid_list = ibdm.ibdm_dp_gidlist_head; gid_list;
5229 5219 gid_list = gid_list->gl_next) {
5230 5220 mutex_enter(&gid_list->gl_mutex);
5231 5221 if ((gid_list->gl_state != IBDM_GID_PROBING_COMPLETE) ||
5232 5222 (gid_list->gl_iou == NULL)) {
5233 5223 mutex_exit(&gid_list->gl_mutex);
5234 5224 continue;
5235 5225 }
5236 5226 for (k = 0; k < gid_list->gl_iou->iou_info.iou_num_ctrl_slots;
5237 5227 k++) {
5238 5228 ioc = IBDM_GIDINFO2IOCINFO(gid_list, k);
5239 5229 if (ioc->ioc_state == IBDM_IOC_STATE_PROBE_SUCCESS)
5240 5230 ++count;
5241 5231 }
5242 5232 mutex_exit(&gid_list->gl_mutex);
5243 5233 }
5244 5234 ibdm.ibdm_busy &= ~IBDM_BUSY;
5245 5235 cv_broadcast(&ibdm.ibdm_busy_cv);
5246 5236 mutex_exit(&ibdm.ibdm_mutex);
5247 5237
5248 5238 IBTF_DPRINTF_L4("ibdm", "\tget_ioc_count: count = %d", count);
5249 5239 return (count);
5250 5240 }
5251 5241
5252 5242
5253 5243 /*
5254 5244 * ibdm_ibnex_get_ioc_list()
5255 5245 * Returns information about all the IOCs present on the fabric.
5256 5246 * Reprobes the IOCs and the GID list if list_flag is set to REPROBE_ALL.
5257 5247 * Does not sweep fabric if DONOT_PROBE is set
5258 5248 */
5259 5249 ibdm_ioc_info_t *
5260 5250 ibdm_ibnex_get_ioc_list(ibdm_ibnex_get_ioclist_mtd_t list_flag)
5261 5251 {
5262 5252 int ii;
5263 5253 ibdm_ioc_info_t *ioc_list = NULL, *tmp, *ioc;
5264 5254 ibdm_dp_gidinfo_t *gid_list;
5265 5255 ib_dm_io_unitinfo_t *iou;
5266 5256
5267 5257 IBTF_DPRINTF_L4("ibdm", "\tget_ioc_list: Enter");
5268 5258
5269 5259 if (ibdm_enumerate_iocs == 0)
5270 5260 return (NULL);
5271 5261
5272 5262 mutex_enter(&ibdm.ibdm_mutex);
5273 5263 if (list_flag != IBDM_IBNEX_DONOT_PROBE)
5274 5264 ibdm_sweep_fabric(list_flag == IBDM_IBNEX_REPROBE_ALL);
5275 5265
5276 5266 while (ibdm.ibdm_busy & IBDM_BUSY)
5277 5267 cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
5278 5268 ibdm.ibdm_busy |= IBDM_BUSY;
5279 5269
5280 5270 gid_list = ibdm.ibdm_dp_gidlist_head;
5281 5271 while (gid_list) {
5282 5272 mutex_enter(&gid_list->gl_mutex);
5283 5273 if (gid_list->gl_state != IBDM_GID_PROBING_COMPLETE) {
5284 5274 mutex_exit(&gid_list->gl_mutex);
5285 5275 gid_list = gid_list->gl_next;
5286 5276 continue;
5287 5277 }
5288 5278 if (gid_list->gl_iou == NULL) {
5289 5279 IBTF_DPRINTF_L2("ibdm",
5290 5280 "\tget_ioc_list: No IOU info");
5291 5281 mutex_exit(&gid_list->gl_mutex);
5292 5282 gid_list = gid_list->gl_next;
5293 5283 continue;
5294 5284 }
5295 5285 iou = &gid_list->gl_iou->iou_info;
5296 5286 for (ii = 0; ii < iou->iou_num_ctrl_slots; ii++) {
5297 5287 ioc = IBDM_GIDINFO2IOCINFO(gid_list, ii);
5298 5288 if (ioc->ioc_state == IBDM_IOC_STATE_PROBE_SUCCESS) {
5299 5289 tmp = ibdm_dup_ioc_info(ioc, gid_list);
5300 5290 tmp->ioc_next = ioc_list;
5301 5291 ioc_list = tmp;
5302 5292 }
5303 5293 }
5304 5294 mutex_exit(&gid_list->gl_mutex);
5305 5295 gid_list = gid_list->gl_next;
5306 5296 }
5307 5297 ibdm.ibdm_busy &= ~IBDM_BUSY;
5308 5298 cv_broadcast(&ibdm.ibdm_busy_cv);
5309 5299 mutex_exit(&ibdm.ibdm_mutex);
5310 5300
5311 5301 IBTF_DPRINTF_L4("ibdm", "\tget_ioc_list: End");
5312 5302 return (ioc_list);
5313 5303 }
5314 5304
5315 5305 /*
5316 5306 * ibdm_dup_ioc_info()
5317 5307 * Duplicate the IOC information and return the IOC
5318 5308 * information.
5319 5309 */
5320 5310 static ibdm_ioc_info_t *
5321 5311 ibdm_dup_ioc_info(ibdm_ioc_info_t *in_ioc, ibdm_dp_gidinfo_t *gid_list)
5322 5312 {
5323 5313 ibdm_ioc_info_t *out_ioc;
5324 5314 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*out_ioc));
5325 5315 ASSERT(MUTEX_HELD(&gid_list->gl_mutex));
5326 5316
5327 5317 out_ioc = kmem_alloc(sizeof (ibdm_ioc_info_t), KM_SLEEP);
5328 5318 bcopy(in_ioc, out_ioc, sizeof (ibdm_ioc_info_t));
5329 5319 ibdm_update_ioc_port_gidlist(out_ioc, gid_list);
5330 5320 out_ioc->ioc_iou_dc_valid = gid_list->gl_iou->iou_dc_valid;
5331 5321 out_ioc->ioc_iou_diagcode = gid_list->gl_iou->iou_diagcode;
5332 5322
5333 5323 return (out_ioc);
5334 5324 }
5335 5325
5336 5326
5337 5327 /*
5338 5328 * ibdm_free_ioc_list()
5339 5329 * Deallocate memory for IOC list structure
5340 5330 */
5341 5331 void
5342 5332 ibdm_ibnex_free_ioc_list(ibdm_ioc_info_t *ioc)
5343 5333 {
5344 5334 ibdm_ioc_info_t *temp;
5345 5335
5346 5336 IBTF_DPRINTF_L4("ibdm", "\tibnex_free_ioc_list:");
5347 5337 while (ioc) {
5348 5338 temp = ioc;
5349 5339 ioc = ioc->ioc_next;
5350 5340 kmem_free(temp->ioc_gid_list,
5351 5341 (sizeof (ibdm_gid_t) * temp->ioc_nportgids));
5352 5342 if (temp->ioc_hca_list)
5353 5343 ibdm_ibnex_free_hca_list(temp->ioc_hca_list);
5354 5344 kmem_free(temp, sizeof (ibdm_ioc_info_t));
5355 5345 }
5356 5346 }
5357 5347
5358 5348
5359 5349 /*
5360 5350 * ibdm_ibnex_update_pkey_tbls
5361 5351 * Updates the DM P_Key database.
5362 5352 * NOTE: Two cases are handled here: P_Key being added or removed.
5363 5353 *
5364 5354 * Arguments : NONE
5365 5355 * Return Values : NONE
5366 5356 */
5367 5357 void
5368 5358 ibdm_ibnex_update_pkey_tbls(void)
5369 5359 {
5370 5360 int h, pp, pidx;
5371 5361 uint_t nports;
5372 5362 uint_t size;
5373 5363 ib_pkey_t new_pkey;
5374 5364 ib_pkey_t *orig_pkey;
5375 5365 ibdm_hca_list_t *hca_list;
5376 5366 ibdm_port_attr_t *port;
5377 5367 ibt_hca_portinfo_t *pinfop;
5378 5368
5379 5369 IBTF_DPRINTF_L4("ibdm", "\tibnex_update_pkey_tbls:");
5380 5370
5381 5371 mutex_enter(&ibdm.ibdm_hl_mutex);
5382 5372 hca_list = ibdm.ibdm_hca_list_head;
5383 5373
5384 5374 for (h = 0; h < ibdm.ibdm_hca_count; h++) {
5385 5375
5386 5376 /* This updates P_Key Tables for all ports of this HCA */
5387 5377 (void) ibt_query_hca_ports(hca_list->hl_hca_hdl, 0, &pinfop,
5388 5378 &nports, &size);
5389 5379
5390 5380 /* number of ports shouldn't have changed */
5391 5381 ASSERT(nports == hca_list->hl_nports);
5392 5382
5393 5383 for (pp = 0; pp < hca_list->hl_nports; pp++) {
5394 5384 port = &hca_list->hl_port_attr[pp];
5395 5385
5396 5386 /*
5397 5387 * First figure out the P_Keys from IBTL.
5398 5388 * Three things could have happened:
5399 5389 * New P_Keys added
5400 5390 * Existing P_Keys removed
5401 5391 * Both of the above two
5402 5392 *
5403 5393 * Loop through the P_Key Indices and check if a
5404 5394 * give P_Key_Ix matches that of the one seen by
5405 5395 * IBDM. If they match no action is needed.
5406 5396 *
5407 5397 * If they don't match:
5408 5398 * 1. if orig_pkey is invalid and new_pkey is valid
5409 5399 * ---> add new_pkey to DM database
5410 5400 * 2. if orig_pkey is valid and new_pkey is invalid
5411 5401 * ---> remove orig_pkey from DM database
5412 5402 * 3. if orig_pkey and new_pkey are both valid:
5413 5403 * ---> remov orig_pkey from DM database
5414 5404 * ---> add new_pkey to DM database
5415 5405 * 4. if orig_pkey and new_pkey are both invalid:
5416 5406 * ---> do nothing. Updated DM database.
5417 5407 */
5418 5408
5419 5409 for (pidx = 0; pidx < port->pa_npkeys; pidx++) {
5420 5410 new_pkey = pinfop[pp].p_pkey_tbl[pidx];
5421 5411 orig_pkey = &port->pa_pkey_tbl[pidx].pt_pkey;
5422 5412
5423 5413 /* keys match - do nothing */
5424 5414 if (*orig_pkey == new_pkey)
5425 5415 continue;
5426 5416
5427 5417 if (IBDM_INVALID_PKEY(*orig_pkey) &&
5428 5418 !IBDM_INVALID_PKEY(new_pkey)) {
5429 5419 /* P_Key was added */
5430 5420 IBTF_DPRINTF_L5("ibdm",
5431 5421 "\tibnex_update_pkey_tbls: new "
5432 5422 "P_Key added = 0x%x", new_pkey);
5433 5423 *orig_pkey = new_pkey;
5434 5424 ibdm_port_attr_ibmf_init(port,
5435 5425 new_pkey, pp);
5436 5426 } else if (!IBDM_INVALID_PKEY(*orig_pkey) &&
5437 5427 IBDM_INVALID_PKEY(new_pkey)) {
5438 5428 /* P_Key was removed */
5439 5429 IBTF_DPRINTF_L5("ibdm",
5440 5430 "\tibnex_update_pkey_tbls: P_Key "
5441 5431 "removed = 0x%x", *orig_pkey);
5442 5432 *orig_pkey = new_pkey;
5443 5433 (void) ibdm_port_attr_ibmf_fini(port,
5444 5434 pidx);
5445 5435 } else if (!IBDM_INVALID_PKEY(*orig_pkey) &&
5446 5436 !IBDM_INVALID_PKEY(new_pkey)) {
5447 5437 /* P_Key were replaced */
5448 5438 IBTF_DPRINTF_L5("ibdm",
5449 5439 "\tibnex_update_pkey_tbls: P_Key "
5450 5440 "replaced 0x%x with 0x%x",
5451 5441 *orig_pkey, new_pkey);
5452 5442 (void) ibdm_port_attr_ibmf_fini(port,
5453 5443 pidx);
5454 5444 *orig_pkey = new_pkey;
5455 5445 ibdm_port_attr_ibmf_init(port,
5456 5446 new_pkey, pp);
5457 5447 } else {
5458 5448 /*
5459 5449 * P_Keys are invalid
5460 5450 * set anyway to reflect if
5461 5451 * INVALID_FULL was changed to
5462 5452 * INVALID_LIMITED or vice-versa.
5463 5453 */
5464 5454 *orig_pkey = new_pkey;
5465 5455 } /* end of else */
5466 5456
5467 5457 } /* loop of p_key index */
5468 5458
5469 5459 } /* loop of #ports of HCA */
5470 5460
5471 5461 ibt_free_portinfo(pinfop, size);
5472 5462 hca_list = hca_list->hl_next;
5473 5463
5474 5464 } /* loop for all HCAs in the system */
5475 5465
5476 5466 mutex_exit(&ibdm.ibdm_hl_mutex);
5477 5467 }
5478 5468
5479 5469
5480 5470 /*
5481 5471 * ibdm_send_ioc_profile()
5482 5472 * Send IOC Controller Profile request. When the request is completed
5483 5473 * IBMF calls ibdm_process_incoming_mad routine to inform about
5484 5474 * the completion.
5485 5475 */
5486 5476 static int
5487 5477 ibdm_send_ioc_profile(ibdm_dp_gidinfo_t *gid_info, uint8_t ioc_no)
5488 5478 {
5489 5479 ibmf_msg_t *msg;
5490 5480 ib_mad_hdr_t *hdr;
5491 5481 ibdm_ioc_info_t *ioc_info = &(gid_info->gl_iou->iou_ioc_info[ioc_no]);
5492 5482 ibdm_timeout_cb_args_t *cb_args;
5493 5483
5494 5484 IBTF_DPRINTF_L4("ibdm", "\tsend_ioc_profile: "
5495 5485 "gid info 0x%p, ioc_no = %d", gid_info, ioc_no);
5496 5486
5497 5487 /*
5498 5488 * Send command to get IOC profile.
5499 5489 * Allocate a IBMF packet and initialize the packet.
5500 5490 */
5501 5491 if (ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_SLEEP,
5502 5492 &msg) != IBMF_SUCCESS) {
5503 5493 IBTF_DPRINTF_L2("ibdm", "\tsend_ioc_profile: pkt alloc fail");
5504 5494 return (IBDM_FAILURE);
5505 5495 }
5506 5496
5507 5497 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
5508 5498 ibdm_alloc_send_buffers(msg);
5509 5499 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
5510 5500
5511 5501 mutex_enter(&gid_info->gl_mutex);
5512 5502 ibdm_bump_transactionID(gid_info);
5513 5503 mutex_exit(&gid_info->gl_mutex);
5514 5504
5515 5505 msg->im_local_addr.ia_local_lid = gid_info->gl_slid;
5516 5506 msg->im_local_addr.ia_remote_lid = gid_info->gl_dlid;
5517 5507 if (gid_info->gl_redirected == B_TRUE) {
5518 5508 if (gid_info->gl_redirect_dlid != 0) {
5519 5509 msg->im_local_addr.ia_remote_lid =
5520 5510 gid_info->gl_redirect_dlid;
5521 5511 }
5522 5512 msg->im_local_addr.ia_remote_qno = gid_info->gl_redirect_QP;
5523 5513 msg->im_local_addr.ia_p_key = gid_info->gl_redirect_pkey;
5524 5514 msg->im_local_addr.ia_q_key = gid_info->gl_redirect_qkey;
5525 5515 msg->im_local_addr.ia_service_level = gid_info->gl_redirectSL;
5526 5516 } else {
5527 5517 msg->im_local_addr.ia_remote_qno = 1;
5528 5518 msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
5529 5519 msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
5530 5520 msg->im_local_addr.ia_service_level = gid_info->gl_SL;
5531 5521 }
5532 5522
5533 5523 hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
5534 5524 hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
5535 5525 hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
5536 5526 hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
5537 5527 hdr->R_Method = IB_DM_DEVMGT_METHOD_GET;
5538 5528 hdr->Status = 0;
5539 5529 hdr->TransactionID = h2b64(gid_info->gl_transactionID);
5540 5530 hdr->AttributeID = h2b16(IB_DM_ATTR_IOC_CTRL_PROFILE);
5541 5531 hdr->AttributeModifier = h2b32(ioc_no + 1);
5542 5532
5543 5533 ioc_info->ioc_state = IBDM_IOC_STATE_REPROBE_PROGRESS;
5544 5534 cb_args = &ioc_info->ioc_cb_args;
5545 5535 cb_args->cb_gid_info = gid_info;
5546 5536 cb_args->cb_retry_count = ibdm_dft_retry_cnt;
5547 5537 cb_args->cb_req_type = IBDM_REQ_TYPE_IOCINFO;
5548 5538 cb_args->cb_ioc_num = ioc_no;
5549 5539
5550 5540 mutex_enter(&gid_info->gl_mutex);
5551 5541 ioc_info->ioc_timeout_id = timeout(ibdm_pkt_timeout_hdlr,
5552 5542 cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
5553 5543 mutex_exit(&gid_info->gl_mutex);
5554 5544
5555 5545 IBTF_DPRINTF_L5("ibdm", "\tsend_ioc_profile:"
5556 5546 "timeout %x", ioc_info->ioc_timeout_id);
5557 5547
5558 5548 if (ibmf_msg_transport(gid_info->gl_ibmf_hdl, gid_info->gl_qp_hdl, msg,
5559 5549 NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
5560 5550 IBTF_DPRINTF_L2("ibdm",
5561 5551 "\tsend_ioc_profile: msg transport failed");
5562 5552 ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl, msg, cb_args);
5563 5553 }
5564 5554 ioc_info->ioc_state = IBDM_IOC_STATE_REPROBE_PROGRESS;
5565 5555 return (IBDM_SUCCESS);
5566 5556 }
5567 5557
5568 5558
5569 5559 /*
5570 5560 * ibdm_port_reachable
5571 5561 * Returns B_TRUE if the port GID is reachable by sending
5572 5562 * a SA query to get the NODE record for this port GUID.
5573 5563 */
5574 5564 static boolean_t
5575 5565 ibdm_port_reachable(ibmf_saa_handle_t sa_hdl, ib_guid_t guid)
5576 5566 {
5577 5567 sa_node_record_t *resp;
5578 5568 size_t length;
5579 5569
5580 5570 /*
5581 5571 * Verify if it's reachable by getting the node record.
5582 5572 */
5583 5573 if (ibdm_get_node_record_by_port(sa_hdl, guid, &resp, &length) ==
5584 5574 IBDM_SUCCESS) {
5585 5575 kmem_free(resp, length);
5586 5576 return (B_TRUE);
5587 5577 }
5588 5578 return (B_FALSE);
5589 5579 }
5590 5580
5591 5581 /*
5592 5582 * ibdm_get_node_record_by_port
5593 5583 * Sends a SA query to get the NODE record for port GUID
5594 5584 * Returns IBDM_SUCCESS if the port GID is reachable.
5595 5585 *
5596 5586 * Note: the caller must be responsible for freeing the resource
5597 5587 * by calling kmem_free(resp, length) later.
5598 5588 */
5599 5589 static int
5600 5590 ibdm_get_node_record_by_port(ibmf_saa_handle_t sa_hdl, ib_guid_t guid,
5601 5591 sa_node_record_t **resp, size_t *length)
5602 5592 {
5603 5593 sa_node_record_t req;
5604 5594 ibmf_saa_access_args_t args;
5605 5595 int ret;
5606 5596 ASSERT(resp != NULL && length != NULL);
5607 5597
5608 5598 IBTF_DPRINTF_L4("ibdm", "\tport_reachable: port_guid %llx",
5609 5599 guid);
5610 5600
5611 5601 bzero(&req, sizeof (sa_node_record_t));
5612 5602 req.NodeInfo.PortGUID = guid;
5613 5603
5614 5604 args.sq_attr_id = SA_NODERECORD_ATTRID;
5615 5605 args.sq_access_type = IBMF_SAA_RETRIEVE;
5616 5606 args.sq_component_mask = SA_NODEINFO_COMPMASK_PORTGUID;
5617 5607 args.sq_template = &req;
5618 5608 args.sq_callback = NULL;
5619 5609 args.sq_callback_arg = NULL;
5620 5610
5621 5611 ret = ibmf_sa_access(sa_hdl, &args, 0, length, (void **) resp);
5622 5612 if (ret != IBMF_SUCCESS) {
5623 5613 IBTF_DPRINTF_L2("ibdm", "\tport_reachable:"
5624 5614 " SA Retrieve Failed: %d", ret);
5625 5615 return (IBDM_FAILURE);
5626 5616 }
5627 5617 if (*resp == NULL || *length == 0) {
5628 5618 IBTF_DPRINTF_L2("ibdm", "\tport_reachable: No records");
5629 5619 return (IBDM_FAILURE);
5630 5620 }
5631 5621 /*
5632 5622 * There is one NodeRecord on each endport on a subnet.
5633 5623 */
5634 5624 ASSERT(*length == sizeof (sa_node_record_t));
5635 5625
5636 5626 return (IBDM_SUCCESS);
5637 5627 }
5638 5628
5639 5629
5640 5630 /*
5641 5631 * Update the gidlist for all affected IOCs when GID becomes
5642 5632 * available/unavailable.
5643 5633 *
5644 5634 * Parameters :
5645 5635 * gidinfo - Incoming / Outgoing GID.
5646 5636 * add_flag - 1 for GID added, 0 for GID removed.
5647 5637 * - (-1) : IOC gid list updated, ioc_list required.
5648 5638 *
5649 5639 * This function gets the GID for the node GUID corresponding to the
5650 5640 * port GID. Gets the IOU info
5651 5641 */
5652 5642 static ibdm_ioc_info_t *
5653 5643 ibdm_update_ioc_gidlist(ibdm_dp_gidinfo_t *gid_info, int avail_flag)
5654 5644 {
5655 5645 ibdm_dp_gidinfo_t *node_gid = NULL;
5656 5646 uint8_t niocs, ii;
5657 5647 ibdm_ioc_info_t *ioc, *ioc_list = NULL, *tmp;
5658 5648
5659 5649 IBTF_DPRINTF_L4("ibdm", "\tupdate_ioc_gidlist");
5660 5650
5661 5651 switch (avail_flag) {
5662 5652 case 1 :
5663 5653 node_gid = ibdm_check_dest_nodeguid(gid_info);
5664 5654 break;
5665 5655 case 0 :
5666 5656 node_gid = ibdm_handle_gid_rm(gid_info);
5667 5657 break;
5668 5658 case -1 :
5669 5659 node_gid = gid_info;
5670 5660 break;
5671 5661 default :
5672 5662 break;
5673 5663 }
5674 5664
5675 5665 if (node_gid == NULL) {
5676 5666 IBTF_DPRINTF_L4("ibdm", "\tupdate_ioc_gidlist: "
5677 5667 "No node GID found, port gid 0x%p, avail_flag %d",
5678 5668 gid_info, avail_flag);
5679 5669 return (NULL);
5680 5670 }
5681 5671
5682 5672 mutex_enter(&node_gid->gl_mutex);
5683 5673 if ((node_gid->gl_state != IBDM_GID_PROBING_COMPLETE &&
5684 5674 node_gid->gl_state != IBDM_GID_PROBING_SKIPPED) ||
5685 5675 node_gid->gl_iou == NULL) {
5686 5676 IBTF_DPRINTF_L4("ibdm", "\tupdate_ioc_gidlist "
5687 5677 "gl_state %x, gl_iou %p", node_gid->gl_state,
5688 5678 node_gid->gl_iou);
5689 5679 mutex_exit(&node_gid->gl_mutex);
5690 5680 return (NULL);
5691 5681 }
5692 5682
5693 5683 niocs = node_gid->gl_iou->iou_info.iou_num_ctrl_slots;
5694 5684 IBTF_DPRINTF_L4("ibdm", "\tupdate_ioc_gidlist : niocs %x",
5695 5685 niocs);
5696 5686 for (ii = 0; ii < niocs; ii++) {
5697 5687 ioc = IBDM_GIDINFO2IOCINFO(node_gid, ii);
5698 5688 /*
5699 5689 * Skip IOCs for which probe is not complete or
5700 5690 * reprobe is progress
5701 5691 */
5702 5692 if (ioc->ioc_state == IBDM_IOC_STATE_PROBE_SUCCESS) {
5703 5693 tmp = ibdm_dup_ioc_info(ioc, node_gid);
5704 5694 tmp->ioc_info_updated.ib_gid_prop_updated = 1;
5705 5695 tmp->ioc_next = ioc_list;
5706 5696 ioc_list = tmp;
5707 5697 }
5708 5698 }
5709 5699 mutex_exit(&node_gid->gl_mutex);
5710 5700
5711 5701 IBTF_DPRINTF_L4("ibdm", "\tupdate_ioc_gidlist : return %p",
5712 5702 ioc_list);
5713 5703 return (ioc_list);
5714 5704 }
5715 5705
5716 5706 /*
5717 5707 * ibdm_saa_event_cb :
5718 5708 * Event handling which does *not* require ibdm_hl_mutex to be
5719 5709 * held are executed in the same thread. This is to prevent
5720 5710 * deadlocks with HCA port down notifications which hold the
5721 5711 * ibdm_hl_mutex.
5722 5712 *
5723 5713 * GID_AVAILABLE event is handled here. A taskq is spawned to
5724 5714 * handle GID_UNAVAILABLE.
5725 5715 *
5726 5716 * A new mutex ibdm_ibnex_mutex has been introduced to protect
5727 5717 * ibnex_callback. This has been done to prevent any possible
5728 5718 * deadlock (described above) while handling GID_AVAILABLE.
5729 5719 *
5730 5720 * IBMF calls the event callback for a HCA port. The SA handle
5731 5721 * for this port would be valid, till the callback returns.
5732 5722 * IBDM calling IBDM using the above SA handle should be valid.
5733 5723 *
5734 5724 * IBDM will additionally check (SA handle != NULL), before
5735 5725 * calling IBMF.
5736 5726 */
5737 5727 /*ARGSUSED*/
5738 5728 static void
5739 5729 ibdm_saa_event_cb(ibmf_saa_handle_t ibmf_saa_handle,
5740 5730 ibmf_saa_subnet_event_t ibmf_saa_event,
5741 5731 ibmf_saa_event_details_t *event_details, void *callback_arg)
5742 5732 {
5743 5733 ibdm_saa_event_arg_t *event_arg;
5744 5734 ib_gid_t sgid, dgid;
5745 5735 ibdm_port_attr_t *hca_port;
5746 5736 ibdm_dp_gidinfo_t *gid_info, *node_gid_info = NULL;
5747 5737 sa_node_record_t *nrec;
5748 5738 size_t length;
5749 5739
5750 5740 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*event_arg));
5751 5741
5752 5742 hca_port = (ibdm_port_attr_t *)callback_arg;
5753 5743
5754 5744 IBTF_DPRINTF_L4("ibdm", "\tsaa_event_cb(%x, %x, %x, %x)\n",
5755 5745 ibmf_saa_handle, ibmf_saa_event, event_details,
5756 5746 callback_arg);
5757 5747
5758 5748 #ifdef DEBUG
5759 5749 if (ibdm_ignore_saa_event)
5760 5750 return;
5761 5751 #endif
5762 5752
5763 5753 if (ibmf_saa_event == IBMF_SAA_EVENT_GID_AVAILABLE) {
5764 5754 /*
5765 5755 * Ensure no other probe / sweep fabric is in
5766 5756 * progress.
5767 5757 */
5768 5758 mutex_enter(&ibdm.ibdm_mutex);
5769 5759 while (ibdm.ibdm_busy & IBDM_BUSY)
5770 5760 cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
5771 5761 ibdm.ibdm_busy |= IBDM_BUSY;
5772 5762 mutex_exit(&ibdm.ibdm_mutex);
5773 5763
5774 5764 /*
5775 5765 * If we already know about this GID, return.
5776 5766 * GID_AVAILABLE may be reported for multiple HCA
5777 5767 * ports.
5778 5768 */
5779 5769 if ((ibdm_check_dgid(event_details->ie_gid.gid_guid,
5780 5770 event_details->ie_gid.gid_prefix)) != NULL) {
5781 5771 mutex_enter(&ibdm.ibdm_mutex);
5782 5772 ibdm.ibdm_busy &= ~IBDM_BUSY;
5783 5773 cv_broadcast(&ibdm.ibdm_busy_cv);
5784 5774 mutex_exit(&ibdm.ibdm_mutex);
5785 5775 return;
5786 5776 }
5787 5777
5788 5778 IBTF_DPRINTF_L4("ibdm", "\tGID (prefix %x, guid %llx) "
5789 5779 "Insertion notified",
5790 5780 event_details->ie_gid.gid_prefix,
5791 5781 event_details->ie_gid.gid_guid);
5792 5782
5793 5783 /* This is a new gid, insert it to GID list */
5794 5784 sgid.gid_prefix = hca_port->pa_sn_prefix;
5795 5785 sgid.gid_guid = hca_port->pa_port_guid;
5796 5786 dgid.gid_prefix = event_details->ie_gid.gid_prefix;
5797 5787 dgid.gid_guid = event_details->ie_gid.gid_guid;
5798 5788 gid_info = ibdm_create_gid_info(hca_port, sgid, dgid);
5799 5789 if (gid_info == NULL) {
5800 5790 IBTF_DPRINTF_L4("ibdm", "\tGID_AVAILABLE: "
5801 5791 "create_gid_info returned NULL");
5802 5792 mutex_enter(&ibdm.ibdm_mutex);
5803 5793 ibdm.ibdm_busy &= ~IBDM_BUSY;
5804 5794 cv_broadcast(&ibdm.ibdm_busy_cv);
5805 5795 mutex_exit(&ibdm.ibdm_mutex);
5806 5796 return;
5807 5797 }
5808 5798 mutex_enter(&gid_info->gl_mutex);
5809 5799 gid_info->gl_state = IBDM_GID_PROBING_SKIPPED;
5810 5800 mutex_exit(&gid_info->gl_mutex);
5811 5801
5812 5802 /* Get the node GUID */
5813 5803 if (ibdm_get_node_record_by_port(ibmf_saa_handle, dgid.gid_guid,
5814 5804 &nrec, &length) != IBDM_SUCCESS) {
5815 5805 /*
5816 5806 * Set the state to PROBE_NOT_DONE for the
5817 5807 * next sweep to probe it
5818 5808 */
5819 5809 IBTF_DPRINTF_L2("ibdm", "\tsaa_event_taskq: "
5820 5810 "Skipping GID : port GUID not found");
5821 5811 mutex_enter(&gid_info->gl_mutex);
5822 5812 gid_info->gl_state = IBDM_GID_PROBE_NOT_DONE;
5823 5813 mutex_exit(&gid_info->gl_mutex);
5824 5814 mutex_enter(&ibdm.ibdm_mutex);
5825 5815 ibdm.ibdm_busy &= ~IBDM_BUSY;
5826 5816 cv_broadcast(&ibdm.ibdm_busy_cv);
5827 5817 mutex_exit(&ibdm.ibdm_mutex);
5828 5818 return;
5829 5819 }
5830 5820 gid_info->gl_nodeguid = nrec->NodeInfo.NodeGUID;
5831 5821 gid_info->gl_devid = nrec->NodeInfo.DeviceID;
5832 5822 kmem_free(nrec, length);
5833 5823 gid_info->gl_portguid = dgid.gid_guid;
5834 5824
5835 5825 /*
5836 5826 * Get the gid info with the same node GUID.
5837 5827 */
5838 5828 mutex_enter(&ibdm.ibdm_mutex);
5839 5829 node_gid_info = ibdm.ibdm_dp_gidlist_head;
5840 5830 while (node_gid_info) {
5841 5831 if (node_gid_info->gl_nodeguid ==
5842 5832 gid_info->gl_nodeguid &&
5843 5833 node_gid_info->gl_iou != NULL) {
5844 5834 break;
5845 5835 }
5846 5836 node_gid_info = node_gid_info->gl_next;
5847 5837 }
5848 5838 mutex_exit(&ibdm.ibdm_mutex);
5849 5839
5850 5840 /*
5851 5841 * Handling a new GID requires filling of gl_hca_list.
5852 5842 * This require ibdm hca_list to be parsed and hence
5853 5843 * holding the ibdm_hl_mutex. Spawning a new thread to
5854 5844 * handle this.
5855 5845 */
5856 5846 if (node_gid_info == NULL) {
5857 5847 if (taskq_dispatch(system_taskq,
5858 5848 ibdm_saa_handle_new_gid, (void *)gid_info,
5859 5849 TQ_NOSLEEP) == NULL) {
5860 5850 IBTF_DPRINTF_L2("ibdm", "\tsaa_event_cb: "
5861 5851 "new_gid taskq_dispatch failed");
5862 5852 return;
5863 5853 }
5864 5854 }
5865 5855
5866 5856 mutex_enter(&ibdm.ibdm_mutex);
5867 5857 ibdm.ibdm_busy &= ~IBDM_BUSY;
5868 5858 cv_broadcast(&ibdm.ibdm_busy_cv);
5869 5859 mutex_exit(&ibdm.ibdm_mutex);
5870 5860 return;
5871 5861 }
5872 5862
5873 5863 if (ibmf_saa_event != IBMF_SAA_EVENT_GID_UNAVAILABLE)
5874 5864 return;
5875 5865
5876 5866 /*
5877 5867 * GID UNAVAIL EVENT: Try to locate the GID in the GID list.
5878 5868 * If we don't find it we just return.
5879 5869 */
5880 5870 mutex_enter(&ibdm.ibdm_mutex);
5881 5871 gid_info = ibdm.ibdm_dp_gidlist_head;
5882 5872 while (gid_info) {
5883 5873 if (gid_info->gl_portguid ==
5884 5874 event_details->ie_gid.gid_guid) {
5885 5875 break;
5886 5876 }
5887 5877 gid_info = gid_info->gl_next;
5888 5878 }
5889 5879 mutex_exit(&ibdm.ibdm_mutex);
5890 5880 if (gid_info == NULL) {
5891 5881 IBTF_DPRINTF_L2("ibdm", "\tsaa_event_cb: "
5892 5882 "GID for GUID %llX not found during GID UNAVAIL event",
5893 5883 event_details->ie_gid.gid_guid);
5894 5884 return;
5895 5885 }
5896 5886
5897 5887 /*
5898 5888 * If this GID is DM capable, we'll have to check whether this DGID
5899 5889 * is reachable via another port.
5900 5890 */
5901 5891 if (gid_info->gl_is_dm_capable == B_TRUE) {
5902 5892 event_arg = (ibdm_saa_event_arg_t *)kmem_alloc(
5903 5893 sizeof (ibdm_saa_event_arg_t), KM_SLEEP);
5904 5894 event_arg->ibmf_saa_handle = ibmf_saa_handle;
5905 5895 event_arg->ibmf_saa_event = ibmf_saa_event;
5906 5896 bcopy(event_details, &event_arg->event_details,
5907 5897 sizeof (ibmf_saa_event_details_t));
5908 5898 event_arg->callback_arg = callback_arg;
5909 5899
5910 5900 if (taskq_dispatch(system_taskq, ibdm_saa_event_taskq,
5911 5901 (void *)event_arg, TQ_NOSLEEP) == NULL) {
5912 5902 IBTF_DPRINTF_L2("ibdm", "\tsaa_event_cb: "
5913 5903 "taskq_dispatch failed");
5914 5904 ibdm_free_saa_event_arg(event_arg);
5915 5905 return;
5916 5906 }
5917 5907 }
5918 5908 }
5919 5909
5920 5910 /*
5921 5911 * Handle a new GID discovered by GID_AVAILABLE saa event.
5922 5912 */
5923 5913 void
5924 5914 ibdm_saa_handle_new_gid(void *arg)
5925 5915 {
5926 5916 ibdm_dp_gidinfo_t *gid_info;
5927 5917 ibdm_hca_list_t *hca_list = NULL;
5928 5918 ibdm_port_attr_t *port = NULL;
5929 5919 ibdm_ioc_info_t *ioc_list = NULL;
5930 5920
5931 5921 IBTF_DPRINTF_L4(ibdm_string, "\tsaa_handle_new_gid(%p)", arg);
5932 5922
5933 5923 gid_info = (ibdm_dp_gidinfo_t *)arg;
5934 5924
5935 5925 /*
5936 5926 * Ensure that no other sweep / probe has completed
5937 5927 * probing this gid.
5938 5928 */
5939 5929 mutex_enter(&gid_info->gl_mutex);
5940 5930 if (gid_info->gl_state != IBDM_GID_PROBE_NOT_DONE) {
5941 5931 mutex_exit(&gid_info->gl_mutex);
5942 5932 return;
5943 5933 }
5944 5934 mutex_exit(&gid_info->gl_mutex);
5945 5935
5946 5936 /*
5947 5937 * Parse HCAs to fill gl_hca_list
5948 5938 */
5949 5939 mutex_enter(&ibdm.ibdm_hl_mutex);
5950 5940 for (ibdm_get_next_port(&hca_list, &port, 1); port;
5951 5941 ibdm_get_next_port(&hca_list, &port, 1)) {
5952 5942 if (ibdm_port_reachable(port->pa_sa_hdl,
5953 5943 gid_info->gl_portguid) == B_TRUE) {
5954 5944 ibdm_addto_glhcalist(gid_info, hca_list);
5955 5945 }
5956 5946 }
5957 5947 mutex_exit(&ibdm.ibdm_hl_mutex);
5958 5948
5959 5949 /*
5960 5950 * Ensure no other probe / sweep fabric is in
5961 5951 * progress.
5962 5952 */
5963 5953 mutex_enter(&ibdm.ibdm_mutex);
5964 5954 while (ibdm.ibdm_busy & IBDM_BUSY)
5965 5955 cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
5966 5956 ibdm.ibdm_busy |= IBDM_BUSY;
5967 5957 mutex_exit(&ibdm.ibdm_mutex);
5968 5958
5969 5959 /*
5970 5960 * New IOU probe it, to check if new IOCs
5971 5961 */
5972 5962 IBTF_DPRINTF_L4(ibdm_string, "\tsaa_handle_new_gid: "
5973 5963 "new GID : probing");
5974 5964 mutex_enter(&ibdm.ibdm_mutex);
5975 5965 ibdm.ibdm_ngid_probes_in_progress++;
5976 5966 mutex_exit(&ibdm.ibdm_mutex);
5977 5967 mutex_enter(&gid_info->gl_mutex);
5978 5968 gid_info->gl_reprobe_flag = 0;
5979 5969 gid_info->gl_state = IBDM_GID_PROBE_NOT_DONE;
5980 5970 mutex_exit(&gid_info->gl_mutex);
5981 5971 ibdm_probe_gid_thread((void *)gid_info);
5982 5972
5983 5973 mutex_enter(&ibdm.ibdm_mutex);
5984 5974 ibdm_wait_probe_completion();
5985 5975 mutex_exit(&ibdm.ibdm_mutex);
5986 5976
5987 5977 if (gid_info->gl_iou == NULL) {
5988 5978 mutex_enter(&ibdm.ibdm_mutex);
5989 5979 ibdm.ibdm_busy &= ~IBDM_BUSY;
5990 5980 cv_broadcast(&ibdm.ibdm_busy_cv);
5991 5981 mutex_exit(&ibdm.ibdm_mutex);
5992 5982 return;
5993 5983 }
5994 5984
5995 5985 /*
5996 5986 * Update GID list in all IOCs affected by this
5997 5987 */
5998 5988 ioc_list = ibdm_update_ioc_gidlist(gid_info, 1);
5999 5989
6000 5990 /*
6001 5991 * Pass on the IOCs with updated GIDs to IBnexus
6002 5992 */
6003 5993 if (ioc_list) {
6004 5994 mutex_enter(&ibdm.ibdm_ibnex_mutex);
6005 5995 if (ibdm.ibdm_ibnex_callback != NULL) {
6006 5996 (*ibdm.ibdm_ibnex_callback)((void *)ioc_list,
6007 5997 IBDM_EVENT_IOC_PROP_UPDATE);
6008 5998 }
6009 5999 mutex_exit(&ibdm.ibdm_ibnex_mutex);
6010 6000 }
6011 6001
6012 6002 mutex_enter(&ibdm.ibdm_mutex);
6013 6003 ibdm.ibdm_busy &= ~IBDM_BUSY;
6014 6004 cv_broadcast(&ibdm.ibdm_busy_cv);
6015 6005 mutex_exit(&ibdm.ibdm_mutex);
6016 6006 }
6017 6007
6018 6008 /*
6019 6009 * ibdm_saa_event_taskq :
6020 6010 * GID_UNAVAILABLE Event handling requires ibdm_hl_mutex to be
6021 6011 * held. The GID_UNAVAILABLE handling is done in a taskq to
6022 6012 * prevent deadlocks with HCA port down notifications which hold
6023 6013 * ibdm_hl_mutex.
6024 6014 */
6025 6015 void
6026 6016 ibdm_saa_event_taskq(void *arg)
6027 6017 {
6028 6018 ibdm_saa_event_arg_t *event_arg;
6029 6019 ibmf_saa_handle_t ibmf_saa_handle;
6030 6020 ibmf_saa_subnet_event_t ibmf_saa_event;
6031 6021 ibmf_saa_event_details_t *event_details;
6032 6022 void *callback_arg;
6033 6023
6034 6024 ibdm_dp_gidinfo_t *gid_info;
6035 6025 ibdm_port_attr_t *hca_port, *port = NULL;
6036 6026 ibdm_hca_list_t *hca_list = NULL;
6037 6027 int sa_handle_valid = 0;
6038 6028 ibdm_ioc_info_t *ioc_list = NULL;
6039 6029
6040 6030 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*event_arg));
6041 6031
6042 6032 event_arg = (ibdm_saa_event_arg_t *)arg;
6043 6033 ibmf_saa_handle = event_arg->ibmf_saa_handle;
6044 6034 ibmf_saa_event = event_arg->ibmf_saa_event;
6045 6035 event_details = &event_arg->event_details;
6046 6036 callback_arg = event_arg->callback_arg;
6047 6037
6048 6038 ASSERT(callback_arg != NULL);
6049 6039 ASSERT(ibmf_saa_event == IBMF_SAA_EVENT_GID_UNAVAILABLE);
6050 6040 IBTF_DPRINTF_L4("ibdm", "\tsaa_event_taskq(%x, %x, %x, %x)",
6051 6041 ibmf_saa_handle, ibmf_saa_event, event_details,
6052 6042 callback_arg);
6053 6043
6054 6044 hca_port = (ibdm_port_attr_t *)callback_arg;
6055 6045
6056 6046 /* Check if the port_attr is still valid */
6057 6047 mutex_enter(&ibdm.ibdm_hl_mutex);
6058 6048 for (ibdm_get_next_port(&hca_list, &port, 0); port;
6059 6049 ibdm_get_next_port(&hca_list, &port, 0)) {
6060 6050 if (port == hca_port && port->pa_port_guid ==
6061 6051 hca_port->pa_port_guid) {
6062 6052 if (ibmf_saa_handle == hca_port->pa_sa_hdl)
6063 6053 sa_handle_valid = 1;
6064 6054 break;
6065 6055 }
6066 6056 }
6067 6057 mutex_exit(&ibdm.ibdm_hl_mutex);
6068 6058 if (sa_handle_valid == 0) {
6069 6059 ibdm_free_saa_event_arg(event_arg);
6070 6060 return;
6071 6061 }
6072 6062
6073 6063 if (hca_port && (hca_port->pa_sa_hdl == NULL ||
6074 6064 ibmf_saa_handle != hca_port->pa_sa_hdl)) {
6075 6065 ibdm_free_saa_event_arg(event_arg);
6076 6066 return;
6077 6067 }
6078 6068 hca_list = NULL;
6079 6069 port = NULL;
6080 6070
6081 6071 /*
6082 6072 * Check if the GID is visible to other HCA ports.
6083 6073 * Return if so.
6084 6074 */
6085 6075 mutex_enter(&ibdm.ibdm_hl_mutex);
6086 6076 for (ibdm_get_next_port(&hca_list, &port, 1); port;
6087 6077 ibdm_get_next_port(&hca_list, &port, 1)) {
6088 6078 if (ibdm_port_reachable(port->pa_sa_hdl,
6089 6079 event_details->ie_gid.gid_guid) == B_TRUE) {
6090 6080 mutex_exit(&ibdm.ibdm_hl_mutex);
6091 6081 ibdm_free_saa_event_arg(event_arg);
6092 6082 return;
6093 6083 }
6094 6084 }
6095 6085 mutex_exit(&ibdm.ibdm_hl_mutex);
6096 6086
6097 6087 /*
6098 6088 * Ensure no other probe / sweep fabric is in
6099 6089 * progress.
6100 6090 */
6101 6091 mutex_enter(&ibdm.ibdm_mutex);
6102 6092 while (ibdm.ibdm_busy & IBDM_BUSY)
6103 6093 cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
6104 6094 ibdm.ibdm_busy |= IBDM_BUSY;
6105 6095 mutex_exit(&ibdm.ibdm_mutex);
6106 6096
6107 6097 /*
6108 6098 * If this GID is no longer in GID list, return
6109 6099 * GID_UNAVAILABLE may be reported for multiple HCA
6110 6100 * ports.
6111 6101 */
6112 6102 mutex_enter(&ibdm.ibdm_mutex);
6113 6103 gid_info = ibdm.ibdm_dp_gidlist_head;
6114 6104 while (gid_info) {
6115 6105 if (gid_info->gl_portguid ==
6116 6106 event_details->ie_gid.gid_guid) {
6117 6107 break;
6118 6108 }
6119 6109 gid_info = gid_info->gl_next;
6120 6110 }
6121 6111 mutex_exit(&ibdm.ibdm_mutex);
6122 6112 if (gid_info == NULL) {
6123 6113 mutex_enter(&ibdm.ibdm_mutex);
6124 6114 ibdm.ibdm_busy &= ~IBDM_BUSY;
6125 6115 cv_broadcast(&ibdm.ibdm_busy_cv);
6126 6116 mutex_exit(&ibdm.ibdm_mutex);
6127 6117 ibdm_free_saa_event_arg(event_arg);
6128 6118 return;
6129 6119 }
6130 6120
6131 6121 IBTF_DPRINTF_L4("ibdm", "\tGID (prefix %x, guid %llx) "
6132 6122 "Unavailable notification",
6133 6123 event_details->ie_gid.gid_prefix,
6134 6124 event_details->ie_gid.gid_guid);
6135 6125
6136 6126 /*
6137 6127 * Update GID list in all IOCs affected by this
6138 6128 */
6139 6129 if (gid_info->gl_state == IBDM_GID_PROBING_SKIPPED ||
6140 6130 gid_info->gl_state == IBDM_GID_PROBING_COMPLETE)
6141 6131 ioc_list = ibdm_update_ioc_gidlist(gid_info, 0);
6142 6132
6143 6133 /*
6144 6134 * Remove GID from the global GID list
6145 6135 * Handle the case where all port GIDs for an
6146 6136 * IOU have been hot-removed. Check both gid_info
6147 6137 * & ioc_info for checking ngids.
6148 6138 */
6149 6139 mutex_enter(&ibdm.ibdm_mutex);
6150 6140 if (gid_info->gl_iou != NULL && gid_info->gl_ngids == 0) {
6151 6141 mutex_enter(&gid_info->gl_mutex);
6152 6142 (void) ibdm_free_iou_info(gid_info, &gid_info->gl_iou);
6153 6143 mutex_exit(&gid_info->gl_mutex);
6154 6144 }
6155 6145 if (gid_info->gl_prev != NULL)
6156 6146 gid_info->gl_prev->gl_next = gid_info->gl_next;
6157 6147 if (gid_info->gl_next != NULL)
6158 6148 gid_info->gl_next->gl_prev = gid_info->gl_prev;
6159 6149
6160 6150 if (gid_info == ibdm.ibdm_dp_gidlist_head)
6161 6151 ibdm.ibdm_dp_gidlist_head = gid_info->gl_next;
6162 6152 if (gid_info == ibdm.ibdm_dp_gidlist_tail)
6163 6153 ibdm.ibdm_dp_gidlist_tail = gid_info->gl_prev;
6164 6154 ibdm.ibdm_ngids--;
6165 6155
6166 6156 ibdm.ibdm_busy &= ~IBDM_BUSY;
6167 6157 cv_broadcast(&ibdm.ibdm_busy_cv);
6168 6158 mutex_exit(&ibdm.ibdm_mutex);
6169 6159
6170 6160 /* free the hca_list on this gid_info */
6171 6161 ibdm_delete_glhca_list(gid_info);
6172 6162
6173 6163 mutex_destroy(&gid_info->gl_mutex);
6174 6164 kmem_free(gid_info, sizeof (ibdm_dp_gidinfo_t));
6175 6165
6176 6166 /*
6177 6167 * Pass on the IOCs with updated GIDs to IBnexus
6178 6168 */
6179 6169 if (ioc_list) {
6180 6170 IBTF_DPRINTF_L4("ibdm", "\tGID_UNAVAILABLE "
6181 6171 "IOC_PROP_UPDATE for %p\n", ioc_list);
6182 6172 mutex_enter(&ibdm.ibdm_ibnex_mutex);
6183 6173 if (ibdm.ibdm_ibnex_callback != NULL) {
6184 6174 (*ibdm.ibdm_ibnex_callback)((void *)
6185 6175 ioc_list, IBDM_EVENT_IOC_PROP_UPDATE);
6186 6176 }
6187 6177 mutex_exit(&ibdm.ibdm_ibnex_mutex);
6188 6178 }
6189 6179
6190 6180 ibdm_free_saa_event_arg(event_arg);
6191 6181 }
6192 6182
6193 6183
6194 6184 static int
6195 6185 ibdm_cmp_gid_list(ibdm_gid_t *new, ibdm_gid_t *prev)
6196 6186 {
6197 6187 ibdm_gid_t *scan_new, *scan_prev;
6198 6188 int cmp_failed = 0;
6199 6189
6200 6190 ASSERT(new != NULL);
6201 6191 ASSERT(prev != NULL);
6202 6192
6203 6193 /*
6204 6194 * Search for each new gid anywhere in the prev GID list.
6205 6195 * Note that the gid list could have been re-ordered.
6206 6196 */
6207 6197 for (scan_new = new; scan_new; scan_new = scan_new->gid_next) {
6208 6198 for (scan_prev = prev, cmp_failed = 1; scan_prev;
6209 6199 scan_prev = scan_prev->gid_next) {
6210 6200 if (scan_prev->gid_dgid_hi == scan_new->gid_dgid_hi &&
6211 6201 scan_prev->gid_dgid_lo == scan_new->gid_dgid_lo) {
6212 6202 cmp_failed = 0;
6213 6203 break;
6214 6204 }
6215 6205 }
6216 6206
6217 6207 if (cmp_failed)
6218 6208 return (1);
6219 6209 }
6220 6210 return (0);
6221 6211 }
6222 6212
6223 6213 /*
6224 6214 * This is always called in a single thread
6225 6215 * This function updates the gid_list and serv_list of IOC
6226 6216 * The current gid_list is in ioc_info_t(contains only port
6227 6217 * guids for which probe is done) & gidinfo_t(other port gids)
6228 6218 * The gids in both locations are used for comparision.
6229 6219 */
6230 6220 static void
6231 6221 ibdm_reprobe_update_port_srv(ibdm_ioc_info_t *ioc, ibdm_dp_gidinfo_t *gidinfo)
6232 6222 {
6233 6223 ibdm_gid_t *cur_gid_list;
6234 6224 uint_t cur_nportgids;
6235 6225
6236 6226 ASSERT(MUTEX_HELD(&ibdm.ibdm_mutex));
6237 6227
6238 6228 ioc->ioc_info_updated.ib_prop_updated = 0;
6239 6229
6240 6230
6241 6231 /* Current GID list in gid_info only */
6242 6232 cur_gid_list = gidinfo->gl_gid;
6243 6233 cur_nportgids = gidinfo->gl_ngids;
6244 6234
6245 6235 if (ioc->ioc_prev_serv_cnt !=
6246 6236 ioc->ioc_profile.ioc_service_entries ||
6247 6237 ibdm_serv_cmp(&ioc->ioc_serv[0], &ioc->ioc_prev_serv[0],
6248 6238 ioc->ioc_prev_serv_cnt))
6249 6239 ioc->ioc_info_updated.ib_srv_prop_updated = 1;
6250 6240
6251 6241 if (ioc->ioc_prev_nportgids != cur_nportgids ||
6252 6242 ioc->ioc_prev_gid_list == NULL || cur_gid_list == NULL) {
6253 6243 ioc->ioc_info_updated.ib_gid_prop_updated = 1;
6254 6244 } else if (ibdm_cmp_gid_list(ioc->ioc_prev_gid_list, cur_gid_list)) {
6255 6245 ioc->ioc_info_updated.ib_gid_prop_updated = 1;
6256 6246 }
6257 6247
6258 6248 /* Zero out previous entries */
6259 6249 ibdm_free_gid_list(ioc->ioc_prev_gid_list);
6260 6250 if (ioc->ioc_prev_serv)
6261 6251 kmem_free(ioc->ioc_prev_serv, ioc->ioc_prev_serv_cnt *
6262 6252 sizeof (ibdm_srvents_info_t));
6263 6253 ioc->ioc_prev_serv_cnt = 0;
6264 6254 ioc->ioc_prev_nportgids = 0;
6265 6255 ioc->ioc_prev_serv = NULL;
6266 6256 ioc->ioc_prev_gid_list = NULL;
6267 6257 }
6268 6258
6269 6259 /*
6270 6260 * Handle GID removal. This returns gid_info of an GID for the same
6271 6261 * node GUID, if found. For an GID with IOU information, the same
6272 6262 * gid_info is returned if no gid_info with same node_guid is found.
6273 6263 */
6274 6264 static ibdm_dp_gidinfo_t *
6275 6265 ibdm_handle_gid_rm(ibdm_dp_gidinfo_t *rm_gid)
6276 6266 {
6277 6267 ibdm_dp_gidinfo_t *gid_list;
6278 6268
6279 6269 IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm(0x%p)", rm_gid);
6280 6270
6281 6271 if (rm_gid->gl_iou == NULL) {
6282 6272 IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm NO iou");
6283 6273 /*
6284 6274 * Search for a GID with same node_guid and
6285 6275 * gl_iou != NULL
6286 6276 */
6287 6277 for (gid_list = ibdm.ibdm_dp_gidlist_head; gid_list;
6288 6278 gid_list = gid_list->gl_next) {
6289 6279 if (gid_list->gl_iou != NULL && (gid_list->gl_nodeguid
6290 6280 == rm_gid->gl_nodeguid))
6291 6281 break;
6292 6282 }
6293 6283
6294 6284 if (gid_list)
6295 6285 ibdm_rmfrom_glgid_list(gid_list, rm_gid);
6296 6286
6297 6287 IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm ret %p", gid_list);
6298 6288 return (gid_list);
6299 6289 } else {
6300 6290 /*
6301 6291 * Search for a GID with same node_guid and
6302 6292 * gl_iou == NULL
6303 6293 */
6304 6294 IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm with iou");
6305 6295 for (gid_list = ibdm.ibdm_dp_gidlist_head; gid_list;
6306 6296 gid_list = gid_list->gl_next) {
6307 6297 if (gid_list->gl_iou == NULL && (gid_list->gl_nodeguid
6308 6298 == rm_gid->gl_nodeguid))
6309 6299 break;
6310 6300 }
6311 6301
6312 6302 if (gid_list) {
6313 6303 /*
6314 6304 * Copy the following fields from rm_gid :
6315 6305 * 1. gl_state
6316 6306 * 2. gl_iou
6317 6307 * 3. gl_gid & gl_ngids
6318 6308 *
6319 6309 * Note : Function is synchronized by
6320 6310 * ibdm_busy flag.
6321 6311 *
6322 6312 * Note : Redirect info is initialized if
6323 6313 * any MADs for the GID fail
6324 6314 */
6325 6315 IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm "
6326 6316 "copying info to GID with gl_iou != NULl");
6327 6317 gid_list->gl_state = rm_gid->gl_state;
6328 6318 gid_list->gl_iou = rm_gid->gl_iou;
6329 6319 gid_list->gl_gid = rm_gid->gl_gid;
6330 6320 gid_list->gl_ngids = rm_gid->gl_ngids;
6331 6321
6332 6322 /* Remove the GID from gl_gid list */
6333 6323 ibdm_rmfrom_glgid_list(gid_list, rm_gid);
6334 6324 } else {
6335 6325 /*
6336 6326 * Handle a case where all GIDs to the IOU have
6337 6327 * been removed.
6338 6328 */
6339 6329 IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm 0 GID "
6340 6330 "to IOU");
6341 6331
6342 6332 ibdm_rmfrom_glgid_list(rm_gid, rm_gid);
6343 6333 return (rm_gid);
6344 6334 }
6345 6335 IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm ret %p", gid_list);
6346 6336 return (gid_list);
6347 6337 }
6348 6338 }
6349 6339
6350 6340 static void
6351 6341 ibdm_rmfrom_glgid_list(ibdm_dp_gidinfo_t *gid_info,
6352 6342 ibdm_dp_gidinfo_t *rm_gid)
6353 6343 {
6354 6344 ibdm_gid_t *tmp, *prev;
6355 6345
6356 6346 IBTF_DPRINTF_L4("ibdm", "\trmfrom_glgid (%p, %p)",
6357 6347 gid_info, rm_gid);
6358 6348
6359 6349 for (tmp = gid_info->gl_gid, prev = NULL; tmp; ) {
6360 6350 if (tmp->gid_dgid_hi == rm_gid->gl_dgid_hi &&
6361 6351 tmp->gid_dgid_lo == rm_gid->gl_dgid_lo) {
6362 6352 if (prev == NULL)
6363 6353 gid_info->gl_gid = tmp->gid_next;
6364 6354 else
6365 6355 prev->gid_next = tmp->gid_next;
6366 6356
6367 6357 kmem_free(tmp, sizeof (ibdm_gid_t));
6368 6358 gid_info->gl_ngids--;
6369 6359 break;
6370 6360 } else {
6371 6361 prev = tmp;
6372 6362 tmp = tmp->gid_next;
6373 6363 }
6374 6364 }
6375 6365 }
6376 6366
6377 6367 static void
6378 6368 ibdm_addto_gidlist(ibdm_gid_t **src_ptr, ibdm_gid_t *dest)
6379 6369 {
6380 6370 ibdm_gid_t *head = NULL, *new, *tail;
6381 6371
6382 6372 /* First copy the destination */
6383 6373 for (; dest; dest = dest->gid_next) {
6384 6374 new = kmem_zalloc(sizeof (ibdm_gid_t), KM_SLEEP);
6385 6375 new->gid_dgid_hi = dest->gid_dgid_hi;
6386 6376 new->gid_dgid_lo = dest->gid_dgid_lo;
6387 6377 new->gid_next = head;
6388 6378 head = new;
6389 6379 }
6390 6380
6391 6381 /* Insert this to the source */
6392 6382 if (*src_ptr == NULL)
6393 6383 *src_ptr = head;
6394 6384 else {
6395 6385 for (tail = *src_ptr; tail->gid_next != NULL;
6396 6386 tail = tail->gid_next)
6397 6387 ;
6398 6388
6399 6389 tail->gid_next = head;
6400 6390 }
6401 6391 }
6402 6392
6403 6393 static void
6404 6394 ibdm_free_gid_list(ibdm_gid_t *head)
6405 6395 {
6406 6396 ibdm_gid_t *delete;
6407 6397
6408 6398 for (delete = head; delete; ) {
6409 6399 head = delete->gid_next;
6410 6400 kmem_free(delete, sizeof (ibdm_gid_t));
6411 6401 delete = head;
6412 6402 }
6413 6403 }
6414 6404
6415 6405 /*
6416 6406 * This function rescans the DM capable GIDs (gl_state is
6417 6407 * GID_PROBE_COMPLETE or IBDM_GID_PROBING_SKIPPED.This
6418 6408 * basically checks if the DM capable GID is reachable. If
6419 6409 * not this is handled the same way as GID_UNAVAILABLE,
6420 6410 * except that notifications are not send to IBnexus.
6421 6411 *
6422 6412 * This function also initializes the ioc_prev_list for
6423 6413 * a particular IOC (when called from probe_ioc, with
6424 6414 * ioc_guidp != NULL) or all IOCs for the gid (called from
6425 6415 * sweep_fabric, ioc_guidp == NULL).
6426 6416 */
6427 6417 static void
6428 6418 ibdm_rescan_gidlist(ib_guid_t *ioc_guidp)
6429 6419 {
6430 6420 ibdm_dp_gidinfo_t *gid_info, *tmp;
6431 6421 int ii, niocs, found;
6432 6422 ibdm_hca_list_t *hca_list = NULL;
6433 6423 ibdm_port_attr_t *port = NULL;
6434 6424 ibdm_ioc_info_t *ioc_list;
6435 6425
6436 6426 for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info; ) {
6437 6427 found = 0;
6438 6428 if (gid_info->gl_state != IBDM_GID_PROBING_SKIPPED &&
6439 6429 gid_info->gl_state != IBDM_GID_PROBING_COMPLETE) {
6440 6430 gid_info = gid_info->gl_next;
6441 6431 continue;
6442 6432 }
6443 6433
6444 6434 /*
6445 6435 * Check if the GID is visible to any HCA ports.
6446 6436 * Return if so.
6447 6437 */
6448 6438 mutex_enter(&ibdm.ibdm_hl_mutex);
6449 6439 for (ibdm_get_next_port(&hca_list, &port, 1); port;
6450 6440 ibdm_get_next_port(&hca_list, &port, 1)) {
6451 6441 if (ibdm_port_reachable(port->pa_sa_hdl,
6452 6442 gid_info->gl_dgid_lo) == B_TRUE) {
6453 6443 found = 1;
6454 6444 break;
6455 6445 }
6456 6446 }
6457 6447 mutex_exit(&ibdm.ibdm_hl_mutex);
6458 6448
6459 6449 if (found) {
6460 6450 if (gid_info->gl_iou == NULL) {
6461 6451 gid_info = gid_info->gl_next;
6462 6452 continue;
6463 6453 }
6464 6454
6465 6455 /* Intialize the ioc_prev_gid_list */
6466 6456 niocs =
6467 6457 gid_info->gl_iou->iou_info.iou_num_ctrl_slots;
6468 6458 for (ii = 0; ii < niocs; ii++) {
6469 6459 ioc_list = IBDM_GIDINFO2IOCINFO(gid_info, ii);
6470 6460
6471 6461 if (ioc_guidp == NULL || (*ioc_guidp ==
6472 6462 ioc_list->ioc_profile.ioc_guid)) {
6473 6463 /* Add info of GIDs in gid_info also */
6474 6464 ibdm_addto_gidlist(
6475 6465 &ioc_list->ioc_prev_gid_list,
6476 6466 gid_info->gl_gid);
6477 6467 ioc_list->ioc_prev_nportgids =
6478 6468 gid_info->gl_ngids;
6479 6469 }
6480 6470 }
6481 6471 gid_info = gid_info->gl_next;
6482 6472 continue;
6483 6473 }
6484 6474
6485 6475 IBTF_DPRINTF_L4("ibdm", "\trescan_gidlist "
6486 6476 "deleted port GUID %llx",
6487 6477 gid_info->gl_dgid_lo);
6488 6478
6489 6479 /*
6490 6480 * Update GID list in all IOCs affected by this
6491 6481 */
6492 6482 ioc_list = ibdm_update_ioc_gidlist(gid_info, 0);
6493 6483
6494 6484 /*
6495 6485 * Remove GID from the global GID list
6496 6486 * Handle the case where all port GIDs for an
6497 6487 * IOU have been hot-removed.
6498 6488 */
6499 6489 mutex_enter(&ibdm.ibdm_mutex);
6500 6490 if (gid_info->gl_iou != NULL && gid_info->gl_ngids == 0) {
6501 6491 mutex_enter(&gid_info->gl_mutex);
6502 6492 (void) ibdm_free_iou_info(gid_info, &gid_info->gl_iou);
6503 6493 mutex_exit(&gid_info->gl_mutex);
6504 6494 }
6505 6495
6506 6496 tmp = gid_info->gl_next;
6507 6497 if (gid_info->gl_prev != NULL)
6508 6498 gid_info->gl_prev->gl_next = gid_info->gl_next;
6509 6499 if (gid_info->gl_next != NULL)
6510 6500 gid_info->gl_next->gl_prev = gid_info->gl_prev;
6511 6501
6512 6502 if (gid_info == ibdm.ibdm_dp_gidlist_head)
6513 6503 ibdm.ibdm_dp_gidlist_head = gid_info->gl_next;
6514 6504 if (gid_info == ibdm.ibdm_dp_gidlist_tail)
6515 6505 ibdm.ibdm_dp_gidlist_tail = gid_info->gl_prev;
6516 6506 ibdm.ibdm_ngids--;
6517 6507 mutex_exit(&ibdm.ibdm_mutex);
6518 6508
6519 6509 /* free the hca_list on this gid_info */
6520 6510 ibdm_delete_glhca_list(gid_info);
6521 6511
6522 6512 mutex_destroy(&gid_info->gl_mutex);
6523 6513 kmem_free(gid_info, sizeof (ibdm_dp_gidinfo_t));
6524 6514
6525 6515 gid_info = tmp;
6526 6516
6527 6517 /*
6528 6518 * Pass on the IOCs with updated GIDs to IBnexus
6529 6519 */
6530 6520 if (ioc_list) {
6531 6521 IBTF_DPRINTF_L4("ibdm", "\trescan_gidlist "
6532 6522 "IOC_PROP_UPDATE for %p\n", ioc_list);
6533 6523 mutex_enter(&ibdm.ibdm_ibnex_mutex);
6534 6524 if (ibdm.ibdm_ibnex_callback != NULL) {
6535 6525 (*ibdm.ibdm_ibnex_callback)((void *)
6536 6526 ioc_list, IBDM_EVENT_IOC_PROP_UPDATE);
6537 6527 }
6538 6528 mutex_exit(&ibdm.ibdm_ibnex_mutex);
6539 6529 }
6540 6530 }
6541 6531 }
6542 6532
6543 6533 /*
6544 6534 * This function notifies IBnex of IOCs on this GID.
6545 6535 * Notification is for GIDs with gl_reprobe_flag set.
6546 6536 * The flag is set when IOC probe / fabric sweep
6547 6537 * probes a GID starting from CLASS port info.
6548 6538 *
6549 6539 * IBnexus will have information of a reconnected IOC
6550 6540 * if it had probed it before. If this is a new IOC,
6551 6541 * IBnexus ignores the notification.
6552 6542 *
6553 6543 * This function should be called with no locks held.
6554 6544 */
6555 6545 static void
6556 6546 ibdm_notify_newgid_iocs(ibdm_dp_gidinfo_t *gid_info)
6557 6547 {
6558 6548 ibdm_ioc_info_t *ioc_list;
6559 6549
6560 6550 if (gid_info->gl_reprobe_flag == 0 ||
6561 6551 gid_info->gl_iou == NULL)
6562 6552 return;
6563 6553
6564 6554 ioc_list = ibdm_update_ioc_gidlist(gid_info, -1);
6565 6555
6566 6556 /*
6567 6557 * Pass on the IOCs with updated GIDs to IBnexus
6568 6558 */
6569 6559 if (ioc_list) {
6570 6560 mutex_enter(&ibdm.ibdm_ibnex_mutex);
6571 6561 if (ibdm.ibdm_ibnex_callback != NULL) {
6572 6562 (*ibdm.ibdm_ibnex_callback)((void *)ioc_list,
6573 6563 IBDM_EVENT_IOC_PROP_UPDATE);
6574 6564 }
6575 6565 mutex_exit(&ibdm.ibdm_ibnex_mutex);
6576 6566 }
6577 6567 }
6578 6568
6579 6569
6580 6570 static void
6581 6571 ibdm_free_saa_event_arg(ibdm_saa_event_arg_t *arg)
6582 6572 {
6583 6573 if (arg != NULL)
6584 6574 kmem_free(arg, sizeof (ibdm_saa_event_arg_t));
6585 6575 }
6586 6576
6587 6577 /*
6588 6578 * This function parses the list of HCAs and HCA ports
6589 6579 * to return the port_attr of the next HCA port. A port
6590 6580 * connected to IB fabric (port_state active) is returned,
6591 6581 * if connected_flag is set.
6592 6582 */
6593 6583 static void
6594 6584 ibdm_get_next_port(ibdm_hca_list_t **inp_hcap,
6595 6585 ibdm_port_attr_t **inp_portp, int connect_flag)
6596 6586 {
6597 6587 int ii;
6598 6588 ibdm_port_attr_t *port, *next_port = NULL;
6599 6589 ibdm_port_attr_t *inp_port;
6600 6590 ibdm_hca_list_t *hca_list;
6601 6591 int found = 0;
6602 6592
6603 6593 ASSERT(MUTEX_HELD(&ibdm.ibdm_hl_mutex));
6604 6594 IBTF_DPRINTF_L4(ibdm_string, "\tget_next_port(%p, %p, %x)",
6605 6595 inp_hcap, inp_portp, connect_flag);
6606 6596
6607 6597 hca_list = *inp_hcap;
6608 6598 inp_port = *inp_portp;
6609 6599
6610 6600 if (hca_list == NULL)
6611 6601 hca_list = ibdm.ibdm_hca_list_head;
6612 6602
6613 6603 for (; hca_list; hca_list = hca_list->hl_next) {
6614 6604 for (ii = 0; ii < hca_list->hl_nports; ii++) {
6615 6605 port = &hca_list->hl_port_attr[ii];
6616 6606
6617 6607 /*
6618 6608 * inp_port != NULL;
6619 6609 * Skip till we find the matching port
6620 6610 */
6621 6611 if (inp_port && !found) {
6622 6612 if (inp_port == port)
6623 6613 found = 1;
6624 6614 continue;
6625 6615 }
6626 6616
6627 6617 if (!connect_flag) {
6628 6618 next_port = port;
6629 6619 break;
6630 6620 }
6631 6621
6632 6622 if (port->pa_sa_hdl == NULL)
6633 6623 ibdm_initialize_port(port);
6634 6624 if (port->pa_sa_hdl == NULL)
6635 6625 (void) ibdm_fini_port(port);
6636 6626 else if (next_port == NULL &&
6637 6627 port->pa_sa_hdl != NULL &&
6638 6628 port->pa_state == IBT_PORT_ACTIVE) {
6639 6629 next_port = port;
6640 6630 break;
6641 6631 }
6642 6632 }
6643 6633
6644 6634 if (next_port)
6645 6635 break;
6646 6636 }
6647 6637
6648 6638 IBTF_DPRINTF_L4(ibdm_string, "\tget_next_port : "
6649 6639 "returns hca_list %p port %p", hca_list, next_port);
6650 6640 *inp_hcap = hca_list;
6651 6641 *inp_portp = next_port;
6652 6642 }
6653 6643
6654 6644 static void
6655 6645 ibdm_add_to_gl_gid(ibdm_dp_gidinfo_t *nodegid, ibdm_dp_gidinfo_t *addgid)
6656 6646 {
6657 6647 ibdm_gid_t *tmp;
6658 6648
6659 6649 tmp = kmem_zalloc(sizeof (ibdm_gid_t), KM_SLEEP);
6660 6650 tmp->gid_dgid_hi = addgid->gl_dgid_hi;
6661 6651 tmp->gid_dgid_lo = addgid->gl_dgid_lo;
6662 6652
6663 6653 mutex_enter(&nodegid->gl_mutex);
6664 6654 tmp->gid_next = nodegid->gl_gid;
6665 6655 nodegid->gl_gid = tmp;
6666 6656 nodegid->gl_ngids++;
6667 6657 mutex_exit(&nodegid->gl_mutex);
6668 6658 }
6669 6659
6670 6660 static void
6671 6661 ibdm_addto_glhcalist(ibdm_dp_gidinfo_t *gid_info,
6672 6662 ibdm_hca_list_t *hca)
6673 6663 {
6674 6664 ibdm_hca_list_t *head, *prev = NULL, *temp;
6675 6665
6676 6666 IBTF_DPRINTF_L4(ibdm_string, "\taddto_glhcalist(%p, %p) "
6677 6667 ": gl_hca_list %p", gid_info, hca, gid_info->gl_hca_list);
6678 6668 ASSERT(!MUTEX_HELD(&gid_info->gl_mutex));
6679 6669
6680 6670 mutex_enter(&gid_info->gl_mutex);
6681 6671 head = gid_info->gl_hca_list;
6682 6672 if (head == NULL) {
6683 6673 head = ibdm_dup_hca_attr(hca);
6684 6674 head->hl_next = NULL;
6685 6675 gid_info->gl_hca_list = head;
6686 6676 mutex_exit(&gid_info->gl_mutex);
6687 6677 IBTF_DPRINTF_L4(ibdm_string, "\tadd_to_glhcalist: "
6688 6678 "gid %p, gl_hca_list %p", gid_info,
6689 6679 gid_info->gl_hca_list);
6690 6680 return;
6691 6681 }
6692 6682
6693 6683 /* Check if already in the list */
6694 6684 while (head) {
6695 6685 if (head->hl_hca_guid == hca->hl_hca_guid) {
6696 6686 mutex_exit(&gid_info->gl_mutex);
6697 6687 IBTF_DPRINTF_L4(ibdm_string,
6698 6688 "\taddto_glhcalist : gid %p hca %p dup",
6699 6689 gid_info, hca);
6700 6690 return;
6701 6691 }
6702 6692 prev = head;
6703 6693 head = head->hl_next;
6704 6694 }
6705 6695
6706 6696 /* Add this HCA to gl_hca_list */
6707 6697 temp = ibdm_dup_hca_attr(hca);
6708 6698 temp->hl_next = NULL;
6709 6699 prev->hl_next = temp;
6710 6700 mutex_exit(&gid_info->gl_mutex);
6711 6701
6712 6702 IBTF_DPRINTF_L4(ibdm_string, "\tadd_to_glhcalist: "
6713 6703 "gid %p, gl_hca_list %p", gid_info, gid_info->gl_hca_list);
6714 6704 }
6715 6705
6716 6706 static void
6717 6707 ibdm_delete_glhca_list(ibdm_dp_gidinfo_t *gid_info)
6718 6708 {
6719 6709 ASSERT(!MUTEX_HELD(&gid_info->gl_mutex));
6720 6710 ASSERT(!MUTEX_HELD(&ibdm.ibdm_mutex));
6721 6711
6722 6712 mutex_enter(&gid_info->gl_mutex);
6723 6713 if (gid_info->gl_hca_list)
6724 6714 ibdm_ibnex_free_hca_list(gid_info->gl_hca_list);
6725 6715 gid_info->gl_hca_list = NULL;
6726 6716 mutex_exit(&gid_info->gl_mutex);
6727 6717 }
6728 6718
6729 6719
6730 6720 static void
6731 6721 ibdm_reset_all_dgids(ibmf_saa_handle_t port_sa_hdl)
6732 6722 {
6733 6723 IBTF_DPRINTF_L4(ibdm_string, "\treset_all_dgids(%X)",
6734 6724 port_sa_hdl);
6735 6725
6736 6726 if (ibdm_enumerate_iocs == 0)
6737 6727 return;
6738 6728
6739 6729 ASSERT(!MUTEX_HELD(&ibdm.ibdm_mutex));
6740 6730 ASSERT(!MUTEX_HELD(&ibdm.ibdm_hl_mutex));
6741 6731
6742 6732 /* Check : Not busy in another probe / sweep */
6743 6733 mutex_enter(&ibdm.ibdm_mutex);
6744 6734 if ((ibdm.ibdm_busy & IBDM_BUSY) == 0) {
6745 6735 ibdm_dp_gidinfo_t *gid_info;
6746 6736
6747 6737 ibdm.ibdm_busy |= IBDM_BUSY;
6748 6738 mutex_exit(&ibdm.ibdm_mutex);
6749 6739
6750 6740 /*
6751 6741 * Check if any GID is using the SA & IBMF handle
6752 6742 * of HCA port going down. Reset ibdm_dp_gidinfo_t
6753 6743 * using another HCA port which can reach the GID.
6754 6744 * This is for DM capable GIDs only, no need to do
6755 6745 * this for others
6756 6746 *
6757 6747 * Delete the GID if no alternate HCA port to reach
6758 6748 * it is found.
6759 6749 */
6760 6750 for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info; ) {
6761 6751 ibdm_dp_gidinfo_t *tmp;
6762 6752
6763 6753 IBTF_DPRINTF_L4(ibdm_string, "\tevent_hdlr "
6764 6754 "checking gidinfo %p", gid_info);
6765 6755
6766 6756 if (gid_info->gl_sa_hdl == port_sa_hdl) {
6767 6757 IBTF_DPRINTF_L3(ibdm_string,
6768 6758 "\tevent_hdlr: down HCA port hdl "
6769 6759 "matches gid %p", gid_info);
6770 6760
6771 6761 /*
6772 6762 * The non-DM GIDs can come back
6773 6763 * with a new subnet prefix, when
6774 6764 * the HCA port commes up again. To
6775 6765 * avoid issues, delete non-DM
6776 6766 * capable GIDs, if the gid was
6777 6767 * discovered using the HCA port
6778 6768 * going down. This is ensured by
6779 6769 * setting gl_disconnected to 1.
6780 6770 */
6781 6771 if (gid_info->gl_is_dm_capable == B_FALSE)
6782 6772 gid_info->gl_disconnected = 1;
6783 6773 else
6784 6774 ibdm_reset_gidinfo(gid_info);
6785 6775
6786 6776 if (gid_info->gl_disconnected) {
6787 6777 IBTF_DPRINTF_L3(ibdm_string,
6788 6778 "\tevent_hdlr: deleting"
6789 6779 " gid %p", gid_info);
6790 6780 tmp = gid_info;
6791 6781 gid_info = gid_info->gl_next;
6792 6782 ibdm_delete_gidinfo(tmp);
6793 6783 } else
6794 6784 gid_info = gid_info->gl_next;
6795 6785 } else
6796 6786 gid_info = gid_info->gl_next;
6797 6787 }
6798 6788
6799 6789 mutex_enter(&ibdm.ibdm_mutex);
6800 6790 ibdm.ibdm_busy &= ~IBDM_BUSY;
6801 6791 cv_signal(&ibdm.ibdm_busy_cv);
6802 6792 }
6803 6793 mutex_exit(&ibdm.ibdm_mutex);
6804 6794 }
6805 6795
6806 6796 static void
6807 6797 ibdm_reset_gidinfo(ibdm_dp_gidinfo_t *gidinfo)
6808 6798 {
6809 6799 ibdm_hca_list_t *hca_list = NULL;
6810 6800 ibdm_port_attr_t *port = NULL;
6811 6801 int gid_reinited = 0;
6812 6802 sa_node_record_t *nr, *tmp;
6813 6803 sa_portinfo_record_t *pi;
6814 6804 size_t nr_len = 0, pi_len = 0;
6815 6805 size_t path_len;
6816 6806 ib_gid_t sgid, dgid;
6817 6807 int ret, ii, nrecords;
6818 6808 sa_path_record_t *path;
6819 6809 uint8_t npaths = 1;
6820 6810 ibdm_pkey_tbl_t *pkey_tbl;
6821 6811
6822 6812 IBTF_DPRINTF_L4(ibdm_string, "\treset_gidinfo(%p)", gidinfo);
6823 6813
6824 6814 /*
6825 6815 * Get list of all the ports reachable from the local known HCA
6826 6816 * ports which are active
6827 6817 */
6828 6818 mutex_enter(&ibdm.ibdm_hl_mutex);
6829 6819 for (ibdm_get_next_port(&hca_list, &port, 1); port;
6830 6820 ibdm_get_next_port(&hca_list, &port, 1)) {
6831 6821
6832 6822
6833 6823 /*
6834 6824 * Get the path and re-populate the gidinfo.
6835 6825 * Getting the path is the same probe_ioc
6836 6826 * Init the gid info as in ibdm_create_gidinfo()
6837 6827 */
6838 6828 nr = ibdm_get_node_records(port->pa_sa_hdl, &nr_len,
6839 6829 gidinfo->gl_nodeguid);
6840 6830 if (nr == NULL) {
6841 6831 IBTF_DPRINTF_L4(ibdm_string,
6842 6832 "\treset_gidinfo : no records");
6843 6833 continue;
6844 6834 }
6845 6835
6846 6836 nrecords = (nr_len / sizeof (sa_node_record_t));
6847 6837 for (tmp = nr, ii = 0; (ii < nrecords); ii++, tmp++) {
6848 6838 if (tmp->NodeInfo.PortGUID == gidinfo->gl_portguid)
6849 6839 break;
6850 6840 }
6851 6841
6852 6842 if (ii == nrecords) {
6853 6843 IBTF_DPRINTF_L4(ibdm_string,
6854 6844 "\treset_gidinfo : no record for portguid");
6855 6845 kmem_free(nr, nr_len);
6856 6846 continue;
6857 6847 }
6858 6848
6859 6849 pi = ibdm_get_portinfo(port->pa_sa_hdl, &pi_len, tmp->LID);
6860 6850 if (pi == NULL) {
6861 6851 IBTF_DPRINTF_L4(ibdm_string,
6862 6852 "\treset_gidinfo : no portinfo");
6863 6853 kmem_free(nr, nr_len);
6864 6854 continue;
6865 6855 }
6866 6856
6867 6857 sgid.gid_prefix = port->pa_sn_prefix;
6868 6858 sgid.gid_guid = port->pa_port_guid;
6869 6859 dgid.gid_prefix = pi->PortInfo.GidPrefix;
6870 6860 dgid.gid_guid = tmp->NodeInfo.PortGUID;
6871 6861
6872 6862 ret = ibmf_saa_gid_to_pathrecords(port->pa_sa_hdl, sgid, dgid,
6873 6863 IBMF_SAA_PKEY_WC, 0, B_TRUE, &npaths, 0, &path_len, &path);
6874 6864
6875 6865 if ((ret != IBMF_SUCCESS) || path == NULL) {
6876 6866 IBTF_DPRINTF_L4(ibdm_string,
6877 6867 "\treset_gidinfo : no paths");
6878 6868 kmem_free(pi, pi_len);
6879 6869 kmem_free(nr, nr_len);
6880 6870 continue;
6881 6871 }
6882 6872
6883 6873 gidinfo->gl_dgid_hi = path->DGID.gid_prefix;
6884 6874 gidinfo->gl_dgid_lo = path->DGID.gid_guid;
6885 6875 gidinfo->gl_sgid_hi = path->SGID.gid_prefix;
6886 6876 gidinfo->gl_sgid_lo = path->SGID.gid_guid;
6887 6877 gidinfo->gl_p_key = path->P_Key;
6888 6878 gidinfo->gl_sa_hdl = port->pa_sa_hdl;
6889 6879 gidinfo->gl_ibmf_hdl = port->pa_ibmf_hdl;
6890 6880 gidinfo->gl_slid = path->SLID;
6891 6881 gidinfo->gl_dlid = path->DLID;
6892 6882 /* Reset redirect info, next MAD will set if redirected */
6893 6883 gidinfo->gl_redirected = 0;
6894 6884 gidinfo->gl_devid = (*tmp).NodeInfo.DeviceID;
6895 6885 gidinfo->gl_SL = path->SL;
6896 6886
6897 6887 gidinfo->gl_qp_hdl = IBMF_QP_HANDLE_DEFAULT;
6898 6888 for (ii = 0; ii < port->pa_npkeys; ii++) {
6899 6889 if (port->pa_pkey_tbl == NULL)
6900 6890 break;
6901 6891
6902 6892 pkey_tbl = &port->pa_pkey_tbl[ii];
6903 6893 if ((gidinfo->gl_p_key == pkey_tbl->pt_pkey) &&
6904 6894 (pkey_tbl->pt_qp_hdl != NULL)) {
6905 6895 gidinfo->gl_qp_hdl = pkey_tbl->pt_qp_hdl;
6906 6896 break;
6907 6897 }
6908 6898 }
6909 6899
6910 6900 if (gidinfo->gl_qp_hdl == NULL)
6911 6901 IBTF_DPRINTF_L2(ibdm_string,
6912 6902 "\treset_gid_info: No matching Pkey");
6913 6903 else
6914 6904 gid_reinited = 1;
6915 6905
6916 6906 kmem_free(path, path_len);
6917 6907 kmem_free(pi, pi_len);
6918 6908 kmem_free(nr, nr_len);
6919 6909 break;
6920 6910 }
6921 6911 mutex_exit(&ibdm.ibdm_hl_mutex);
6922 6912
6923 6913 if (!gid_reinited)
6924 6914 gidinfo->gl_disconnected = 1;
6925 6915 }
6926 6916
6927 6917 static void
6928 6918 ibdm_delete_gidinfo(ibdm_dp_gidinfo_t *gidinfo)
6929 6919 {
6930 6920 ibdm_ioc_info_t *ioc_list;
6931 6921 int in_gidlist = 0;
6932 6922
6933 6923 /*
6934 6924 * Check if gidinfo has been inserted into the
6935 6925 * ibdm_dp_gidlist_head list. gl_next or gl_prev
6936 6926 * != NULL, if gidinfo is the list.
6937 6927 */
6938 6928 if (gidinfo->gl_prev != NULL ||
6939 6929 gidinfo->gl_next != NULL ||
6940 6930 ibdm.ibdm_dp_gidlist_head == gidinfo)
6941 6931 in_gidlist = 1;
6942 6932
6943 6933 ioc_list = ibdm_update_ioc_gidlist(gidinfo, 0);
6944 6934
6945 6935 /*
6946 6936 * Remove GID from the global GID list
6947 6937 * Handle the case where all port GIDs for an
6948 6938 * IOU have been hot-removed.
6949 6939 */
6950 6940 mutex_enter(&ibdm.ibdm_mutex);
6951 6941 if (gidinfo->gl_iou != NULL && gidinfo->gl_ngids == 0) {
6952 6942 mutex_enter(&gidinfo->gl_mutex);
6953 6943 (void) ibdm_free_iou_info(gidinfo, &gidinfo->gl_iou);
6954 6944 mutex_exit(&gidinfo->gl_mutex);
6955 6945 }
6956 6946
6957 6947 /* Delete gl_hca_list */
6958 6948 mutex_exit(&ibdm.ibdm_mutex);
6959 6949 ibdm_delete_glhca_list(gidinfo);
6960 6950 mutex_enter(&ibdm.ibdm_mutex);
6961 6951
6962 6952 if (in_gidlist) {
6963 6953 if (gidinfo->gl_prev != NULL)
6964 6954 gidinfo->gl_prev->gl_next = gidinfo->gl_next;
6965 6955 if (gidinfo->gl_next != NULL)
6966 6956 gidinfo->gl_next->gl_prev = gidinfo->gl_prev;
6967 6957
6968 6958 if (gidinfo == ibdm.ibdm_dp_gidlist_head)
6969 6959 ibdm.ibdm_dp_gidlist_head = gidinfo->gl_next;
6970 6960 if (gidinfo == ibdm.ibdm_dp_gidlist_tail)
6971 6961 ibdm.ibdm_dp_gidlist_tail = gidinfo->gl_prev;
6972 6962 ibdm.ibdm_ngids--;
6973 6963 }
6974 6964 mutex_exit(&ibdm.ibdm_mutex);
6975 6965
6976 6966 mutex_destroy(&gidinfo->gl_mutex);
6977 6967 cv_destroy(&gidinfo->gl_probe_cv);
6978 6968 kmem_free(gidinfo, sizeof (ibdm_dp_gidinfo_t));
6979 6969
6980 6970 /*
6981 6971 * Pass on the IOCs with updated GIDs to IBnexus
6982 6972 */
6983 6973 if (ioc_list) {
6984 6974 IBTF_DPRINTF_L4("ibdm", "\tdelete_gidinfo "
6985 6975 "IOC_PROP_UPDATE for %p\n", ioc_list);
6986 6976 mutex_enter(&ibdm.ibdm_ibnex_mutex);
6987 6977 if (ibdm.ibdm_ibnex_callback != NULL) {
6988 6978 (*ibdm.ibdm_ibnex_callback)((void *)
6989 6979 ioc_list, IBDM_EVENT_IOC_PROP_UPDATE);
6990 6980 }
6991 6981 mutex_exit(&ibdm.ibdm_ibnex_mutex);
6992 6982 }
6993 6983 }
6994 6984
6995 6985
6996 6986 static void
6997 6987 ibdm_fill_srv_attr_mod(ib_mad_hdr_t *hdr, ibdm_timeout_cb_args_t *cb_args)
6998 6988 {
6999 6989 uint32_t attr_mod;
7000 6990
7001 6991 attr_mod = (cb_args->cb_ioc_num + 1) << 16;
7002 6992 attr_mod |= cb_args->cb_srvents_start;
7003 6993 attr_mod |= (cb_args->cb_srvents_end) << 8;
7004 6994 hdr->AttributeModifier = h2b32(attr_mod);
7005 6995 }
7006 6996
7007 6997 static void
7008 6998 ibdm_bump_transactionID(ibdm_dp_gidinfo_t *gid_info)
7009 6999 {
7010 7000 ASSERT(MUTEX_HELD(&gid_info->gl_mutex));
7011 7001 gid_info->gl_transactionID++;
7012 7002 if (gid_info->gl_transactionID == gid_info->gl_max_transactionID) {
7013 7003 IBTF_DPRINTF_L4(ibdm_string,
7014 7004 "\tbump_transactionID(%p), wrapup", gid_info);
7015 7005 gid_info->gl_transactionID = gid_info->gl_min_transactionID;
7016 7006 }
7017 7007 }
7018 7008
7019 7009 /*
7020 7010 * gl_prev_iou is set for *non-reprobe* sweeep requests, which
7021 7011 * detected that ChangeID in IOU info has changed. The service
7022 7012 * entry also may have changed. Check if service entry in IOC
7023 7013 * has changed wrt the prev iou, if so notify to IB Nexus.
7024 7014 */
7025 7015 static ibdm_ioc_info_t *
7026 7016 ibdm_handle_prev_iou()
7027 7017 {
7028 7018 ibdm_dp_gidinfo_t *gid_info;
7029 7019 ibdm_ioc_info_t *ioc_list_head = NULL, *ioc_list;
7030 7020 ibdm_ioc_info_t *prev_ioc, *ioc;
7031 7021 int ii, jj, niocs, prev_niocs;
7032 7022
7033 7023 ASSERT(MUTEX_HELD(&ibdm.ibdm_mutex));
7034 7024
7035 7025 IBTF_DPRINTF_L4(ibdm_string, "\thandle_prev_iou enter");
7036 7026 for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info;
7037 7027 gid_info = gid_info->gl_next) {
7038 7028 if (gid_info->gl_prev_iou == NULL)
7039 7029 continue;
7040 7030
7041 7031 IBTF_DPRINTF_L4(ibdm_string, "\thandle_prev_iou gid %p",
7042 7032 gid_info);
7043 7033 niocs = gid_info->gl_iou->iou_info.iou_num_ctrl_slots;
7044 7034 prev_niocs =
7045 7035 gid_info->gl_prev_iou->iou_info.iou_num_ctrl_slots;
7046 7036 for (ii = 0; ii < niocs; ii++) {
7047 7037 ioc = IBDM_GIDINFO2IOCINFO(gid_info, ii);
7048 7038
7049 7039 /* Find matching IOC */
7050 7040 for (jj = 0; jj < prev_niocs; jj++) {
7051 7041 prev_ioc = (ibdm_ioc_info_t *)
7052 7042 &gid_info->gl_prev_iou->iou_ioc_info[jj];
7053 7043 if (prev_ioc->ioc_profile.ioc_guid ==
7054 7044 ioc->ioc_profile.ioc_guid)
7055 7045 break;
7056 7046 }
7057 7047 if (jj == prev_niocs)
7058 7048 prev_ioc = NULL;
7059 7049 if (ioc == NULL || prev_ioc == NULL)
7060 7050 continue;
7061 7051 if ((ioc->ioc_profile.ioc_service_entries !=
7062 7052 prev_ioc->ioc_profile.ioc_service_entries) ||
7063 7053 ibdm_serv_cmp(&ioc->ioc_serv[0],
7064 7054 &prev_ioc->ioc_serv[0],
7065 7055 ioc->ioc_profile.ioc_service_entries) != 0) {
7066 7056 IBTF_DPRINTF_L4(ibdm_string,
7067 7057 "/thandle_prev_iou modified IOC: "
7068 7058 "current ioc %p, old ioc %p",
7069 7059 ioc, prev_ioc);
7070 7060 mutex_enter(&gid_info->gl_mutex);
7071 7061 ioc_list = ibdm_dup_ioc_info(ioc, gid_info);
7072 7062 mutex_exit(&gid_info->gl_mutex);
7073 7063 ioc_list->ioc_info_updated.ib_prop_updated
7074 7064 = 0;
7075 7065 ioc_list->ioc_info_updated.ib_srv_prop_updated
7076 7066 = 1;
7077 7067
7078 7068 if (ioc_list_head == NULL)
7079 7069 ioc_list_head = ioc_list;
7080 7070 else {
7081 7071 ioc_list_head->ioc_next = ioc_list;
7082 7072 ioc_list_head = ioc_list;
7083 7073 }
7084 7074 }
7085 7075 }
7086 7076
7087 7077 mutex_enter(&gid_info->gl_mutex);
7088 7078 (void) ibdm_free_iou_info(gid_info, &gid_info->gl_prev_iou);
7089 7079 mutex_exit(&gid_info->gl_mutex);
7090 7080 }
7091 7081 IBTF_DPRINTF_L4(ibdm_string, "\thandle_prev_iouret %p",
7092 7082 ioc_list_head);
7093 7083 return (ioc_list_head);
7094 7084 }
7095 7085
7096 7086 /*
7097 7087 * Compares two service entries lists, returns 0 if same, returns 1
7098 7088 * if no match.
7099 7089 */
7100 7090 static int
7101 7091 ibdm_serv_cmp(ibdm_srvents_info_t *serv1, ibdm_srvents_info_t *serv2,
7102 7092 int nserv)
7103 7093 {
7104 7094 int ii;
7105 7095
7106 7096 IBTF_DPRINTF_L4(ibdm_string, "\tserv_cmp: enter");
7107 7097 for (ii = 0; ii < nserv; ii++, serv1++, serv2++) {
7108 7098 if (serv1->se_attr.srv_id != serv2->se_attr.srv_id ||
7109 7099 bcmp(serv1->se_attr.srv_name,
7110 7100 serv2->se_attr.srv_name,
7111 7101 IB_DM_MAX_SVC_NAME_LEN) != 0) {
7112 7102 IBTF_DPRINTF_L4(ibdm_string, "\tserv_cmp: ret 1");
7113 7103 return (1);
7114 7104 }
7115 7105 }
7116 7106 IBTF_DPRINTF_L4(ibdm_string, "\tserv_cmp: ret 0");
7117 7107 return (0);
7118 7108 }
7119 7109
7120 7110 /* For debugging purpose only */
7121 7111 #ifdef DEBUG
7122 7112 void
7123 7113 ibdm_dump_mad_hdr(ib_mad_hdr_t *mad_hdr)
7124 7114 {
7125 7115 IBTF_DPRINTF_L4("ibdm", "\t\t MAD Header info");
7126 7116 IBTF_DPRINTF_L4("ibdm", "\t\t ---------------");
7127 7117
7128 7118 IBTF_DPRINTF_L4("ibdm", "\tBase version : 0x%x"
7129 7119 "\tMgmt Class : 0x%x", mad_hdr->BaseVersion, mad_hdr->MgmtClass);
7130 7120 IBTF_DPRINTF_L4("ibdm", "\tClass version : 0x%x"
7131 7121 "\tR Method : 0x%x",
7132 7122 mad_hdr->ClassVersion, mad_hdr->R_Method);
7133 7123 IBTF_DPRINTF_L4("ibdm", "\tMAD Status : 0x%x"
7134 7124 "\tTransaction ID : 0x%llx",
7135 7125 b2h16(mad_hdr->Status), b2h64(mad_hdr->TransactionID));
7136 7126 IBTF_DPRINTF_L4("ibdm", "\t Attribute ID : 0x%x"
7137 7127 "\tAttribute Modified : 0x%lx",
7138 7128 b2h16(mad_hdr->AttributeID), b2h32(mad_hdr->AttributeModifier));
7139 7129 }
7140 7130
7141 7131
7142 7132 void
7143 7133 ibdm_dump_ibmf_msg(ibmf_msg_t *ibmf_msg, int flag)
7144 7134 {
7145 7135 ib_mad_hdr_t *mad_hdr;
7146 7136
7147 7137 IBTF_DPRINTF_L4("ibdm", "\t\t(IBMF_PKT): Local address info");
7148 7138 IBTF_DPRINTF_L4("ibdm", "\t\t ------------------");
7149 7139
7150 7140 IBTF_DPRINTF_L4("ibdm", "\tLocal Lid : 0x%x\tRemote Lid : 0x%x"
7151 7141 " Remote Qp : 0x%x", ibmf_msg->im_local_addr.ia_local_lid,
7152 7142 ibmf_msg->im_local_addr.ia_remote_lid,
7153 7143 ibmf_msg->im_local_addr.ia_remote_qno);
7154 7144 IBTF_DPRINTF_L4("ibdm", "\tP_key : 0x%x\tQ_key : 0x%x"
7155 7145 " SL : 0x%x", ibmf_msg->im_local_addr.ia_p_key,
7156 7146 ibmf_msg->im_local_addr.ia_q_key,
7157 7147 ibmf_msg->im_local_addr.ia_service_level);
7158 7148
7159 7149 if (flag)
7160 7150 mad_hdr = (ib_mad_hdr_t *)IBDM_OUT_IBMFMSG_MADHDR(ibmf_msg);
7161 7151 else
7162 7152 mad_hdr = IBDM_IN_IBMFMSG_MADHDR(ibmf_msg);
7163 7153
7164 7154 ibdm_dump_mad_hdr(mad_hdr);
7165 7155 }
7166 7156
7167 7157
7168 7158 void
7169 7159 ibdm_dump_path_info(sa_path_record_t *path)
7170 7160 {
7171 7161 IBTF_DPRINTF_L4("ibdm", "\t\t Path information");
7172 7162 IBTF_DPRINTF_L4("ibdm", "\t\t ----------------");
7173 7163
7174 7164 IBTF_DPRINTF_L4("ibdm", "\t DGID hi : %llx\tDGID lo : %llx",
7175 7165 path->DGID.gid_prefix, path->DGID.gid_guid);
7176 7166 IBTF_DPRINTF_L4("ibdm", "\t SGID hi : %llx\tSGID lo : %llx",
7177 7167 path->SGID.gid_prefix, path->SGID.gid_guid);
7178 7168 IBTF_DPRINTF_L4("ibdm", "\t SLID : %x\t\tDlID : %x",
7179 7169 path->SLID, path->DLID);
7180 7170 IBTF_DPRINTF_L4("ibdm", "\t P Key : %x\t\tSL : %x",
7181 7171 path->P_Key, path->SL);
7182 7172 }
7183 7173
7184 7174
7185 7175 void
7186 7176 ibdm_dump_classportinfo(ib_mad_classportinfo_t *classportinfo)
7187 7177 {
7188 7178 IBTF_DPRINTF_L4("ibdm", "\t\t CLASSPORT INFO");
7189 7179 IBTF_DPRINTF_L4("ibdm", "\t\t --------------");
7190 7180
7191 7181 IBTF_DPRINTF_L4("ibdm", "\t Response Time Value : 0x%x",
7192 7182 ((b2h32(classportinfo->RespTimeValue)) & 0x1F));
7193 7183
7194 7184 IBTF_DPRINTF_L4("ibdm", "\t Redirected GID hi : 0x%llx",
7195 7185 b2h64(classportinfo->RedirectGID_hi));
7196 7186 IBTF_DPRINTF_L4("ibdm", "\t Redirected GID lo : 0x%llx",
7197 7187 b2h64(classportinfo->RedirectGID_lo));
7198 7188 IBTF_DPRINTF_L4("ibdm", "\t Redirected TC : 0x%x",
7199 7189 classportinfo->RedirectTC);
7200 7190 IBTF_DPRINTF_L4("ibdm", "\t Redirected SL : 0x%x",
7201 7191 classportinfo->RedirectSL);
7202 7192 IBTF_DPRINTF_L4("ibdm", "\t Redirected FL : 0x%x",
7203 7193 classportinfo->RedirectFL);
7204 7194 IBTF_DPRINTF_L4("ibdm", "\t Redirected LID : 0x%x",
7205 7195 b2h16(classportinfo->RedirectLID));
7206 7196 IBTF_DPRINTF_L4("ibdm", "\t Redirected P KEY : 0x%x",
7207 7197 b2h16(classportinfo->RedirectP_Key));
7208 7198 IBTF_DPRINTF_L4("ibdm", "\t Redirected QP : 0x%x",
7209 7199 classportinfo->RedirectQP);
7210 7200 IBTF_DPRINTF_L4("ibdm", "\t Redirected Q KEY : 0x%x",
7211 7201 b2h32(classportinfo->RedirectQ_Key));
7212 7202 IBTF_DPRINTF_L4("ibdm", "\t Trap GID hi : 0x%llx",
7213 7203 b2h64(classportinfo->TrapGID_hi));
7214 7204 IBTF_DPRINTF_L4("ibdm", "\t Trap GID lo : 0x%llx",
7215 7205 b2h64(classportinfo->TrapGID_lo));
7216 7206 IBTF_DPRINTF_L4("ibdm", "\t Trap TC : 0x%x",
7217 7207 classportinfo->TrapTC);
7218 7208 IBTF_DPRINTF_L4("ibdm", "\t Trap SL : 0x%x",
7219 7209 classportinfo->TrapSL);
7220 7210 IBTF_DPRINTF_L4("ibdm", "\t Trap FL : 0x%x",
7221 7211 classportinfo->TrapFL);
7222 7212 IBTF_DPRINTF_L4("ibdm", "\t Trap LID : 0x%x",
7223 7213 b2h16(classportinfo->TrapLID));
7224 7214 IBTF_DPRINTF_L4("ibdm", "\t Trap P_Key : 0x%x",
7225 7215 b2h16(classportinfo->TrapP_Key));
7226 7216 IBTF_DPRINTF_L4("ibdm", "\t Trap HL : 0x%x",
7227 7217 classportinfo->TrapHL);
7228 7218 IBTF_DPRINTF_L4("ibdm", "\t Trap QP : 0x%x",
7229 7219 classportinfo->TrapQP);
7230 7220 IBTF_DPRINTF_L4("ibdm", "\t Trap Q_Key : 0x%x",
7231 7221 b2h32(classportinfo->TrapQ_Key));
7232 7222 }
7233 7223
7234 7224
7235 7225 void
7236 7226 ibdm_dump_iounitinfo(ib_dm_io_unitinfo_t *iou_info)
7237 7227 {
7238 7228 IBTF_DPRINTF_L4("ibdm", "\t\t I/O UnitInfo");
7239 7229 IBTF_DPRINTF_L4("ibdm", "\t\t ------------");
7240 7230
7241 7231 IBTF_DPRINTF_L4("ibdm", "\tChange ID : 0x%x",
7242 7232 b2h16(iou_info->iou_changeid));
7243 7233 IBTF_DPRINTF_L4("ibdm", "\t#of ctrl slots : %d",
7244 7234 iou_info->iou_num_ctrl_slots);
7245 7235 IBTF_DPRINTF_L4("ibdm", "\tIOU flag : 0x%x",
7246 7236 iou_info->iou_flag);
7247 7237 IBTF_DPRINTF_L4("ibdm", "\tContrl list byte 0 : 0x%x",
7248 7238 iou_info->iou_ctrl_list[0]);
7249 7239 IBTF_DPRINTF_L4("ibdm", "\tContrl list byte 1 : 0x%x",
7250 7240 iou_info->iou_ctrl_list[1]);
7251 7241 IBTF_DPRINTF_L4("ibdm", "\tContrl list byte 2 : 0x%x",
7252 7242 iou_info->iou_ctrl_list[2]);
7253 7243 }
7254 7244
7255 7245
7256 7246 void
7257 7247 ibdm_dump_ioc_profile(ib_dm_ioc_ctrl_profile_t *ioc)
7258 7248 {
7259 7249 IBTF_DPRINTF_L4("ibdm", "\t\t IOC Controller Profile");
7260 7250 IBTF_DPRINTF_L4("ibdm", "\t\t ----------------------");
7261 7251
7262 7252 IBTF_DPRINTF_L4("ibdm", "\tIOC Guid : %llx", ioc->ioc_guid);
7263 7253 IBTF_DPRINTF_L4("ibdm", "\tVendorID : 0x%x", ioc->ioc_vendorid);
7264 7254 IBTF_DPRINTF_L4("ibdm", "\tDevice Id : 0x%x", ioc->ioc_deviceid);
7265 7255 IBTF_DPRINTF_L4("ibdm", "\tDevice Ver : 0x%x", ioc->ioc_device_ver);
7266 7256 IBTF_DPRINTF_L4("ibdm", "\tSubsys ID : 0x%x", ioc->ioc_subsys_id);
7267 7257 IBTF_DPRINTF_L4("ibdm", "\tIO class : 0x%x", ioc->ioc_io_class);
7268 7258 IBTF_DPRINTF_L4("ibdm", "\tIO subclass : 0x%x", ioc->ioc_io_subclass);
7269 7259 IBTF_DPRINTF_L4("ibdm", "\tProtocol : 0x%x", ioc->ioc_protocol);
7270 7260 IBTF_DPRINTF_L4("ibdm", "\tProtocolV : 0x%x", ioc->ioc_protocol_ver);
7271 7261 IBTF_DPRINTF_L4("ibdm", "\tmsg qdepth : %d", ioc->ioc_send_msg_qdepth);
7272 7262 IBTF_DPRINTF_L4("ibdm", "\trdma qdepth : %d",
7273 7263 ioc->ioc_rdma_read_qdepth);
7274 7264 IBTF_DPRINTF_L4("ibdm", "\tsndmsg sz : %d", ioc->ioc_send_msg_sz);
7275 7265 IBTF_DPRINTF_L4("ibdm", "\trdma xfersz : %d", ioc->ioc_rdma_xfer_sz);
7276 7266 IBTF_DPRINTF_L4("ibdm", "\topcal mask : 0x%x",
7277 7267 ioc->ioc_ctrl_opcap_mask);
7278 7268 IBTF_DPRINTF_L4("ibdm", "\tsrventries : %x", ioc->ioc_service_entries);
7279 7269 }
7280 7270
7281 7271
7282 7272 void
7283 7273 ibdm_dump_service_entries(ib_dm_srv_t *srv_ents)
7284 7274 {
7285 7275 IBTF_DPRINTF_L4("ibdm",
7286 7276 "\thandle_srventry_mad: service id : %llx", srv_ents->srv_id);
7287 7277
7288 7278 IBTF_DPRINTF_L4("ibdm", "\thandle_srventry_mad: "
7289 7279 "Service Name : %s", srv_ents->srv_name);
7290 7280 }
7291 7281
7292 7282 int ibdm_allow_sweep_fabric_timestamp = 1;
7293 7283
7294 7284 void
7295 7285 ibdm_dump_sweep_fabric_timestamp(int flag)
7296 7286 {
7297 7287 static hrtime_t x;
7298 7288 if (flag) {
7299 7289 if (ibdm_allow_sweep_fabric_timestamp) {
7300 7290 IBTF_DPRINTF_L4("ibdm", "\tTime taken to complete "
7301 7291 "sweep %lld ms", ((gethrtime() - x)/ 1000000));
7302 7292 }
7303 7293 x = 0;
7304 7294 } else
7305 7295 x = gethrtime();
7306 7296 }
7307 7297 #endif
↓ open down ↓ |
2540 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX