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