1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /*
26 * ibtl_impl.c
27 *
28 * This file contains the IBTF module's initialization and
29 * IBTF Clients/Modules registration routines.
30 */
31
32 #include <sys/modctl.h>
33 #include <sys/sunndi.h>
34 #include <sys/ib/ibtl/impl/ibtl.h>
35 #include <sys/ib/ibtl/impl/ibtl_ibnex.h>
36
37 /*
38 * Globals.
39 */
40 static char ibtf[] = "ibtl_impl";
41
42 extern ibtl_ibnex_callback_t ibtl_ibnex_callback_routine;
43
44 /*
45 * ibtl_clnt_list:
46 *
47 * Head of the list of IBT Client Instances. The IBT Client List
48 * is modified by IBTF on an IBT client's ibt_attach/ibt_detach call.
49 *
50 * ibtl_hca_list:
51 *
52 * Head of the list of HCA devices. The HCA List is modified by IBTF on
53 * a CI's ibc_attach/ibc_detach call.
54 * The datap of the list elements points to an ibtl_hca_devinfo_s
55 * structure.
56 *
57 * (ibc_attach)
58 * ibtl_hca_list -> ibtl_hca_devinfo_t--> ... -->ibtl_hca_devinfo_t
59 * [per-hca_dev] | ^ {nth HCA Dev}
60 * | |
61 * | ibtl_hca_t (ibt_open_hca)
62 * | ^ |
63 * | | |
64 * v | V
65 * ibtl_clnt_list -> ibtl_clnt_t--> ...--> {n'th Module}
66 * [per-client_instance] (ibt_attach)
67 *
68 */
69
70 /* Global List of IBT Client Instances, and associated mutex. */
71 struct ibtl_clnt_s *ibtl_clnt_list = NULL;
72 kmutex_t ibtl_clnt_list_mutex;
73
74 /* Lock for the race between the client and CM to free QPs. */
75 kmutex_t ibtl_free_qp_mutex;
76
77 /* Lock for the race between the client closing the HCA and QPN being freed. */
78 kcondvar_t ibtl_close_hca_cv;
79
80 /* Global List of HCA Devices, and associated mutex. */
81 struct ibtl_hca_devinfo_s *ibtl_hca_list = NULL;
82
83 /* Well-known async handlers and associated client private. */
84 ibt_async_handler_t ibtl_cm_async_handler;
85 ibt_async_handler_t ibtl_dm_async_handler;
86 ibt_async_handler_t ibtl_ibma_async_handler;
87 void *ibtl_cm_clnt_private;
88 void *ibtl_dm_clnt_private;
89 void *ibtl_ibma_clnt_private;
90
91 extern int ib_hw_status;
92
93 /*
94 * Misc Module Declarations.
95 */
96 extern struct mod_ops mod_miscops;
97 static struct modlmisc modlmisc = {
98 &mod_miscops, /* Type of module - misc. */
99 "IB Transport Layer" /* Name of the Module. */
100 };
101
102 static struct modlinkage modlinkage = {
103 MODREV_1, (void *)&modlmisc, NULL
104 };
105
106 static void ibtl_kstat_init(ibtl_hca_devinfo_t *);
107 static void ibtl_kstat_fini(ibtl_hca_devinfo_t *);
108 static void ibtl_kstat_stats_create(ibtl_hca_devinfo_t *, uint_t);
109 static void ibtl_kstat_pkeys_create(ibtl_hca_devinfo_t *, uint_t);
110
111 extern kmutex_t ibtl_part_attr_mutex;
112
113 /*
114 * IBTF Loadable Module Routines.
115 */
116
117 int
118 _init(void)
119 {
120 int rval;
121
122 if ((rval = mod_install(&modlinkage)) != 0)
123 return (rval);
124
125 /*
126 * initialize IBTL ib2usec table
127 */
128 ibtl_ib2usec_init();
129
130 /*
131 * Initialize Logging
132 */
133 ibtl_logging_initialization();
134
135 /*
136 * Initialize the Alloc QP States.
137 */
138 ibtl_init_cep_states();
139
140 /*
141 * Initialize all Global Link Lists.
142 */
143 mutex_init(&ibtl_clnt_list_mutex, NULL, MUTEX_DEFAULT, NULL);
144 mutex_init(&ibtl_free_qp_mutex, NULL, MUTEX_DEFAULT, NULL);
145 cv_init(&ibtl_close_hca_cv, NULL, CV_DEFAULT, NULL);
146
147 mutex_init(&ibtl_qp_mutex, NULL, MUTEX_DEFAULT, NULL);
148 cv_init(&ibtl_qp_cv, NULL, CV_DEFAULT, NULL);
149
150 mutex_init(&ibtl_part_attr_mutex, NULL, MUTEX_DEFAULT, NULL);
151
152 ibtl_thread_init();
153
154 return (rval);
155 }
156
157
158 int
159 _fini(void)
160 {
161 int rval;
162
163 if ((rval = mod_remove(&modlinkage)) != 0) {
164 return (rval);
165 }
166
167 ibtl_thread_fini();
168
169 mutex_destroy(&ibtl_clnt_list_mutex);
170 mutex_destroy(&ibtl_free_qp_mutex);
171 cv_destroy(&ibtl_close_hca_cv);
172 mutex_destroy(&ibtl_qp_mutex);
173 cv_destroy(&ibtl_qp_cv);
174 mutex_destroy(&ibtl_part_attr_mutex);
175
176 /*
177 * Stop Logging
178 */
179 ibtl_logging_destroy();
180
181 return (rval);
182 }
183
184
185 int
186 _info(struct modinfo *modinfop)
187 {
188 /* Return the Module Information. */
189 return (mod_info(&modlinkage, modinfop));
190 }
191
192
193 /*
194 * IBTF Client Registration Routines.
195 */
196
197 /*
198 * Function:
199 * ibt_attach
200 * Input:
201 * modinfop - Client Module info structure.
202 * arg - usually client's dip
203 * clnt_private - client's private data pointer.
204 * Output:
205 * ibt_hdl_p - pointer to client's specific IBT handle,
206 * which is opaque to clients.
207 * Returns:
208 * IBT_SUCCESS
209 * IBT_INVALID_PARAM
210 * Called by:
211 * IBTF Client module during its attach() to register its instance
212 * to IBTF.
213 * Description:
214 * Registers the IBTF client module instance and returns an opaque
215 * handler to the client to be used for future calls to IBTF.
216 * Adds this client module instance to ibtl_clnt_list list.
217 * Records well-known async handlers.
218 */
219 ibt_status_t
220 ibt_attach(ibt_clnt_modinfo_t *mod_infop, dev_info_t *arg, void *clnt_private,
221 ibt_clnt_hdl_t *ibt_hdl_p)
222 {
223 dev_info_t *pdip;
224 ibtl_clnt_t *clntp;
225
226 IBTF_DPRINTF_L3(ibtf, "ibt_attach(%p, %p, %p)",
227 mod_infop, arg, clnt_private);
228
229 if (mod_infop->mi_clnt_name == NULL) {
230 IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
231 "IB client needs to specify its name");
232 return (IBT_INVALID_PARAM);
233 }
234
235 /*
236 * Validate the Transport API version.
237 */
238 if (mod_infop->mi_ibt_version != IBTI_V_CURR) {
239 IBTF_DPRINTF_L1(ibtf, "ibt_attach: IB client '%s' has an "
240 "invalid IB TI Version '%d'", mod_infop->mi_clnt_name,
241 mod_infop->mi_ibt_version);
242 return (IBT_NOT_SUPPORTED);
243 }
244
245 if (mod_infop->mi_async_handler == NULL) {
246 IBTF_DPRINTF_L2(ibtf, "ibt_attach: Client '%s' has not\n"
247 " provided an Asynchronous Event Handler.\n"
248 " This will be required soon.",
249 mod_infop->mi_clnt_name);
250 }
251
252 /*
253 * Check out Client's Class information. If it is not of mgmt class,
254 * we expect 'arg' to be Not NULL and point to client driver's
255 * device info struct.
256 */
257 if ((!IBT_MISCMOD_CLIENTS(mod_infop->mi_clnt_class)) &&
258 (arg == NULL)) {
259 IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
260 "arg not set with driver's dip.");
261 return (IBT_INVALID_PARAM);
262 }
263
264 if (!IBT_MISCMOD_CLIENTS(mod_infop->mi_clnt_class)) {
265 pdip = ddi_get_parent(arg);
266 if (pdip == NULL ||
267 ibtl_ibnex_valid_hca_parent(pdip) != IBT_SUCCESS) {
268 IBTF_DPRINTF_L2(ibtf, "ibt_attach: "
269 "client %s is not a child of IB nexus driver.",
270 ddi_driver_name(arg));
271 return (IBT_INVALID_PARAM);
272 }
273 }
274
275 mutex_enter(&ibtl_clnt_list_mutex);
276 if (mod_infop->mi_clnt_class == IBT_CM) {
277 if (ibtl_cm_async_handler != NULL) {
278 IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
279 "CM is already attached.");
280 mutex_exit(&ibtl_clnt_list_mutex);
281 return (IBT_INVALID_PARAM);
282 }
283 ibtl_cm_async_handler = mod_infop->mi_async_handler;
284 ibtl_cm_clnt_private = clnt_private;
285 } else if (mod_infop->mi_clnt_class == IBT_DM) {
286 if (ibtl_dm_async_handler != NULL) {
287 IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
288 "DM is already attached.");
289 mutex_exit(&ibtl_clnt_list_mutex);
290 return (IBT_INVALID_PARAM);
291 }
292 ibtl_dm_async_handler = mod_infop->mi_async_handler;
293 ibtl_dm_clnt_private = clnt_private;
294 } else if (mod_infop->mi_clnt_class == IBT_IBMA) {
295 if (ibtl_ibma_async_handler != NULL) {
296 IBTF_DPRINTF_L1(ibtf, "ibt_attach: "
297 "IBMF is already attached.");
298 mutex_exit(&ibtl_clnt_list_mutex);
299 return (IBT_INVALID_PARAM);
300 }
301 ibtl_ibma_async_handler = mod_infop->mi_async_handler;
302 ibtl_ibma_clnt_private = clnt_private;
303 }
304
305 /* Allocate the memory for per-client-device info structure */
306 clntp = kmem_zalloc(sizeof (ibtl_clnt_t), KM_SLEEP);
307
308 /* Update the Client info structure */
309 clntp->clnt_modinfop = mod_infop; /* IBT Client's Mod Info */
310 clntp->clnt_private = clnt_private; /* IBT Client's private */
311 clntp->clnt_dip = arg; /* IBT Client's dip */
312 clntp->clnt_async_cnt = 0;
313 /* using a count of 7 below guarantees it is NULL terminated */
314 (void) strncpy(clntp->clnt_name, mod_infop->mi_clnt_name, 7);
315
316 /*
317 * Update Client Device Instance List.
318 */
319 clntp->clnt_list_link = ibtl_clnt_list;
320 ibtl_clnt_list = clntp;
321 mutex_exit(&ibtl_clnt_list_mutex);
322
323 /*
324 * The ibt_hdl_p is a opaque handle which is the address of
325 * ibt_clnt_t structure passed back to the clients.
326 * The client will pass on this handle in its future calls to IBTF.
327 */
328 *ibt_hdl_p = clntp;
329
330 return (IBT_SUCCESS);
331 }
332
333
334 /*
335 * Function:
336 * ibt_detach
337 * Input:
338 * ibt_hdl - IBT Handle as returned during ibt_attach call.
339 * Output:
340 * none
341 * Returns:
342 * IBT_SUCCESS
343 * IBT_INVALID_PARAM.
344 * Called by:
345 * IBTF Client module during its detach() to de-register its instance
346 * from IBTF.
347 * Description:
348 * Deregisters the IBTF client module instance from the IBTF.
349 * All resources and any reference to this ibt_hdl will be removed.
350 */
351 ibt_status_t
352 ibt_detach(ibt_clnt_hdl_t ibt_hdl)
353 {
354 ibtl_clnt_t **clntpp;
355
356 IBTF_DPRINTF_L3(ibtf, "ibt_detach(%p)", ibt_hdl);
357
358 mutex_enter(&ibtl_clnt_list_mutex);
359 clntpp = &ibtl_clnt_list;
360 for (; *clntpp != NULL; clntpp = &(*clntpp)->clnt_list_link)
361 if (*clntpp == ibt_hdl)
362 break;
363 if (*clntpp == NULL) {
364 IBTF_DPRINTF_L1(ibtf, "ibt_detach: Client @ %p Not Found",
365 ibt_hdl);
366 mutex_exit(&ibtl_clnt_list_mutex);
367 return (IBT_INVALID_PARAM);
368 }
369
370 /*
371 * Check out whether the client has freed all its resources.
372 * If not done, then fail the detach.
373 *
374 * viz. A client has to close all the HCA they have opened,
375 * i.e. the HCA List maintained for clients has to be empty.
376 * If this list is not empty, then the client has not performed
377 * complete clean-up, so fail the detach.
378 */
379 if (ibt_hdl->clnt_hca_list != NULL) {
380 mutex_exit(&ibtl_clnt_list_mutex);
381
382 IBTF_DPRINTF_L2(ibtf, "ibt_detach: "
383 "ERROR: Client '%s' has not closed all of its HCAs",
384 ibt_hdl->clnt_modinfop->mi_clnt_name);
385 cmn_err(CE_CONT, "IBT DETACH failed: resources not yet "
386 "freed by client '%s'\n",
387 ibt_hdl->clnt_modinfop->mi_clnt_name);
388 return (IBT_HCA_RESOURCES_NOT_FREED);
389 }
390
391 if (ibt_hdl->clnt_srv_cnt != 0) {
392 mutex_exit(&ibtl_clnt_list_mutex);
393 IBTF_DPRINTF_L2(ibtf, "ibt_detach: client '%s' still has "
394 "services or subnet_notices registered",
395 ibt_hdl->clnt_modinfop->mi_clnt_name);
396 cmn_err(CE_CONT, "IBT DETACH failed: resources not yet "
397 "freed by client '%s'\n",
398 ibt_hdl->clnt_modinfop->mi_clnt_name);
399 return (IBT_HCA_RESOURCES_NOT_FREED);
400 }
401
402 /*
403 * Delete the entry of this module from the ibtl_clnt_list List.
404 */
405 *clntpp = ibt_hdl->clnt_list_link; /* remove us */
406
407 /* make sure asyncs complete before freeing */
408 ibtl_free_clnt_async_check(ibt_hdl);
409
410 if (ibt_hdl->clnt_modinfop->mi_clnt_class == IBT_CM) {
411 ibtl_cm_async_handler = NULL;
412 ibtl_cm_clnt_private = NULL;
413 } else if (ibt_hdl->clnt_modinfop->mi_clnt_class == IBT_DM) {
414 ibtl_dm_async_handler = NULL;
415 ibtl_dm_clnt_private = NULL;
416 } else if (ibt_hdl->clnt_modinfop->mi_clnt_class == IBT_IBMA) {
417 ibtl_ibma_async_handler = NULL;
418 ibtl_ibma_clnt_private = NULL;
419 }
420 mutex_exit(&ibtl_clnt_list_mutex);
421
422 /* Free up the memory of per-client info struct. */
423 kmem_free(ibt_hdl, sizeof (ibtl_clnt_t));
424
425 return (IBT_SUCCESS);
426 }
427
428 static void
429 ibtl_set_ibhw_status()
430 {
431 ib_hw_status++;
432 }
433
434 static void
435 ibtl_clear_ibhw_status()
436 {
437 ib_hw_status--;
438 }
439
440 /*
441 * Function:
442 * ibc_init
443 * Input:
444 * modlp - Pointer to IBC client module linkage structure
445 * Output:
446 * None
447 * Returns:
448 * 0 always for now
449 * Called by:
450 * CI client calls IBTF during its _init() to register HCA with
451 * Solaris I/O framework.
452 * Description:
453 * Initializes the CI clients module linkage structure with
454 * default bus_ops structure
455 */
456 int
457 ibc_init(struct modlinkage *modlp)
458 {
459 ibtl_ibnex_cb_args_t cb_args;
460
461 mutex_enter(&ibtl_clnt_list_mutex);
462 cb_args.cb_flag = IBTL_IBNEX_IBC_INIT;
463 cb_args.cb_modlp = modlp;
464 if (ibtl_ibnex_callback_routine) {
465 (void) ((*ibtl_ibnex_callback_routine)(&cb_args));
466 }
467 mutex_exit(&ibtl_clnt_list_mutex);
468 return (0);
469 }
470
471
472 /*
473 * Function:
474 * ibc_fini
475 * Input:
476 * modlp - Pointer to IBC client module linkage structure
477 * Output:
478 * None
479 * Returns:
480 * None
481 * Called by:
482 * CI client calls IBTF during its _fini() to remove HCA with
483 * Solaris I/O framework.
484 * Description:
485 * Undo what is done during ibc_init
486 */
487 void
488 ibc_fini(struct modlinkage *modlp)
489 {
490 ibtl_ibnex_cb_args_t cb_args;
491
492 mutex_enter(&ibtl_clnt_list_mutex);
493 cb_args.cb_flag = IBTL_IBNEX_IBC_FINI;
494 cb_args.cb_modlp = modlp;
495 if (ibtl_ibnex_callback_routine) {
496 (void) ((*ibtl_ibnex_callback_routine)(&cb_args));
497 }
498 mutex_exit(&ibtl_clnt_list_mutex);
499 }
500
501 /*
502 * Function:
503 * ibc_attach
504 * Input:
505 * info_p - IBC HCA Info.
506 * Output:
507 * ibc_hdl_p - IBC Client's HCA Handle.
508 * Returns:
509 * IBC_SUCCESS
510 * IBC_FAILURE
511 * Called by:
512 * CI calls IBTF during its attach() to register HCA Device with IBTF.
513 * Description:
514 * Registers the presence of HCA device by providing the HCA device info
515 * structure and provides an opaque HCA handler for future calls to this
516 * HCA device.
517 */
518 ibc_status_t
519 ibc_attach(ibc_clnt_hdl_t *ibc_hdl_p, ibc_hca_info_t *info_p)
520 {
521 ibtl_hca_devinfo_t *hca_devp;
522 uint_t nports;
523 ibt_status_t status;
524
525 IBTF_DPRINTF_L2(ibtf, "ibc_attach(%p, %p)", ibc_hdl_p, info_p);
526
527 /* Validate the Transport API version */
528 if (info_p->hca_ci_vers != IBCI_V4) {
529 IBTF_DPRINTF_L1(ibtf, "ibc_attach: Invalid IB CI Version '%d'",
530 info_p->hca_ci_vers);
531 return (IBC_FAILURE);
532 }
533
534 if (info_p->hca_attr == NULL) {
535 IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
536 "HCA Attributes must be specified.");
537 return (IBC_FAILURE);
538 }
539
540 nports = info_p->hca_attr->hca_nports;
541 if (nports == 0) {
542 IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
543 "Number of ports must be valid");
544 return (IBC_FAILURE);
545 }
546
547 if (info_p->hca_attr->hca_max_port_pkey_tbl_sz == 0) {
548 IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
549 "Number of Partitions must be at least 1");
550 return (IBC_FAILURE);
551 }
552
553 if ((info_p->hca_attr->hca_flags & IBT_HCA_CURRENT_QP_STATE) == 0) {
554 IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
555 "HCA driver must support QP current state checking");
556 return (IBC_FAILURE);
557 }
558
559 if ((info_p->hca_attr->hca_flags & IBT_HCA_PORT_UP) == 0) {
560 IBTF_DPRINTF_L1(ibtf, "ibc_attach: "
561 "HCA driver must support PORT_UP async events");
562 return (IBC_FAILURE);
563 }
564
565 /*
566 * Install IB nexus driver (if not installed already)
567 */
568 ibtl_set_ibhw_status();
569 if (ndi_devi_config_vhci("ib", 0) == NULL) {
570 IBTF_DPRINTF_L2(ibtf, "ibc_attach: IB nexus attach failed");
571 ibtl_clear_ibhw_status();
572 return (IBC_FAILURE);
573 }
574
575 ibtl_thread_init2();
576
577 /* Allocate the memory for per-client info structure */
578 hca_devp = kmem_zalloc(sizeof (ibtl_hca_devinfo_t) +
579 (nports - 1) * sizeof (ibtl_async_port_event_t), KM_SLEEP);
580
581 mutex_enter(&ibtl_clnt_list_mutex);
582
583 /* Update HCA dev info structure */
584 hca_devp->hd_ibc_hca_hdl = info_p->hca_handle;
585 hca_devp->hd_ibc_ops = info_p->hca_ops;
586 hca_devp->hd_hca_attr = info_p->hca_attr;
587 hca_devp->hd_hca_dip = info_p->hca_attr->hca_dip;
588
589 status = ibtl_init_hca_portinfo(hca_devp);
590 if (status != IBT_SUCCESS) {
591 mutex_exit(&ibtl_clnt_list_mutex);
592 IBTF_DPRINTF_L1(ibtf, "ibc_attach: call to ibc_query_hca_ports "
593 "failed: status = %d", status);
594 kmem_free(hca_devp, sizeof (ibtl_hca_devinfo_t) +
595 (nports - 1) * sizeof (ibtl_async_port_event_t));
596 return (IBC_FAILURE);
597 }
598
599 /* Register the with MPxIO as PHCI */
600 if (ibtl_ibnex_phci_register(hca_devp->hd_hca_dip) != IBT_SUCCESS) {
601 mutex_exit(&ibtl_clnt_list_mutex);
602 IBTF_DPRINTF_L1(ibtf, "ibc_attach: MPxIO register failed");
603 kmem_free(hca_devp, sizeof (ibtl_hca_devinfo_t) +
604 (nports - 1) * sizeof (ibtl_async_port_event_t));
605 return (IBC_FAILURE);
606 }
607
608 /* Initialize the Client List for this HCA. */
609 hca_devp->hd_state = IBTL_HCA_DEV_ATTACHED;
610
611 /* lock out asyncs until after we announce the new HCA */
612 hca_devp->hd_async_busy = 1;
613
614 cv_init(&hca_devp->hd_async_task_cv, NULL, CV_DEFAULT, NULL);
615 cv_init(&hca_devp->hd_async_busy_cv, NULL, CV_DEFAULT, NULL);
616
617 /* init portinfo locking variables */
618 hca_devp->hd_portinfo_locked_port = 0;
619 cv_init(&hca_devp->hd_portinfo_cv, NULL, CV_DEFAULT, NULL);
620
621 ibtl_kstat_init(hca_devp);
622
623 mutex_exit(&ibtl_clnt_list_mutex);
624
625 /*
626 * The ibc_hdl_p points to an opaque handle which is the address
627 * of ibt_hca_devinfo_t structure passed back to the CI.
628 * The CI will pass on this handle in its future upcalls to IBTF.
629 */
630 *ibc_hdl_p = hca_devp;
631
632 return (IBC_SUCCESS);
633 }
634
635
636 /*
637 * Function:
638 * ibc_post_attach
639 * Input:
640 * ibc_hdl - IBC Client's HCA Handle.
641 * Returns:
642 * none
643 * Called by:
644 * CI calls IBTF during its attach() after a successful ibc_attach().
645 * Description:
646 * Announces to all known clients the existence of this HCA (by GUID).
647 */
648 void
649 ibc_post_attach(ibc_clnt_hdl_t ibc_hdl)
650 {
651 IBTF_DPRINTF_L2(ibtf, "ibc_post_attach(%p)", ibc_hdl);
652
653 /*
654 * Update the HCA Device List.
655 */
656 mutex_enter(&ibtl_clnt_list_mutex);
657 ibc_hdl->hd_hca_dev_link = ibtl_hca_list;
658 ibtl_hca_list = ibc_hdl;
659 mutex_exit(&ibtl_clnt_list_mutex);
660
661 /* notify all IBT Client Device Instances of the new HCA Device */
662 ibtl_announce_new_hca(ibc_hdl);
663 }
664
665
666 /*
667 * Function:
668 * ibc_pre_detach
669 * Input:
670 * ibc_clnt_hdl - IBC HCA Handle as returned during ibc_attach call.
671 * cmd - DDI_DETACH/DDI_SUSPEND command.
672 * Output:
673 * none
674 * Returns:
675 * IBC_SUCCESS
676 * IBC_FAILURE.
677 * Called by:
678 * CI to try to get all IBTF clients to close the HCA device.
679 * Description:
680 * Attempts to deregister the HCA device entry from the IBTF.
681 * If all resources are freed by the IBTF clients and this HCA
682 * is closed, then IBC_SUCCESS is returned.
683 */
684 ibc_status_t
685 ibc_pre_detach(ibc_clnt_hdl_t hca_devp, ddi_detach_cmd_t cmd)
686 {
687 ibtl_hca_devinfo_t **hcapp, *hcap;
688
689 IBTF_DPRINTF_L2(ibtf, "ibc_pre_detach(%p, 0x%x)", hca_devp, cmd);
690
691 /*
692 * Return failure, if command is not DDI_DETACH
693 */
694 switch (cmd) {
695 case DDI_DETACH:
696 break;
697 default:
698 return (IBC_FAILURE); /* TBD: DDI_FAILURE */
699 }
700
701 /* Make sure this HCA is on the HCA Device List. */
702 mutex_enter(&ibtl_clnt_list_mutex);
703 hcap = ibtl_hca_list;
704 while (hcap != NULL) {
705 if (hcap == hca_devp)
706 break;
707 hcap = hcap->hd_hca_dev_link;
708 }
709 if (hcap == NULL) {
710 mutex_exit(&ibtl_clnt_list_mutex);
711 return (IBC_FAILURE);
712 }
713
714 /*
715 * Initially set the state to "Detaching".
716 */
717 hca_devp->hd_state = IBTL_HCA_DEV_DETACHING;
718
719 /*
720 * Try to detach all IBTI clients, and continue only if all
721 * of the detaches succeed.
722 */
723 if (ibtl_detach_all_clients(hca_devp)) {
724 hca_devp->hd_state = IBTL_HCA_DEV_ATTACHED; /* fix hd_state */
725 mutex_exit(&ibtl_clnt_list_mutex);
726
727 return (IBC_FAILURE);
728 }
729
730 /*
731 * Check to see if all clients closed this HCA, or not.
732 * We only succeed if all clients cooperated.
733 */
734 if (hca_devp->hd_clnt_list != NULL) {
735 hca_devp->hd_state = IBTL_HCA_DEV_ATTACHED;
736 mutex_exit(&ibtl_clnt_list_mutex);
737 IBTF_DPRINTF_L2(ibtf, "ibc_pre_detach: HCA still has attached "
738 "clients");
739 return (IBC_FAILURE);
740 }
741
742 /*
743 * mark this device as detached
744 */
745 hca_devp->hd_state = IBTL_HCA_DEV_DETACHED;
746
747 /* Delete the entry for this hca_devp from hca_head_list */
748 hcapp = &ibtl_hca_list;
749 while (*hcapp != NULL) {
750 if (*hcapp == hca_devp)
751 break;
752 hcapp = &(*hcapp)->hd_hca_dev_link;
753 }
754
755 if (ibtl_ibnex_phci_unregister(hca_devp->hd_hca_dip) != IBT_SUCCESS) {
756 hca_devp->hd_state = IBTL_HCA_DEV_ATTACHED; /* fix hd_state */
757 mutex_exit(&ibtl_clnt_list_mutex);
758 IBTF_DPRINTF_L1(ibtf, "ibc_pre_detach: PHCI unregister failed");
759 return (IBC_FAILURE);
760 }
761
762 if (*hcapp == NULL) {
763 hca_devp->hd_state = IBTL_HCA_DEV_ATTACHED; /* fix hd_state */
764 mutex_exit(&ibtl_clnt_list_mutex);
765 IBTF_DPRINTF_L1(ibtf, "ibc_pre_detach: HCA not attached");
766 return (IBC_FAILURE);
767 }
768 *hcapp = hca_devp->hd_hca_dev_link;
769 ibtl_fast_gid_cache_valid = B_FALSE; /* invalidate fast_gid_cache */
770 mutex_exit(&ibtl_clnt_list_mutex);
771
772 return (IBC_SUCCESS);
773 }
774
775 /*
776 * Function:
777 * ibc_detach
778 * Input:
779 * ibc_clnt_hdl - IBC HCA Handle as returned during ibc_attach call.
780 * Output:
781 * none
782 * Returns:
783 * None
784 * Called by:
785 * CI to detach the HCA device from IBTF.
786 * Description:
787 * Do the second step of detaching the HCA, which is required
788 * after a successful ibc_pre_detach.
789 */
790 void
791 ibc_detach(ibc_clnt_hdl_t hca_devp)
792 {
793 IBTF_DPRINTF_L2(ibtf, "ibc_detach(%p)", hca_devp);
794
795 mutex_enter(&ibtl_clnt_list_mutex);
796 if (hca_devp->hd_state != IBTL_HCA_DEV_DETACHED) {
797 mutex_exit(&ibtl_clnt_list_mutex);
798 IBTF_DPRINTF_L0(ibtf, "ibc_detach: HCA has not successfully "
799 "pre-detached");
800 return;
801 }
802
803 cv_destroy(&hca_devp->hd_async_task_cv);
804 cv_destroy(&hca_devp->hd_async_busy_cv);
805 cv_destroy(&hca_devp->hd_portinfo_cv);
806
807 kmem_free(hca_devp->hd_portinfop, hca_devp->hd_portinfo_len);
808 mutex_exit(&ibtl_clnt_list_mutex);
809
810 ibtl_kstat_fini(hca_devp);
811
812 /* Free up the memory of per-client info struct */
813 kmem_free(hca_devp, sizeof (ibtl_hca_devinfo_t) +
814 (hca_devp->hd_hca_attr->hca_nports - 1) *
815 sizeof (ibtl_async_port_event_t));
816 ibtl_clear_ibhw_status();
817 }
818
819 /*
820 * Function:
821 * ibt_ci_data_in()
822 *
823 * Input:
824 * hca_hdl HCA Handle.
825 * flags IBT_COMPLETE_ALLOC - Finish a deferred alloc.
826 * object Identifies the type object pointed to by
827 * ibt_object_handle.
828 *
829 * ibt_object_handle The handle of the object to be associated with
830 * the data in/out
831 *
832 * data_p Pointer data passed in to the CI. The buffer
833 * should be allocated by the caller.
834 *
835 * data_sz The size of the buffer pointed to by
836 * data_p.
837 * Output:
838 *
839 * Returns:
840 * IBT_SUCCESS
841 * IBT_NOT_SUPPORTED Feature not supported.
842 * IBT_INVALID_PARAM Invalid object type specified.
843 * IBT_HCA_HDL_INVALID
844 * IBT_AH_HDL_INVALID/IBT_UD_DEST_HDL_INVALID
845 * IBT_CHAN_HDL_INVALID/IBT_QP_HDL_INVALID
846 * IBT_CQ_HDL_INVALID
847 * IBT_EEC_HDL_INVALID
848 * IBT_RDD_HDL_INVALID
849 * IBT_MW_HDL_INVALID
850 * IBT_PD_HDL_INVALID
851 * IBT_SRQ_HDL_INVALID
852 *
853 * Description:
854 * Exchange CI private data for the specified CI object.
855 */
856 ibt_status_t
857 ibt_ci_data_in(ibt_hca_hdl_t hca, ibt_ci_data_flags_t flags,
858 ibt_object_type_t object, void *ibt_object_handle, void *data_p,
859 size_t data_sz)
860 {
861 ibt_status_t retval;
862 void *ci_obj_hdl;
863
864 IBTF_DPRINTF_L3(ibtf, "ibt_ci_data_in(%p, %x, %d, %p, %p, %d)",
865 hca, flags, object, ibt_object_handle, data_p, data_sz);
866
867 switch (object) {
868 case IBT_HDL_HCA:
869 ci_obj_hdl = (void *)
870 (IBTL_HCA2CIHCA(((ibt_hca_hdl_t)ibt_object_handle)));
871 break;
872
873 case IBT_HDL_CHANNEL:
874 ci_obj_hdl = (void *)
875 (IBTL_CHAN2CIQP(((ibt_channel_hdl_t)ibt_object_handle)));
876 break;
877
878 case IBT_HDL_CQ:
879 ci_obj_hdl = (void *)
880 (((ibt_cq_hdl_t)(ibt_object_handle))->cq_ibc_cq_hdl);
881 break;
882
883 case IBT_HDL_EEC:
884 ci_obj_hdl = (void *)
885 (((ibt_eec_hdl_t)(ibt_object_handle))->eec_ibc_eec_hdl);
886 break;
887
888 case IBT_HDL_UD_DEST:
889 ci_obj_hdl = (void *)
890 (((ibt_ud_dest_hdl_t)(ibt_object_handle))->ud_ah);
891 break;
892
893 case IBT_HDL_SRQ:
894 ci_obj_hdl = (void *)
895 (((ibt_srq_hdl_t)(ibt_object_handle))->srq_ibc_srq_hdl);
896 break;
897
898 default:
899 ci_obj_hdl = ibt_object_handle;
900 break;
901 }
902
903 retval = (IBTL_HCA2CIHCAOPS_P(hca)->ibc_ci_data_in)(IBTL_HCA2CIHCA(hca),
904 flags, object, ci_obj_hdl, data_p, data_sz);
905
906 if (retval != IBT_SUCCESS) {
907 IBTF_DPRINTF_L2(ibtf, "ibt_ci_data_in: Failed : %d", retval);
908 }
909 return (retval);
910 }
911
912 /*
913 * Function:
914 * ibt_ci_data_out()
915 *
916 * Input:
917 * hca_hdl HCA Handle.
918 * flags IBT_COMPLETE_ALLOC - Finish a deferred alloc.
919 * object Identifies the type object pointed to by
920 * ibt_object_handle.
921 *
922 * ibt_object_handle The handle of the object to be associated with
923 * the data in/out
924 *
925 * data_p Pointer to a buffer in which to return the CI
926 * private data. The buffer should be allocated
927 * by the caller.
928 *
929 * data_sz The size of the buffer pointed to by
930 * data_p.
931 * Output:
932 *
933 * Returns:
934 * IBT_SUCCESS
935 * IBT_NOT_SUPPORTED Feature not supported.
936 * IBT_INSUFF_RESOURCE The buffer pointed to by data_p was too
937 * small to hold the data.
938 * IBT_INVALID_PARAM Invalid object type specified.
939 * IBT_HCA_HDL_INVALID
940 * IBT_AH_HDL_INVALID/IBT_UD_DEST_HDL_INVALID
941 * IBT_CHAN_HDL_INVALID/IBT_QP_HDL_INVALID
942 * IBT_CQ_HDL_INVALID
943 * IBT_EEC_HDL_INVALID
944 * IBT_RDD_HDL_INVALID
945 * IBT_MW_HDL_INVALID
946 * IBT_PD_HDL_INVALID
947 * IBT_SRQ_HDL_INVALID
948 *
949 * Description:
950 * Exchange CI private data for the specified CI object.
951 */
952 ibt_status_t
953 ibt_ci_data_out(ibt_hca_hdl_t hca, ibt_ci_data_flags_t flags,
954 ibt_object_type_t object, void *ibt_object_handle, void *data_p,
955 size_t data_sz)
956 {
957 ibt_status_t retval;
958 void *ci_obj_hdl;
959
960 IBTF_DPRINTF_L3(ibtf, "ibt_ci_data_out(%p, %x, %d, %p, %p, %d)",
961 hca, flags, object, ibt_object_handle, data_p, data_sz);
962
963 switch (object) {
964 case IBT_HDL_HCA:
965 ci_obj_hdl = (void *)
966 (IBTL_HCA2CIHCA(((ibt_hca_hdl_t)ibt_object_handle)));
967 break;
968
969 case IBT_HDL_CHANNEL:
970 ci_obj_hdl = (void *)
971 (IBTL_CHAN2CIQP(((ibt_channel_hdl_t)ibt_object_handle)));
972 break;
973
974 case IBT_HDL_CQ:
975 ci_obj_hdl = (void *)
976 (((ibt_cq_hdl_t)(ibt_object_handle))->cq_ibc_cq_hdl);
977 break;
978
979 case IBT_HDL_EEC:
980 ci_obj_hdl = (void *)
981 (((ibt_eec_hdl_t)(ibt_object_handle))->eec_ibc_eec_hdl);
982 break;
983
984 case IBT_HDL_UD_DEST:
985 ci_obj_hdl = (void *)
986 (((ibt_ud_dest_hdl_t)(ibt_object_handle))->ud_ah);
987 break;
988
989 case IBT_HDL_SRQ:
990 ci_obj_hdl = (void *)
991 (((ibt_srq_hdl_t)(ibt_object_handle))->srq_ibc_srq_hdl);
992 break;
993
994 default:
995 ci_obj_hdl = ibt_object_handle;
996 break;
997 }
998
999 retval = (IBTL_HCA2CIHCAOPS_P(hca)->ibc_ci_data_out)
1000 (IBTL_HCA2CIHCA(hca), flags, object, ci_obj_hdl, data_p, data_sz);
1001
1002 if (retval != IBT_SUCCESS) {
1003 IBTF_DPRINTF_L2(ibtf, "ibt_ci_data_out: Failed : %d", retval);
1004 }
1005 return (retval);
1006 }
1007
1008
1009 /*
1010 * FMA Support functions.
1011 */
1012
1013 #define IBTL_ENA_MASK 0xC0000000
1014 #define IBTL_ENA_POSSIBLE 0x80000000
1015 #define IBTL_TYPE_SHIFT 27
1016
1017 /*
1018 * Function:
1019 * ibt_get_module_failure()
1020 *
1021 * Input:
1022 * type Identifies the failing IB module.
1023 * ena '0' or the data for Fault Management
1024 * Architecture (ENA).
1025 *
1026 * Returns:
1027 * status Special IB failure status.
1028 *
1029 * Description:
1030 * XXX Just stubbed out to return failures with no data for Fault
1031 * Management Architecture (ENAs) at the moment XXX
1032 */
1033 ibt_status_t
1034 ibt_get_module_failure(ibt_failure_type_t type, uint64_t ena)
1035 {
1036 ibt_status_t ret;
1037
1038 IBTF_DPRINTF_L3(ibtf, "ibt_get_module_failure(%d, 0x%llX)", type, ena);
1039
1040 switch (type) {
1041 case IBT_FAILURE_CI:
1042 case IBT_FAILURE_IBMF:
1043 case IBT_FAILURE_IBCM:
1044 case IBT_FAILURE_IBDM:
1045 case IBT_FAILURE_IBTL:
1046 case IBT_FAILURE_IBSM:
1047 ret = IBTL_ENA_POSSIBLE | (type << IBTL_TYPE_SHIFT);
1048 break;
1049 default:
1050 ret = IBT_FAILURE;
1051 }
1052 IBTF_DPRINTF_L3(ibtf, "ibt_get_module_failure: ret = 0x%lX", ret);
1053 return (ret);
1054 }
1055
1056
1057 /*
1058 * Function:
1059 * ibc_get_ci_failure()
1060 *
1061 * Input:
1062 * ena '0' or the data for Fault Management
1063 * Architecture (ENA).
1064 *
1065 * Returns:
1066 * status Special CI failure status.
1067 *
1068 * Description:
1069 * Just use the function above to do the job.
1070 */
1071 ibt_status_t
1072 ibc_get_ci_failure(uint64_t ena)
1073 {
1074 return (ibt_get_module_failure(IBT_FAILURE_CI, ena));
1075 }
1076
1077
1078 /*
1079 * ibt_check_failure()
1080 * Function to test for special case failures.
1081 *
1082 * status An ibt_status_t returned from an IBTF function call.
1083 *
1084 * reserved_p NULL, or a pointer to where we store the data for
1085 * Fault Management Architecture (ENA).
1086 *
1087 * Description:
1088 * XXX Still need to determine the data for Fault Management Architecture
1089 * (ENA), using 0 for now XXX
1090 */
1091 ibt_failure_type_t
1092 ibt_check_failure(ibt_status_t status, uint64_t *reserved_p)
1093 {
1094 ibt_failure_type_t type;
1095
1096 IBTF_DPRINTF_L3(ibtf, "ibt_check_failure(%X)", status);
1097
1098 if ((status & IBTL_ENA_MASK) == IBTL_ENA_POSSIBLE) {
1099 type = status & ~IBTL_ENA_POSSIBLE >> IBTL_TYPE_SHIFT;
1100
1101 /* XXX Need more work here... */
1102 if (reserved_p != NULL)
1103 *reserved_p = 0;
1104 } else {
1105 type = IBT_FAILURE_STANDARD;
1106 if (reserved_p != NULL)
1107 *reserved_p = 0; /* No FMA Data Available. */
1108 }
1109 IBTF_DPRINTF_L3(ibtf, "ibt_check_failure: type = 0x%X", type);
1110 return (type);
1111 }
1112
1113 /*
1114 * Initialize and create kstats.
1115 *
1116 * We create the following kstats on all ports of the HCA:
1117 * <hca_driver_name><instance_number>/port<port_num>/stats
1118 * <hca_driver_name><instance_number>/port<port_num>/pkeys
1119 */
1120 static void
1121 ibtl_kstat_init(ibtl_hca_devinfo_t *hca_devp)
1122 {
1123 uint_t nports = hca_devp->hd_hca_attr->hca_nports;
1124 ibtl_hca_port_kstat_t *pks;
1125 int i;
1126
1127 IBTF_DPRINTF_L3(ibtf, "ibtl_kstat_init(hca_devp = 0x%p)", hca_devp);
1128
1129 hca_devp->hd_hca_port_ks_info_len =
1130 sizeof (ibtl_hca_port_kstat_t) * nports;
1131 pks = kmem_zalloc(hca_devp->hd_hca_port_ks_info_len, KM_SLEEP);
1132 hca_devp->hd_hca_port_ks_info = pks;
1133
1134 for (i = 0; i < nports; i++, pks++) {
1135 pks->pks_hca_devp = hca_devp;
1136 pks->pks_port_num = i + 1;
1137 ibtl_kstat_stats_create(hca_devp, i + 1);
1138 ibtl_kstat_pkeys_create(hca_devp, i + 1);
1139 }
1140 }
1141
1142 /*
1143 * Delete kstats on all ports of the HCA.
1144 */
1145 static void
1146 ibtl_kstat_fini(ibtl_hca_devinfo_t *hca_devp)
1147 {
1148 ibtl_hca_port_kstat_t *pks;
1149 int i;
1150
1151 IBTF_DPRINTF_L3(ibtf, "ibtl_kstat_fini(hca_devp = 0x%p)", hca_devp);
1152
1153 pks = hca_devp->hd_hca_port_ks_info;
1154
1155 if (pks == NULL)
1156 return;
1157
1158 for (i = 0; i < hca_devp->hd_hca_attr->hca_nports; i++, pks++) {
1159 if (pks->pks_stats_ksp)
1160 kstat_delete(pks->pks_stats_ksp);
1161
1162 if (pks->pks_pkeys_ksp) {
1163 ASSERT(!MUTEX_HELD(&ibtl_clnt_list_mutex));
1164 kstat_delete(pks->pks_pkeys_ksp);
1165 }
1166 }
1167
1168 kmem_free(hca_devp->hd_hca_port_ks_info,
1169 hca_devp->hd_hca_port_ks_info_len);
1170 }
1171
1172 /*
1173 * Update "stats" kstat.
1174 * Called by kstat framework.
1175 */
1176 static int
1177 ibtl_kstat_stats_update(kstat_t *ksp, int rw)
1178 {
1179 ibtl_hca_port_kstat_t *pks;
1180 ibtl_hca_devinfo_t *hca_devp;
1181 ibt_hca_portinfo_t *p;
1182 struct kstat_named *data;
1183
1184 IBTF_DPRINTF_L4(ibtf, "ibtl_kstat_stats_update(ksp = 0x%p, rw = %d)",
1185 ksp, rw);
1186
1187 if (rw == KSTAT_WRITE)
1188 return (EACCES);
1189
1190 mutex_enter(&ibtl_clnt_list_mutex);
1191
1192 /*
1193 * Update the link_state kstat using the value from portinfo cache.
1194 */
1195 pks = ksp->ks_private;
1196 hca_devp = pks->pks_hca_devp;
1197 data = (struct kstat_named *)(ksp->ks_data);
1198 p = hca_devp->hd_portinfop + pks->pks_port_num - 1;
1199 data[0].value.ui32 = (uint32_t)p->p_linkstate;
1200
1201 mutex_exit(&ibtl_clnt_list_mutex);
1202
1203 return (0);
1204 }
1205
1206 /*
1207 * Create "stats" kstat for the specified HCA port in the form:
1208 * <hca_driver_name><instance_number>/port<port_num>/stats
1209 * At preset it contains only one named data of "link_state"
1210 */
1211 static void
1212 ibtl_kstat_stats_create(ibtl_hca_devinfo_t *hca_devp, uint_t port_num)
1213 {
1214 struct kstat *ksp;
1215 struct kstat_named *named_data;
1216 char *drv_name;
1217 int drv_instance;
1218 ibtl_hca_port_kstat_t *pks;
1219 char kname[40];
1220
1221 IBTF_DPRINTF_L3(ibtf, "ibtl_kstat_stats_create(hca_devp = 0x%p, "
1222 "port_num = 0x%u)", hca_devp, port_num);
1223
1224 drv_name = (char *)ddi_driver_name(hca_devp->hd_hca_dip);
1225 drv_instance = ddi_get_instance(hca_devp->hd_hca_dip);
1226 (void) snprintf(kname, sizeof (kname), "%s%d/port%d/stats",
1227 drv_name, drv_instance, port_num);
1228
1229 ksp = kstat_create("ibtf", 0, kname, "ib", KSTAT_TYPE_NAMED, 1, 0);
1230 if (ksp == NULL) {
1231 IBTF_DPRINTF_L2(ibtf,
1232 "ibtl_kstat_stats_create: kstat_create() failed");
1233 return;
1234 }
1235
1236 named_data = (struct kstat_named *)(ksp->ks_data);
1237 kstat_named_init(&named_data[0], "link_state", KSTAT_DATA_UINT32);
1238
1239 pks = hca_devp->hd_hca_port_ks_info + port_num - 1;
1240 pks->pks_stats_ksp = ksp;
1241
1242 ksp->ks_private = pks;
1243 ksp->ks_update = ibtl_kstat_stats_update;
1244
1245 /* Install the kstat */
1246 kstat_install(ksp);
1247 }
1248
1249 /*
1250 * Update "pkeys" kstat.
1251 *
1252 * Called by kstat framework. Since ks_lock was set to ibtl_clnt_list_mutex
1253 * at the time of the kstat creation, kstat framework will hold this lock
1254 * while calling this function.
1255 */
1256 static int
1257 ibtl_kstat_pkeys_update(kstat_t *ksp, int rw)
1258 {
1259 ibtl_hca_port_kstat_t *pks;
1260 ibtl_hca_devinfo_t *hca_devp;
1261 ibt_hca_portinfo_t *p;
1262
1263 IBTF_DPRINTF_L4(ibtf, "ibtl_kstat_pkeys_update(ksp = 0x%p, rw = %d)",
1264 ksp, rw);
1265
1266 ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
1267
1268 if (rw == KSTAT_WRITE)
1269 return (EACCES);
1270
1271 pks = ksp->ks_private;
1272 hca_devp = pks->pks_hca_devp;
1273
1274 /*
1275 * Point kstat data to the pkey table in the portinfo cache.
1276 */
1277
1278 p = hca_devp->hd_portinfop + pks->pks_port_num - 1;
1279
1280 ksp->ks_data = p->p_pkey_tbl;
1281 ksp->ks_ndata = p->p_pkey_tbl_sz;
1282 ksp->ks_data_size = p->p_pkey_tbl_sz * sizeof (ib_pkey_t);
1283
1284 return (0);
1285 }
1286
1287 /*
1288 * Create "pkeys" kstat for the specified HCA port in the form:
1289 * <hca_driver_name><instance_number>/port<port_num>/pkeys
1290 *
1291 * Currently kstat framework allows only some fixed data types as named
1292 * data components under a named kstat. Due to this limitation it is not
1293 * possible to add "pkeys" as a named data under the "stats" kstat.
1294 */
1295 static void
1296 ibtl_kstat_pkeys_create(ibtl_hca_devinfo_t *hca_devp, uint_t port_num)
1297 {
1298 struct kstat *ksp;
1299 char *drv_name;
1300 int drv_instance;
1301 char kname[40];
1302 ibtl_hca_port_kstat_t *pks;
1303
1304 IBTF_DPRINTF_L3(ibtf, "ibtl_kstat_stats_create(hca_devp = 0x%p, "
1305 "port_num = 0x%u)", hca_devp, port_num);
1306
1307 drv_name = (char *)ddi_driver_name(hca_devp->hd_hca_dip);
1308 drv_instance = ddi_get_instance(hca_devp->hd_hca_dip);
1309 (void) snprintf(kname, sizeof (kname), "%s%d/port%d/pkeys",
1310 drv_name, drv_instance, port_num);
1311
1312 ksp = kstat_create("ibtf", 0, kname, "ib", KSTAT_TYPE_RAW, 0,
1313 KSTAT_FLAG_VAR_SIZE | KSTAT_FLAG_VIRTUAL);
1314 if (ksp == NULL) {
1315 IBTF_DPRINTF_L2(ibtf,
1316 "ibtl_kstat_pkeys_create: kstat_create() failed");
1317 return;
1318 }
1319
1320 pks = hca_devp->hd_hca_port_ks_info + port_num - 1;
1321 pks->pks_pkeys_ksp = ksp;
1322
1323 ksp->ks_private = pks;
1324 ksp->ks_update = ibtl_kstat_pkeys_update;
1325 ksp->ks_lock = &ibtl_clnt_list_mutex;
1326
1327 /*
1328 * We just go with the default_kstat_snapshot().
1329 * So there is no need to set ks_snapshot field.
1330 */
1331
1332 /* Install the kstat */
1333 kstat_install(ksp);
1334 }