1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * I/O Controller functions for the Solaris COMSTAR SCSI RDMA Protocol
28 * Target (SRPT) port provider.
29 */
30
31 #include <sys/types.h>
32 #include <sys/ddi.h>
33 #include <sys/types.h>
34 #include <sys/sunddi.h>
35 #include <sys/atomic.h>
36 #include <sys/sysmacros.h>
37 #include <sys/ib/ibtl/ibti.h>
38 #include <sys/sdt.h>
39
40 #include "srp.h"
41 #include "srpt_impl.h"
42 #include "srpt_ioc.h"
43 #include "srpt_stp.h"
44 #include "srpt_ch.h"
45 #include "srpt_common.h"
46
47 /*
48 * srpt_ioc_srq_size - Tunable parameter that specifies the number
49 * of receive WQ entries that can be posted to the IOC shared
50 * receive queue.
51 */
52 uint32_t srpt_ioc_srq_size = SRPT_DEFAULT_IOC_SRQ_SIZE;
53 extern uint16_t srpt_send_msg_depth;
54 extern uint32_t srpt_iu_size;
55 extern boolean_t srpt_enable_by_default;
56
57 /* IOC profile capabilities mask must be big-endian */
58 typedef struct srpt_ioc_opcap_bits_s {
59 #if defined(_BIT_FIELDS_LTOH)
60 uint8_t af:1,
61 at:1,
62 wf:1,
63 wt:1,
64 rf:1,
65 rt:1,
66 sf:1,
67 st:1;
68 #elif defined(_BIT_FIELDS_HTOL)
69 uint8_t st:1,
70 sf:1,
71 rt:1,
72 rf:1,
73 wt:1,
74 wf:1,
75 at:1,
76 af:1;
77 #else
78 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
79 #endif
80 } srpt_ioc_opcap_bits_t;
81
82 typedef union {
83 srpt_ioc_opcap_bits_t bits;
84 uint8_t mask;
85 } srpt_ioc_opcap_mask_t;
86
87 /*
88 * vmem arena variables - values derived from iSER
89 */
90 #define SRPT_MR_QUANTSIZE 0x400 /* 1K */
91 #define SRPT_MIN_CHUNKSIZE 0x100000 /* 1MB */
92
93 /* use less memory on 32-bit kernels as it's much more constrained */
94 #ifdef _LP64
95 #define SRPT_BUF_MR_CHUNKSIZE 0x1000000 /* 16MB */
96 #define SRPT_BUF_POOL_MAX 0x40000000 /* 1GB */
97 #else
98 #define SRPT_BUF_MR_CHUNKSIZE 0x400000 /* 4MB */
99 #define SRPT_BUF_POOL_MAX 0x4000000 /* 64MB */
100 #endif
101
102 static ibt_mr_flags_t srpt_dbuf_mr_flags =
103 IBT_MR_ENABLE_LOCAL_WRITE | IBT_MR_ENABLE_REMOTE_WRITE |
104 IBT_MR_ENABLE_REMOTE_READ;
105
106 void srpt_ioc_ib_async_hdlr(void *clnt, ibt_hca_hdl_t hdl,
107 ibt_async_code_t code, ibt_async_event_t *event);
108
109 static struct ibt_clnt_modinfo_s srpt_ibt_modinfo = {
110 IBTI_V_CURR,
111 IBT_STORAGE_DEV,
112 srpt_ioc_ib_async_hdlr,
113 NULL,
114 "srpt"
115 };
116
117 static srpt_ioc_t *srpt_ioc_init(ib_guid_t guid);
118 static void srpt_ioc_fini(srpt_ioc_t *ioc);
119 static boolean_t srpt_check_hca_cfg_enabled(ib_guid_t hca_guid);
120
121 static srpt_vmem_pool_t *srpt_vmem_create(const char *name, srpt_ioc_t *ioc,
122 ib_memlen_t chunksize, uint64_t maxsize, ibt_mr_flags_t flags);
123 static void *srpt_vmem_alloc(srpt_vmem_pool_t *vm_pool, size_t size);
124 static int srpt_vmem_mr_compare(const void *a, const void *b);
125 static srpt_mr_t *srpt_vmem_chunk_alloc(srpt_vmem_pool_t *ioc,
126 ib_memlen_t chunksize);
127 static void srpt_vmem_destroy(srpt_vmem_pool_t *vm_pool);
128 static void srpt_vmem_free(srpt_vmem_pool_t *vm_pool, void *vaddr, size_t size);
129 static srpt_mr_t *srpt_reg_mem(srpt_vmem_pool_t *vm_pool, ib_vaddr_t vaddr,
130 ib_memlen_t len);
131 static void srpt_vmem_chunk_free(srpt_vmem_pool_t *vm_pool, srpt_mr_t *mr);
132 static void srpt_dereg_mem(srpt_ioc_t *ioc, srpt_mr_t *mr);
133 static int srpt_vmem_mr(srpt_vmem_pool_t *vm_pool, void *vaddr, size_t size,
134 srpt_mr_t *mr);
135
136 /*
137 * srpt_ioc_attach() - I/O Controller attach
138 *
139 * Attach to IBTF and initialize I/O controllers. The srpt_ctxt->sc_rwlock
140 * should be held outside of this call.
141 */
142 int
srpt_ioc_attach()143 srpt_ioc_attach()
144 {
145 int status;
146 int hca_cnt;
147 int hca_ndx;
148 ib_guid_t *guid;
149
150 ASSERT(srpt_ctxt != NULL);
151
152 /*
153 * Attach to IBTF and initialize a list of IB devices. Each
154 * HCA will be represented by an I/O Controller.
155 */
156 status = ibt_attach(&srpt_ibt_modinfo, srpt_ctxt->sc_dip,
157 srpt_ctxt, &srpt_ctxt->sc_ibt_hdl);
158 if (status != DDI_SUCCESS) {
159 SRPT_DPRINTF_L1("ioc_attach, ibt_attach failed (0x%x)",
160 status);
161 return (DDI_FAILURE);
162 }
163
164 hca_cnt = ibt_get_hca_list(&guid);
165 if (hca_cnt < 1) {
166 /*
167 * not a fatal error. Service will be up and
168 * waiting for ATTACH events.
169 */
170 SRPT_DPRINTF_L2("ioc_attach, no HCA found");
171 return (DDI_SUCCESS);
172 }
173
174 for (hca_ndx = 0; hca_ndx < hca_cnt; hca_ndx++) {
175 SRPT_DPRINTF_L2("ioc_attach, attaching HCA %016llx",
176 (u_longlong_t)guid[hca_ndx]);
177 srpt_ioc_attach_hca(guid[hca_ndx], B_FALSE);
178 }
179
180 ibt_free_hca_list(guid, hca_cnt);
181 SRPT_DPRINTF_L3("ioc_attach, added %d I/O Controller(s)",
182 srpt_ctxt->sc_num_iocs);
183 return (DDI_SUCCESS);
184 }
185
186 /*
187 * Initialize I/O Controllers. sprt_ctxt->sc_rwlock must be locked by the
188 * caller.
189 *
190 * 'checked' indicates no need to lookup the hca in the HCA configuration
191 * list.
192 */
193 void
srpt_ioc_attach_hca(ib_guid_t hca_guid,boolean_t checked)194 srpt_ioc_attach_hca(ib_guid_t hca_guid, boolean_t checked)
195 {
196 boolean_t enable_hca = B_TRUE;
197 srpt_ioc_t *ioc;
198
199 if (!checked) {
200 enable_hca = srpt_check_hca_cfg_enabled(hca_guid);
201
202 if (!enable_hca) {
203 /* nothing to do */
204 SRPT_DPRINTF_L2(
205 "ioc_attach_hca, HCA %016llx disabled "
206 "by srpt config",
207 (u_longlong_t)hca_guid);
208 return;
209 }
210 }
211
212 SRPT_DPRINTF_L2("ioc_attach_hca, adding I/O"
213 " Controller (%016llx)", (u_longlong_t)hca_guid);
214
215 ioc = srpt_ioc_init(hca_guid);
216 if (ioc == NULL) {
217 /*
218 * IOC already exists or an error occurred. Already
219 * logged by srpt_ioc_init()
220 */
221 return;
222 }
223
224 /*
225 * Create the COMSTAR SRP Target for this IOC. If this fails,
226 * remove the IOC.
227 */
228 rw_enter(&ioc->ioc_rwlock, RW_WRITER);
229 ioc->ioc_tgt_port = srpt_stp_alloc_port(ioc, ioc->ioc_guid);
230 if (ioc->ioc_tgt_port == NULL) {
231 SRPT_DPRINTF_L1("ioc_attach_hca: alloc SCSI"
232 " Target Port error on GUID(%016llx)",
233 (u_longlong_t)ioc->ioc_guid);
234 rw_exit(&ioc->ioc_rwlock);
235 srpt_ioc_fini(ioc);
236 return;
237 }
238 rw_exit(&ioc->ioc_rwlock);
239
240 /*
241 * New HCA added with default SCSI Target Port, SRP service
242 * will be started when SCSI Target Port is brought
243 * on-line by STMF.
244 */
245 list_insert_tail(&srpt_ctxt->sc_ioc_list, ioc);
246 SRPT_DPRINTF_L2("ioc_attach_hca, I/O Controller ibt HCA hdl (%p)",
247 (void *)ioc->ioc_ibt_hdl);
248
249 srpt_ctxt->sc_num_iocs++;
250 }
251
252 /*
253 * srpt_check_hca_cfg_enabled()
254 *
255 * Function to check the configuration for the enabled status of a given
256 * HCA. Returns B_TRUE if SRPT services should be activated for this HCA,
257 * B_FALSE if it should be disabled.
258 */
259 static boolean_t
srpt_check_hca_cfg_enabled(ib_guid_t hca_guid)260 srpt_check_hca_cfg_enabled(ib_guid_t hca_guid)
261 {
262 int status;
263 char buf[32];
264 nvlist_t *hcanv;
265 boolean_t enable_hca;
266
267 enable_hca = srpt_enable_by_default;
268
269 SRPT_FORMAT_HCAKEY(buf, sizeof (buf), (u_longlong_t)hca_guid);
270
271 if (srpt_ctxt->sc_cfg_hca_nv != NULL) {
272 status = nvlist_lookup_nvlist(srpt_ctxt->sc_cfg_hca_nv,
273 buf, &hcanv);
274 if (status == 0) {
275 SRPT_DPRINTF_L3("check_hca_cfg, found guid %s", buf);
276 (void) nvlist_lookup_boolean_value(hcanv,
277 SRPT_PROP_ENABLED, &enable_hca);
278 } else {
279 SRPT_DPRINTF_L3("check_hca_cfg, did not find guid %s",
280 buf);
281 }
282 }
283
284 return (enable_hca);
285 }
286
287 /*
288 * srpt_ioc_update()
289 *
290 * Using the configuration nvlist, enables or disables SRP services
291 * the provided HCAs. srpt_ctxt->sc_rwlock should be held outside of this call.
292 */
293 void
srpt_ioc_update(void)294 srpt_ioc_update(void)
295 {
296 boolean_t enabled;
297 nvpair_t *nvp = NULL;
298 uint64_t hca_guid;
299 nvlist_t *nvl;
300 nvlist_t *cfg = srpt_ctxt->sc_cfg_hca_nv;
301
302 if (cfg == NULL) {
303 SRPT_DPRINTF_L2("ioc_update, no configuration data");
304 return;
305 }
306
307 while ((nvp = nvlist_next_nvpair(cfg, nvp)) != NULL) {
308 enabled = srpt_enable_by_default;
309
310 if ((nvpair_value_nvlist(nvp, &nvl)) != 0) {
311 SRPT_DPRINTF_L2("ioc_update, did not find an nvlist");
312 continue;
313 }
314
315 if ((nvlist_lookup_uint64(nvl, SRPT_PROP_GUID, &hca_guid))
316 != 0) {
317 SRPT_DPRINTF_L2("ioc_update, did not find a guid");
318 continue;
319 }
320
321 (void) nvlist_lookup_boolean_value(nvl, SRPT_PROP_ENABLED,
322 &enabled);
323
324 if (enabled) {
325 SRPT_DPRINTF_L2("ioc_update, enabling guid %016llx",
326 (u_longlong_t)hca_guid);
327 srpt_ioc_attach_hca(hca_guid, B_TRUE);
328 } else {
329 SRPT_DPRINTF_L2("ioc_update, disabling guid %016llx",
330 (u_longlong_t)hca_guid);
331 srpt_ioc_detach_hca(hca_guid);
332 }
333 }
334 }
335
336 /*
337 * srpt_ioc_detach() - I/O Controller detach
338 *
339 * srpt_ctxt->sc_rwlock should be held outside of this call.
340 */
341 void
srpt_ioc_detach()342 srpt_ioc_detach()
343 {
344 srpt_ioc_t *ioc;
345
346 /*
347 * All SRP targets must be destroyed before calling this
348 * function.
349 */
350 while ((ioc = list_head(&srpt_ctxt->sc_ioc_list)) != NULL) {
351 SRPT_DPRINTF_L2("ioc_detach, removing I/O Controller(%p)"
352 " (%016llx), ibt_hdl(%p)",
353 (void *)ioc,
354 ioc ? (u_longlong_t)ioc->ioc_guid : 0x0ll,
355 (void *)ioc->ioc_ibt_hdl);
356
357 list_remove(&srpt_ctxt->sc_ioc_list, ioc);
358 srpt_ioc_fini(ioc);
359 srpt_ctxt->sc_num_iocs--;
360 }
361
362 srpt_ctxt->sc_ibt_hdl = NULL;
363 }
364
365 /*
366 * srpt_ioc_detach_hca()
367 *
368 * Stop SRP Target services on this HCA
369 *
370 * Note that this is not entirely synchronous with srpt_ioc_attach_hca()
371 * in that we don't need to check the configuration to know whether to
372 * disable an HCA. We get here either because the IB framework has told
373 * us the HCA has been detached, or because the administrator has explicitly
374 * disabled this HCA.
375 *
376 * Must be called with srpt_ctxt->sc_rwlock locked as RW_WRITER.
377 */
378 void
srpt_ioc_detach_hca(ib_guid_t hca_guid)379 srpt_ioc_detach_hca(ib_guid_t hca_guid)
380 {
381 srpt_ioc_t *ioc;
382 srpt_target_port_t *tgt;
383 stmf_status_t stmf_status = STMF_SUCCESS;
384
385 ioc = srpt_ioc_get_locked(hca_guid);
386 if (ioc == NULL) {
387 /* doesn't exist, nothing to do */
388 return;
389 }
390
391 rw_enter(&ioc->ioc_rwlock, RW_WRITER);
392 tgt = ioc->ioc_tgt_port;
393
394 if (tgt != NULL) {
395 stmf_status = srpt_stp_destroy_port(tgt);
396 if (stmf_status == STMF_SUCCESS) {
397 ioc->ioc_tgt_port = NULL;
398 (void) srpt_stp_free_port(tgt);
399 }
400 }
401
402 rw_exit(&ioc->ioc_rwlock);
403
404 if (stmf_status != STMF_SUCCESS) {
405 /* should never happen */
406 return;
407 }
408
409 list_remove(&srpt_ctxt->sc_ioc_list, ioc);
410 srpt_ctxt->sc_num_iocs--;
411
412 srpt_ioc_fini(ioc);
413 SRPT_DPRINTF_L2("ioc_detach_hca, HCA %016llx detached",
414 (u_longlong_t)hca_guid);
415 }
416
417 /*
418 * srpt_ioc_init() - I/O Controller initialization
419 *
420 * Requires srpt_ctxt->rw_lock be held outside of call.
421 */
422 static srpt_ioc_t *
srpt_ioc_init(ib_guid_t guid)423 srpt_ioc_init(ib_guid_t guid)
424 {
425 ibt_status_t status;
426 srpt_ioc_t *ioc;
427 ibt_hca_attr_t hca_attr;
428 uint_t iu_ndx;
429 uint_t err_ndx;
430 ibt_mr_attr_t mr_attr;
431 ibt_mr_desc_t mr_desc;
432 srpt_iu_t *iu;
433 ibt_srq_sizes_t srq_attr;
434 char namebuf[32];
435 size_t iu_offset;
436 uint_t srq_sz;
437
438 status = ibt_query_hca_byguid(guid, &hca_attr);
439 if (status != IBT_SUCCESS) {
440 SRPT_DPRINTF_L1("ioc_init, HCA query error (%d)",
441 status);
442 return (NULL);
443 }
444
445 ioc = srpt_ioc_get_locked(guid);
446 if (ioc != NULL) {
447 SRPT_DPRINTF_L2("ioc_init, HCA already exists");
448 return (NULL);
449 }
450
451 ioc = kmem_zalloc(sizeof (srpt_ioc_t), KM_SLEEP);
452
453 rw_init(&ioc->ioc_rwlock, NULL, RW_DRIVER, NULL);
454 rw_enter(&ioc->ioc_rwlock, RW_WRITER);
455
456 bcopy(&hca_attr, &ioc->ioc_attr, sizeof (ibt_hca_attr_t));
457
458 SRPT_DPRINTF_L2("ioc_init, HCA max mr=%d, mrlen=%lld",
459 hca_attr.hca_max_memr, (u_longlong_t)hca_attr.hca_max_memr_len);
460 ioc->ioc_guid = guid;
461
462 status = ibt_open_hca(srpt_ctxt->sc_ibt_hdl, guid, &ioc->ioc_ibt_hdl);
463 if (status != IBT_SUCCESS) {
464 SRPT_DPRINTF_L1("ioc_init, IBT open failed (%d)", status);
465 goto hca_open_err;
466 }
467
468 status = ibt_alloc_pd(ioc->ioc_ibt_hdl, IBT_PD_NO_FLAGS,
469 &ioc->ioc_pd_hdl);
470 if (status != IBT_SUCCESS) {
471 SRPT_DPRINTF_L1("ioc_init, IBT create PD failed (%d)", status);
472 goto pd_alloc_err;
473 }
474
475 /*
476 * We require hardware support for SRQs. We use a common SRQ to
477 * reduce channel memory consumption.
478 */
479 if ((ioc->ioc_attr.hca_flags & IBT_HCA_SRQ) == 0) {
480 SRPT_DPRINTF_L0(
481 "ioc_init, no SRQ capability, HCA not supported");
482 goto srq_alloc_err;
483 }
484
485 SRPT_DPRINTF_L3("ioc_init, Using shared receive queues, max srq work"
486 " queue size(%d), def size = %d", ioc->ioc_attr.hca_max_srqs_sz,
487 srpt_ioc_srq_size);
488 srq_sz = srq_attr.srq_wr_sz = min(srpt_ioc_srq_size,
489 ioc->ioc_attr.hca_max_srqs_sz) - 1;
490 srq_attr.srq_sgl_sz = 1;
491
492 status = ibt_alloc_srq(ioc->ioc_ibt_hdl, IBT_SRQ_NO_FLAGS,
493 ioc->ioc_pd_hdl, &srq_attr, &ioc->ioc_srq_hdl,
494 &ioc->ioc_srq_attr);
495 if (status != IBT_SUCCESS) {
496 SRPT_DPRINTF_L1("ioc_init, IBT create SRQ failed(%d)", status);
497 goto srq_alloc_err;
498 }
499
500 SRPT_DPRINTF_L2("ioc_init, Using SRQ size(%d), MAX SG size(%d)",
501 srq_sz, 1);
502
503 ibt_set_srq_private(ioc->ioc_srq_hdl, ioc);
504
505 /*
506 * Allocate a pool of SRP IU message buffers and post them to
507 * the I/O Controller SRQ. We let the SRQ manage the free IU
508 * messages.
509 */
510 ioc->ioc_num_iu_entries = srq_sz;
511
512 ioc->ioc_iu_pool = kmem_zalloc(sizeof (srpt_iu_t) *
513 ioc->ioc_num_iu_entries, KM_SLEEP);
514
515 ioc->ioc_iu_bufs = kmem_alloc(srpt_iu_size *
516 ioc->ioc_num_iu_entries, KM_SLEEP);
517
518 if ((ioc->ioc_iu_pool == NULL) || (ioc->ioc_iu_bufs == NULL)) {
519 SRPT_DPRINTF_L1("ioc_init, failed to allocate SRQ IUs");
520 goto srq_iu_alloc_err;
521 }
522
523 mr_attr.mr_vaddr = (ib_vaddr_t)(uintptr_t)ioc->ioc_iu_bufs;
524 mr_attr.mr_len = srpt_iu_size * ioc->ioc_num_iu_entries;
525 mr_attr.mr_as = NULL;
526 mr_attr.mr_flags = IBT_MR_ENABLE_LOCAL_WRITE;
527
528 status = ibt_register_mr(ioc->ioc_ibt_hdl, ioc->ioc_pd_hdl,
529 &mr_attr, &ioc->ioc_iu_mr_hdl, &mr_desc);
530 if (status != IBT_SUCCESS) {
531 SRPT_DPRINTF_L1("ioc_init, IU buffer pool MR err(%d)",
532 status);
533 goto srq_iu_alloc_err;
534 }
535
536 for (iu_ndx = 0, iu = ioc->ioc_iu_pool; iu_ndx <
537 ioc->ioc_num_iu_entries; iu_ndx++, iu++) {
538
539 iu_offset = (iu_ndx * srpt_iu_size);
540 iu->iu_buf = (void *)((uintptr_t)ioc->ioc_iu_bufs + iu_offset);
541
542 mutex_init(&iu->iu_lock, NULL, MUTEX_DRIVER, NULL);
543
544 iu->iu_sge.ds_va = mr_desc.md_vaddr + iu_offset;
545 iu->iu_sge.ds_key = mr_desc.md_lkey;
546 iu->iu_sge.ds_len = srpt_iu_size;
547 iu->iu_ioc = ioc;
548 iu->iu_pool_ndx = iu_ndx;
549
550 status = srpt_ioc_post_recv_iu(ioc, &ioc->ioc_iu_pool[iu_ndx]);
551 if (status != IBT_SUCCESS) {
552 SRPT_DPRINTF_L1("ioc_init, SRQ IU post err(%d)",
553 status);
554 goto srq_iu_post_err;
555 }
556 }
557
558 /*
559 * Initialize the dbuf vmem arena
560 */
561 (void) snprintf(namebuf, sizeof (namebuf),
562 "srpt_buf_pool_%16llX", (u_longlong_t)guid);
563 ioc->ioc_dbuf_pool = srpt_vmem_create(namebuf, ioc,
564 SRPT_BUF_MR_CHUNKSIZE, SRPT_BUF_POOL_MAX, srpt_dbuf_mr_flags);
565
566 if (ioc->ioc_dbuf_pool == NULL) {
567 goto stmf_db_alloc_err;
568 }
569
570 /*
571 * Allocate the I/O Controller STMF data buffer allocator. The
572 * data store will span all targets associated with this IOC.
573 */
574 ioc->ioc_stmf_ds = stmf_alloc(STMF_STRUCT_DBUF_STORE, 0, 0);
575 if (ioc->ioc_stmf_ds == NULL) {
576 SRPT_DPRINTF_L1("ioc_attach, STMF DBUF alloc failure for IOC");
577 goto stmf_db_alloc_err;
578 }
579 ioc->ioc_stmf_ds->ds_alloc_data_buf = &srpt_ioc_ds_alloc_dbuf;
580 ioc->ioc_stmf_ds->ds_free_data_buf = &srpt_ioc_ds_free_dbuf;
581 ioc->ioc_stmf_ds->ds_port_private = ioc;
582
583 rw_exit(&ioc->ioc_rwlock);
584 return (ioc);
585
586 stmf_db_alloc_err:
587 if (ioc->ioc_dbuf_pool != NULL) {
588 srpt_vmem_destroy(ioc->ioc_dbuf_pool);
589 }
590
591 srq_iu_post_err:
592 if (ioc->ioc_iu_mr_hdl != NULL) {
593 status = ibt_deregister_mr(ioc->ioc_ibt_hdl,
594 ioc->ioc_iu_mr_hdl);
595 if (status != IBT_SUCCESS) {
596 SRPT_DPRINTF_L1("ioc_init, error deregistering"
597 " memory region (%d)", status);
598 }
599 }
600 for (err_ndx = 0, iu = ioc->ioc_iu_pool; err_ndx < iu_ndx;
601 err_ndx++, iu++) {
602 mutex_destroy(&iu->iu_lock);
603 }
604
605 srq_iu_alloc_err:
606 if (ioc->ioc_iu_bufs != NULL) {
607 kmem_free(ioc->ioc_iu_bufs, srpt_iu_size *
608 ioc->ioc_num_iu_entries);
609 }
610 if (ioc->ioc_iu_pool != NULL) {
611 kmem_free(ioc->ioc_iu_pool,
612 sizeof (srpt_iu_t) * ioc->ioc_num_iu_entries);
613 }
614 if (ioc->ioc_srq_hdl != NULL) {
615 status = ibt_free_srq(ioc->ioc_srq_hdl);
616 if (status != IBT_SUCCESS) {
617 SRPT_DPRINTF_L1("ioc_init, error freeing SRQ (%d)",
618 status);
619 }
620
621 }
622
623 srq_alloc_err:
624 status = ibt_free_pd(ioc->ioc_ibt_hdl, ioc->ioc_pd_hdl);
625 if (status != IBT_SUCCESS) {
626 SRPT_DPRINTF_L1("ioc_init, free PD error (%d)", status);
627 }
628
629 pd_alloc_err:
630 status = ibt_close_hca(ioc->ioc_ibt_hdl);
631 if (status != IBT_SUCCESS) {
632 SRPT_DPRINTF_L1("ioc_init, close ioc error (%d)", status);
633 }
634
635 hca_open_err:
636 rw_exit(&ioc->ioc_rwlock);
637 rw_destroy(&ioc->ioc_rwlock);
638 kmem_free(ioc, sizeof (*ioc));
639 return (NULL);
640 }
641
642 /*
643 * srpt_ioc_fini() - I/O Controller Cleanup
644 *
645 * Requires srpt_ctxt->sc_rwlock be held outside of call.
646 */
647 static void
srpt_ioc_fini(srpt_ioc_t * ioc)648 srpt_ioc_fini(srpt_ioc_t *ioc)
649 {
650 int status;
651 int ndx;
652
653 /*
654 * Note driver flows will have already taken all SRP
655 * services running on the I/O Controller off-line.
656 */
657 ASSERT(ioc->ioc_tgt_port == NULL);
658 rw_enter(&ioc->ioc_rwlock, RW_WRITER);
659 if (ioc->ioc_ibt_hdl != NULL) {
660 if (ioc->ioc_stmf_ds != NULL) {
661 stmf_free(ioc->ioc_stmf_ds);
662 }
663
664 if (ioc->ioc_srq_hdl != NULL) {
665 SRPT_DPRINTF_L4("ioc_fini, freeing SRQ");
666 status = ibt_free_srq(ioc->ioc_srq_hdl);
667 if (status != IBT_SUCCESS) {
668 SRPT_DPRINTF_L1("ioc_fini, free SRQ"
669 " error (%d)", status);
670 }
671 }
672
673 if (ioc->ioc_iu_mr_hdl != NULL) {
674 status = ibt_deregister_mr(
675 ioc->ioc_ibt_hdl, ioc->ioc_iu_mr_hdl);
676 if (status != IBT_SUCCESS) {
677 SRPT_DPRINTF_L1("ioc_fini, error deregistering"
678 " memory region (%d)", status);
679 }
680 }
681
682 if (ioc->ioc_iu_bufs != NULL) {
683 kmem_free(ioc->ioc_iu_bufs, srpt_iu_size *
684 ioc->ioc_num_iu_entries);
685 }
686
687 if (ioc->ioc_iu_pool != NULL) {
688 SRPT_DPRINTF_L4("ioc_fini, freeing IU entries");
689 for (ndx = 0; ndx < ioc->ioc_num_iu_entries; ndx++) {
690 mutex_destroy(&ioc->ioc_iu_pool[ndx].iu_lock);
691 }
692
693 SRPT_DPRINTF_L4("ioc_fini, free IU pool struct");
694 kmem_free(ioc->ioc_iu_pool,
695 sizeof (srpt_iu_t) * (ioc->ioc_num_iu_entries));
696 ioc->ioc_iu_pool = NULL;
697 ioc->ioc_num_iu_entries = 0;
698 }
699
700 if (ioc->ioc_dbuf_pool != NULL) {
701 srpt_vmem_destroy(ioc->ioc_dbuf_pool);
702 }
703
704 if (ioc->ioc_pd_hdl != NULL) {
705 status = ibt_free_pd(ioc->ioc_ibt_hdl,
706 ioc->ioc_pd_hdl);
707 if (status != IBT_SUCCESS) {
708 SRPT_DPRINTF_L1("ioc_fini, free PD"
709 " error (%d)", status);
710 }
711 }
712
713 status = ibt_close_hca(ioc->ioc_ibt_hdl);
714 if (status != IBT_SUCCESS) {
715 SRPT_DPRINTF_L1(
716 "ioc_fini, close ioc error (%d)", status);
717 }
718 }
719 rw_exit(&ioc->ioc_rwlock);
720 rw_destroy(&ioc->ioc_rwlock);
721 kmem_free(ioc, sizeof (srpt_ioc_t));
722 }
723
724 /*
725 * srpt_ioc_port_active() - I/O Controller port active
726 */
727 static void
srpt_ioc_port_active(ibt_async_event_t * event)728 srpt_ioc_port_active(ibt_async_event_t *event)
729 {
730 ibt_status_t status;
731 srpt_ioc_t *ioc;
732 srpt_target_port_t *tgt = NULL;
733 boolean_t online_target = B_FALSE;
734 stmf_change_status_t cstatus;
735
736 ASSERT(event != NULL);
737
738 SRPT_DPRINTF_L3("ioc_port_active event handler, invoked");
739
740 /*
741 * Find the HCA in question and if the HCA has completed
742 * initialization, and the SRP Target service for the
743 * the I/O Controller exists, then bind this port.
744 */
745 ioc = srpt_ioc_get(event->ev_hca_guid);
746
747 if (ioc == NULL) {
748 SRPT_DPRINTF_L2("ioc_port_active, I/O Controller not"
749 " active");
750 return;
751 }
752
753 tgt = ioc->ioc_tgt_port;
754 if (tgt == NULL) {
755 SRPT_DPRINTF_L2("ioc_port_active, no I/O Controller target"
756 " undefined");
757 return;
758 }
759
760
761 /*
762 * We take the target lock here to serialize this operation
763 * with any STMF initiated target state transitions. If
764 * SRP is off-line then the service handle is NULL.
765 */
766 mutex_enter(&tgt->tp_lock);
767
768 if (tgt->tp_ibt_svc_hdl != NULL) {
769 status = srpt_ioc_svc_bind(tgt, event->ev_port);
770 if ((status != IBT_SUCCESS) &&
771 (status != IBT_HCA_PORT_NOT_ACTIVE)) {
772 SRPT_DPRINTF_L1("ioc_port_active, bind failed (%d)",
773 status);
774 }
775 } else {
776 /* if we were offline because of no ports, try onlining now */
777 if ((tgt->tp_num_active_ports == 0) &&
778 (tgt->tp_requested_state != tgt->tp_state) &&
779 (tgt->tp_requested_state == SRPT_TGT_STATE_ONLINE)) {
780 online_target = B_TRUE;
781 cstatus.st_completion_status = STMF_SUCCESS;
782 cstatus.st_additional_info = "port active";
783 }
784 }
785
786 mutex_exit(&tgt->tp_lock);
787
788 if (online_target) {
789 stmf_status_t ret;
790
791 ret = stmf_ctl(STMF_CMD_LPORT_ONLINE, tgt->tp_lport, &cstatus);
792
793 if (ret == STMF_SUCCESS) {
794 SRPT_DPRINTF_L1("ioc_port_active, port %d active, "
795 "target %016llx online requested", event->ev_port,
796 (u_longlong_t)ioc->ioc_guid);
797 } else if (ret != STMF_ALREADY) {
798 SRPT_DPRINTF_L1("ioc_port_active, port %d active, "
799 "target %016llx failed online request: %d",
800 event->ev_port, (u_longlong_t)ioc->ioc_guid,
801 (int)ret);
802 }
803 }
804 }
805
806 /*
807 * srpt_ioc_port_down()
808 */
809 static void
srpt_ioc_port_down(ibt_async_event_t * event)810 srpt_ioc_port_down(ibt_async_event_t *event)
811 {
812 srpt_ioc_t *ioc;
813 srpt_target_port_t *tgt;
814 srpt_channel_t *ch;
815 srpt_channel_t *next_ch;
816 boolean_t offline_target = B_FALSE;
817 stmf_change_status_t cstatus;
818
819 SRPT_DPRINTF_L3("ioc_port_down event handler, invoked");
820
821 /*
822 * Find the HCA in question and if the HCA has completed
823 * initialization, and the SRP Target service for the
824 * the I/O Controller exists, then logout initiators
825 * through this port.
826 */
827 ioc = srpt_ioc_get(event->ev_hca_guid);
828
829 if (ioc == NULL) {
830 SRPT_DPRINTF_L2("ioc_port_down, I/O Controller not"
831 " active");
832 return;
833 }
834
835 /*
836 * We only have one target now, but we could go through all
837 * SCSI target ports if more are added.
838 */
839 tgt = ioc->ioc_tgt_port;
840 if (tgt == NULL) {
841 SRPT_DPRINTF_L2("ioc_port_down, no I/O Controller target"
842 " undefined");
843 return;
844 }
845 mutex_enter(&tgt->tp_lock);
846
847 /*
848 * For all channel's logged in through this port, initiate a
849 * disconnect.
850 */
851 mutex_enter(&tgt->tp_ch_list_lock);
852 ch = list_head(&tgt->tp_ch_list);
853 while (ch != NULL) {
854 next_ch = list_next(&tgt->tp_ch_list, ch);
855 if (ch->ch_session && (ch->ch_session->ss_hw_port ==
856 event->ev_port)) {
857 srpt_ch_disconnect(ch);
858 }
859 ch = next_ch;
860 }
861 mutex_exit(&tgt->tp_ch_list_lock);
862
863 tgt->tp_num_active_ports--;
864
865 /* if we have no active ports, take the target offline */
866 if ((tgt->tp_num_active_ports == 0) &&
867 (tgt->tp_state == SRPT_TGT_STATE_ONLINE)) {
868 cstatus.st_completion_status = STMF_SUCCESS;
869 cstatus.st_additional_info = "no ports active";
870 offline_target = B_TRUE;
871 }
872
873 mutex_exit(&tgt->tp_lock);
874
875 if (offline_target) {
876 stmf_status_t ret;
877
878 ret = stmf_ctl(STMF_CMD_LPORT_OFFLINE, tgt->tp_lport, &cstatus);
879
880 if (ret == STMF_SUCCESS) {
881 SRPT_DPRINTF_L1("ioc_port_down, port %d down, target "
882 "%016llx offline requested", event->ev_port,
883 (u_longlong_t)ioc->ioc_guid);
884 } else if (ret != STMF_ALREADY) {
885 SRPT_DPRINTF_L1("ioc_port_down, port %d down, target "
886 "%016llx failed offline request: %d",
887 event->ev_port,
888 (u_longlong_t)ioc->ioc_guid, (int)ret);
889 }
890 }
891 }
892
893 /*
894 * srpt_ioc_ib_async_hdlr - I/O Controller IB asynchronous events
895 */
896 /* ARGSUSED */
897 void
srpt_ioc_ib_async_hdlr(void * clnt,ibt_hca_hdl_t hdl,ibt_async_code_t code,ibt_async_event_t * event)898 srpt_ioc_ib_async_hdlr(void *clnt, ibt_hca_hdl_t hdl,
899 ibt_async_code_t code, ibt_async_event_t *event)
900 {
901 srpt_channel_t *ch;
902
903 switch (code) {
904 case IBT_EVENT_PORT_UP:
905 srpt_ioc_port_active(event);
906 break;
907
908 case IBT_ERROR_PORT_DOWN:
909 srpt_ioc_port_down(event);
910 break;
911
912 case IBT_HCA_ATTACH_EVENT:
913 SRPT_DPRINTF_L2(
914 "ib_async_hdlr, received attach event for HCA 0x%016llx",
915 (u_longlong_t)event->ev_hca_guid);
916
917 rw_enter(&srpt_ctxt->sc_rwlock, RW_WRITER);
918 srpt_ioc_attach_hca(event->ev_hca_guid, B_FALSE);
919 rw_exit(&srpt_ctxt->sc_rwlock);
920
921 break;
922
923 case IBT_HCA_DETACH_EVENT:
924 SRPT_DPRINTF_L1(
925 "ioc_iob_async_hdlr, received HCA_DETACH_EVENT for "
926 "HCA 0x%016llx",
927 (u_longlong_t)event->ev_hca_guid);
928
929 rw_enter(&srpt_ctxt->sc_rwlock, RW_WRITER);
930 srpt_ioc_detach_hca(event->ev_hca_guid);
931 rw_exit(&srpt_ctxt->sc_rwlock);
932
933 break;
934
935 case IBT_EVENT_EMPTY_CHAN:
936 /* Channel in ERROR state is now empty */
937 ch = (srpt_channel_t *)ibt_get_chan_private(event->ev_chan_hdl);
938 SRPT_DPRINTF_L3(
939 "ioc_iob_async_hdlr, received empty channel error on %p",
940 (void *)ch);
941 break;
942
943 default:
944 SRPT_DPRINTF_L2("ioc_ib_async_hdlr, event not "
945 "handled (%d)", code);
946 break;
947 }
948 }
949
950 /*
951 * srpt_ioc_svc_bind()
952 */
953 ibt_status_t
srpt_ioc_svc_bind(srpt_target_port_t * tgt,uint_t portnum)954 srpt_ioc_svc_bind(srpt_target_port_t *tgt, uint_t portnum)
955 {
956 ibt_status_t status;
957 srpt_hw_port_t *port;
958 ibt_hca_portinfo_t *portinfo;
959 uint_t qportinfo_sz;
960 uint_t qportnum;
961 ib_gid_t new_gid;
962 srpt_ioc_t *ioc;
963 srpt_session_t sess;
964
965 ASSERT(tgt != NULL);
966 ASSERT(tgt->tp_ioc != NULL);
967 ioc = tgt->tp_ioc;
968
969 if (tgt->tp_ibt_svc_hdl == NULL) {
970 SRPT_DPRINTF_L2("ioc_svc_bind, NULL SCSI target port"
971 " service");
972 return (IBT_INVALID_PARAM);
973 }
974
975 if (portnum == 0 || portnum > tgt->tp_nports) {
976 SRPT_DPRINTF_L2("ioc_svc_bind, bad port (%d)", portnum);
977 return (IBT_INVALID_PARAM);
978 }
979 status = ibt_query_hca_ports(ioc->ioc_ibt_hdl, portnum,
980 &portinfo, &qportnum, &qportinfo_sz);
981 if (status != IBT_SUCCESS) {
982 SRPT_DPRINTF_L1("ioc_svc_bind, query port error (%d)",
983 portnum);
984 return (IBT_INVALID_PARAM);
985 }
986
987 ASSERT(portinfo != NULL);
988
989 /*
990 * If port is not active do nothing, caller should attempt to bind
991 * after the port goes active.
992 */
993 if (portinfo->p_linkstate != IBT_PORT_ACTIVE) {
994 SRPT_DPRINTF_L2("ioc_svc_bind, port %d not in active state",
995 portnum);
996 ibt_free_portinfo(portinfo, qportinfo_sz);
997 return (IBT_HCA_PORT_NOT_ACTIVE);
998 }
999
1000 port = &tgt->tp_hw_port[portnum-1];
1001 new_gid = portinfo->p_sgid_tbl[0];
1002 ibt_free_portinfo(portinfo, qportinfo_sz);
1003
1004 /*
1005 * If previously bound and the port GID has changed,
1006 * unbind the old GID.
1007 */
1008 if (port->hwp_bind_hdl != NULL) {
1009 if (new_gid.gid_guid != port->hwp_gid.gid_guid ||
1010 new_gid.gid_prefix != port->hwp_gid.gid_prefix) {
1011 SRPT_DPRINTF_L2("ioc_svc_bind, unregister current"
1012 " bind");
1013 (void) ibt_unbind_service(tgt->tp_ibt_svc_hdl,
1014 port->hwp_bind_hdl);
1015 port->hwp_bind_hdl = NULL;
1016 } else {
1017 SRPT_DPRINTF_L2("ioc_svc_bind, port %d already bound",
1018 portnum);
1019 }
1020 }
1021
1022 /* bind the new port GID */
1023 if (port->hwp_bind_hdl == NULL) {
1024 SRPT_DPRINTF_L2("ioc_svc_bind, bind service, %016llx:%016llx",
1025 (u_longlong_t)new_gid.gid_prefix,
1026 (u_longlong_t)new_gid.gid_guid);
1027
1028 /*
1029 * Pass SCSI Target Port as CM private data, the target will
1030 * always exist while this service is bound.
1031 */
1032 status = ibt_bind_service(tgt->tp_ibt_svc_hdl, new_gid, NULL,
1033 tgt, &port->hwp_bind_hdl);
1034 if (status != IBT_SUCCESS && status != IBT_CM_SERVICE_EXISTS) {
1035 SRPT_DPRINTF_L1("ioc_svc_bind, bind error (%d)",
1036 status);
1037 return (status);
1038 }
1039 port->hwp_gid.gid_prefix = new_gid.gid_prefix;
1040 port->hwp_gid.gid_guid = new_gid.gid_guid;
1041 }
1042
1043 /* port is now active */
1044 tgt->tp_num_active_ports++;
1045
1046 /* setting up a transient structure for the dtrace probe. */
1047 bzero(&sess, sizeof (srpt_session_t));
1048 ALIAS_STR(sess.ss_t_gid, new_gid.gid_prefix, new_gid.gid_guid);
1049 EUI_STR(sess.ss_t_name, tgt->tp_ibt_svc_id);
1050
1051 DTRACE_SRP_1(service__up, srpt_session_t, &sess);
1052
1053 return (IBT_SUCCESS);
1054 }
1055
1056 /*
1057 * srpt_ioc_svc_unbind()
1058 */
1059 void
srpt_ioc_svc_unbind(srpt_target_port_t * tgt,uint_t portnum)1060 srpt_ioc_svc_unbind(srpt_target_port_t *tgt, uint_t portnum)
1061 {
1062 srpt_hw_port_t *port;
1063 srpt_session_t sess;
1064 ibt_status_t ret;
1065
1066 if (tgt == NULL) {
1067 SRPT_DPRINTF_L2("ioc_svc_unbind, SCSI target does not exist");
1068 return;
1069 }
1070
1071 if (portnum == 0 || portnum > tgt->tp_nports) {
1072 SRPT_DPRINTF_L2("ioc_svc_unbind, bad port (%d)", portnum);
1073 return;
1074 }
1075 port = &tgt->tp_hw_port[portnum-1];
1076
1077 /* setting up a transient structure for the dtrace probe. */
1078 bzero(&sess, sizeof (srpt_session_t));
1079 ALIAS_STR(sess.ss_t_gid, port->hwp_gid.gid_prefix,
1080 port->hwp_gid.gid_guid);
1081 EUI_STR(sess.ss_t_name, tgt->tp_ibt_svc_id);
1082
1083 DTRACE_SRP_1(service__down, srpt_session_t, &sess);
1084
1085 if (tgt->tp_ibt_svc_hdl != NULL && port->hwp_bind_hdl != NULL) {
1086 SRPT_DPRINTF_L2("ioc_svc_unbind, unregister current bind");
1087 ret = ibt_unbind_service(tgt->tp_ibt_svc_hdl,
1088 port->hwp_bind_hdl);
1089 if (ret != IBT_SUCCESS) {
1090 SRPT_DPRINTF_L1(
1091 "ioc_svc_unbind, unregister port %d failed: %d",
1092 portnum, ret);
1093 } else {
1094 port->hwp_bind_hdl = NULL;
1095 port->hwp_gid.gid_prefix = 0;
1096 port->hwp_gid.gid_guid = 0;
1097 }
1098 }
1099 }
1100
1101 /*
1102 * srpt_ioc_svc_unbind_all()
1103 */
1104 void
srpt_ioc_svc_unbind_all(srpt_target_port_t * tgt)1105 srpt_ioc_svc_unbind_all(srpt_target_port_t *tgt)
1106 {
1107 uint_t portnum;
1108
1109 if (tgt == NULL) {
1110 SRPT_DPRINTF_L2("ioc_svc_unbind_all, NULL SCSI target port"
1111 " specified");
1112 return;
1113 }
1114 for (portnum = 1; portnum <= tgt->tp_nports; portnum++) {
1115 srpt_ioc_svc_unbind(tgt, portnum);
1116 }
1117 }
1118
1119 /*
1120 * srpt_ioc_get_locked()
1121 *
1122 * Requires srpt_ctxt->rw_lock be held outside of call.
1123 */
1124 srpt_ioc_t *
srpt_ioc_get_locked(ib_guid_t guid)1125 srpt_ioc_get_locked(ib_guid_t guid)
1126 {
1127 srpt_ioc_t *ioc;
1128
1129 ioc = list_head(&srpt_ctxt->sc_ioc_list);
1130 while (ioc != NULL) {
1131 if (ioc->ioc_guid == guid) {
1132 break;
1133 }
1134 ioc = list_next(&srpt_ctxt->sc_ioc_list, ioc);
1135 }
1136 return (ioc);
1137 }
1138
1139 /*
1140 * srpt_ioc_get()
1141 */
1142 srpt_ioc_t *
srpt_ioc_get(ib_guid_t guid)1143 srpt_ioc_get(ib_guid_t guid)
1144 {
1145 srpt_ioc_t *ioc;
1146
1147 rw_enter(&srpt_ctxt->sc_rwlock, RW_READER);
1148 ioc = srpt_ioc_get_locked(guid);
1149 rw_exit(&srpt_ctxt->sc_rwlock);
1150 return (ioc);
1151 }
1152
1153 /*
1154 * srpt_ioc_post_recv_iu()
1155 */
1156 ibt_status_t
srpt_ioc_post_recv_iu(srpt_ioc_t * ioc,srpt_iu_t * iu)1157 srpt_ioc_post_recv_iu(srpt_ioc_t *ioc, srpt_iu_t *iu)
1158 {
1159 ibt_status_t status;
1160 ibt_recv_wr_t wr;
1161 uint_t posted;
1162
1163 ASSERT(ioc != NULL);
1164 ASSERT(iu != NULL);
1165
1166 wr.wr_id = (ibt_wrid_t)(uintptr_t)iu;
1167 wr.wr_nds = 1;
1168 wr.wr_sgl = &iu->iu_sge;
1169 posted = 0;
1170
1171 status = ibt_post_srq(ioc->ioc_srq_hdl, &wr, 1, &posted);
1172 if (status != IBT_SUCCESS) {
1173 SRPT_DPRINTF_L2("ioc_post_recv_iu, post error (%d)",
1174 status);
1175 }
1176 return (status);
1177 }
1178
1179 /*
1180 * srpt_ioc_repost_recv_iu()
1181 */
1182 void
srpt_ioc_repost_recv_iu(srpt_ioc_t * ioc,srpt_iu_t * iu)1183 srpt_ioc_repost_recv_iu(srpt_ioc_t *ioc, srpt_iu_t *iu)
1184 {
1185 srpt_channel_t *ch;
1186 ibt_status_t status;
1187
1188 ASSERT(iu != NULL);
1189 ASSERT(mutex_owned(&iu->iu_lock));
1190
1191 /*
1192 * Some additional sanity checks while in debug state, all STMF
1193 * related task activities should be complete prior to returning
1194 * this IU to the available pool.
1195 */
1196 ASSERT(iu->iu_stmf_task == NULL);
1197 ASSERT(iu->iu_sq_posted_cnt == 0);
1198
1199 ch = iu->iu_ch;
1200 iu->iu_ch = NULL;
1201 iu->iu_num_rdescs = 0;
1202 iu->iu_rdescs = NULL;
1203 iu->iu_tot_xfer_len = 0;
1204 iu->iu_tag = 0;
1205 iu->iu_flags = 0;
1206 iu->iu_sq_posted_cnt = 0;
1207
1208 status = srpt_ioc_post_recv_iu(ioc, iu);
1209
1210 if (status != IBT_SUCCESS) {
1211 /*
1212 * Very bad, we should initiate a shutdown of the I/O
1213 * Controller here, off-lining any targets associated
1214 * with this I/O Controller (and therefore disconnecting
1215 * any logins that remain).
1216 *
1217 * In practice this should never happen so we put
1218 * the code near the bottom of the implementation list.
1219 */
1220 SRPT_DPRINTF_L0("ioc_repost_recv_iu, error RX IU (%d)",
1221 status);
1222 ASSERT(0);
1223 } else if (ch != NULL) {
1224 atomic_inc_32(&ch->ch_req_lim_delta);
1225 }
1226 }
1227
1228 /*
1229 * srpt_ioc_init_profile()
1230 *
1231 * SRP I/O Controller serialization lock must be held when this
1232 * routine is invoked.
1233 */
1234 void
srpt_ioc_init_profile(srpt_ioc_t * ioc)1235 srpt_ioc_init_profile(srpt_ioc_t *ioc)
1236 {
1237 srpt_ioc_opcap_mask_t capmask = {0};
1238
1239 ASSERT(ioc != NULL);
1240
1241 ioc->ioc_profile.ioc_guid = h2b64(ioc->ioc_guid);
1242 (void) memcpy(ioc->ioc_profile.ioc_id_string,
1243 "Solaris SRP Target 0.9a", 23);
1244
1245 /*
1246 * Note vendor ID and subsystem ID are 24 bit values. Low order
1247 * 8 bits in vendor ID field is slot and is initialized to zero.
1248 * Low order 8 bits of subsystem ID is a reserved field and
1249 * initialized to zero.
1250 */
1251 ioc->ioc_profile.ioc_vendorid =
1252 h2b32((uint32_t)(ioc->ioc_attr.hca_vendor_id << 8));
1253 ioc->ioc_profile.ioc_deviceid =
1254 h2b32((uint32_t)ioc->ioc_attr.hca_device_id);
1255 ioc->ioc_profile.ioc_device_ver =
1256 h2b16((uint16_t)ioc->ioc_attr.hca_version_id);
1257 ioc->ioc_profile.ioc_subsys_vendorid =
1258 h2b32((uint32_t)(ioc->ioc_attr.hca_vendor_id << 8));
1259 ioc->ioc_profile.ioc_subsys_id = h2b32(0);
1260 ioc->ioc_profile.ioc_io_class = h2b16(SRP_REV_16A_IO_CLASS);
1261 ioc->ioc_profile.ioc_io_subclass = h2b16(SRP_IO_SUBCLASS);
1262 ioc->ioc_profile.ioc_protocol = h2b16(SRP_PROTOCOL);
1263 ioc->ioc_profile.ioc_protocol_ver = h2b16(SRP_PROTOCOL_VERSION);
1264 ioc->ioc_profile.ioc_send_msg_qdepth = h2b16(srpt_send_msg_depth);
1265 ioc->ioc_profile.ioc_rdma_read_qdepth =
1266 ioc->ioc_attr.hca_max_rdma_out_chan;
1267 ioc->ioc_profile.ioc_send_msg_sz = h2b32(srpt_iu_size);
1268 ioc->ioc_profile.ioc_rdma_xfer_sz = h2b32(SRPT_DEFAULT_MAX_RDMA_SIZE);
1269
1270 capmask.bits.st = 1; /* Messages can be sent to IOC */
1271 capmask.bits.sf = 1; /* Messages can be sent from IOC */
1272 capmask.bits.rf = 1; /* RDMA Reads can be sent from IOC */
1273 capmask.bits.wf = 1; /* RDMA Writes can be sent from IOC */
1274 ioc->ioc_profile.ioc_ctrl_opcap_mask = capmask.mask;
1275
1276 /*
1277 * We currently only have one target, but if we had a list we would
1278 * go through that list and only count those that are ONLINE when
1279 * setting the services count and entries.
1280 */
1281 if (ioc->ioc_tgt_port->tp_srp_enabled) {
1282 ioc->ioc_profile.ioc_service_entries = 1;
1283 ioc->ioc_svc.srv_id = h2b64(ioc->ioc_guid);
1284 (void) snprintf((char *)ioc->ioc_svc.srv_name,
1285 IB_DM_MAX_SVC_NAME_LEN, "SRP.T10:%016llx",
1286 (u_longlong_t)ioc->ioc_guid);
1287 } else {
1288 ioc->ioc_profile.ioc_service_entries = 0;
1289 ioc->ioc_svc.srv_id = 0;
1290 }
1291 }
1292
1293 /*
1294 * srpt_ioc_ds_alloc_dbuf()
1295 */
1296 /* ARGSUSED */
1297 stmf_data_buf_t *
srpt_ioc_ds_alloc_dbuf(struct scsi_task * task,uint32_t size,uint32_t * pminsize,uint32_t flags)1298 srpt_ioc_ds_alloc_dbuf(struct scsi_task *task, uint32_t size,
1299 uint32_t *pminsize, uint32_t flags)
1300 {
1301 srpt_iu_t *iu;
1302 srpt_ioc_t *ioc;
1303 srpt_ds_dbuf_t *dbuf;
1304 stmf_data_buf_t *stmf_dbuf;
1305 void *buf;
1306 srpt_mr_t mr;
1307
1308 ASSERT(task != NULL);
1309 iu = task->task_port_private;
1310 ioc = iu->iu_ioc;
1311
1312 SRPT_DPRINTF_L4("ioc_ds_alloc_dbuf, invoked ioc(%p)"
1313 " size(%d), flags(%x)",
1314 (void *)ioc, size, flags);
1315
1316 buf = srpt_vmem_alloc(ioc->ioc_dbuf_pool, size);
1317 if (buf == NULL) {
1318 return (NULL);
1319 }
1320
1321 if (srpt_vmem_mr(ioc->ioc_dbuf_pool, buf, size, &mr) != 0) {
1322 goto stmf_alloc_err;
1323 }
1324
1325 stmf_dbuf = stmf_alloc(STMF_STRUCT_DATA_BUF, sizeof (srpt_ds_dbuf_t),
1326 0);
1327 if (stmf_dbuf == NULL) {
1328 SRPT_DPRINTF_L2("ioc_ds_alloc_dbuf, stmf_alloc failed");
1329 goto stmf_alloc_err;
1330 }
1331
1332 dbuf = stmf_dbuf->db_port_private;
1333 dbuf->db_stmf_buf = stmf_dbuf;
1334 dbuf->db_mr_hdl = mr.mr_hdl;
1335 dbuf->db_ioc = ioc;
1336 dbuf->db_sge.ds_va = mr.mr_va;
1337 dbuf->db_sge.ds_key = mr.mr_lkey;
1338 dbuf->db_sge.ds_len = size;
1339
1340 stmf_dbuf->db_buf_size = size;
1341 stmf_dbuf->db_data_size = size;
1342 stmf_dbuf->db_relative_offset = 0;
1343 stmf_dbuf->db_flags = 0;
1344 stmf_dbuf->db_xfer_status = 0;
1345 stmf_dbuf->db_sglist_length = 1;
1346 stmf_dbuf->db_sglist[0].seg_addr = buf;
1347 stmf_dbuf->db_sglist[0].seg_length = size;
1348
1349 return (stmf_dbuf);
1350
1351 buf_mr_err:
1352 stmf_free(stmf_dbuf);
1353
1354 stmf_alloc_err:
1355 srpt_vmem_free(ioc->ioc_dbuf_pool, buf, size);
1356
1357 return (NULL);
1358 }
1359
1360 void
srpt_ioc_ds_free_dbuf(struct stmf_dbuf_store * ds,stmf_data_buf_t * dbuf)1361 srpt_ioc_ds_free_dbuf(struct stmf_dbuf_store *ds,
1362 stmf_data_buf_t *dbuf)
1363 {
1364 srpt_ioc_t *ioc;
1365
1366 SRPT_DPRINTF_L4("ioc_ds_free_dbuf, invoked buf (%p)",
1367 (void *)dbuf);
1368 ioc = ds->ds_port_private;
1369
1370 srpt_vmem_free(ioc->ioc_dbuf_pool, dbuf->db_sglist[0].seg_addr,
1371 dbuf->db_buf_size);
1372 stmf_free(dbuf);
1373 }
1374
1375 /* Memory arena routines */
1376
1377 static srpt_vmem_pool_t *
srpt_vmem_create(const char * name,srpt_ioc_t * ioc,ib_memlen_t chunksize,uint64_t maxsize,ibt_mr_flags_t flags)1378 srpt_vmem_create(const char *name, srpt_ioc_t *ioc, ib_memlen_t chunksize,
1379 uint64_t maxsize, ibt_mr_flags_t flags)
1380 {
1381 srpt_mr_t *chunk;
1382 srpt_vmem_pool_t *result;
1383
1384 ASSERT(chunksize <= maxsize);
1385
1386 result = kmem_zalloc(sizeof (srpt_vmem_pool_t), KM_SLEEP);
1387
1388 result->svp_ioc = ioc;
1389 result->svp_chunksize = chunksize;
1390 result->svp_max_size = maxsize;
1391 result->svp_flags = flags;
1392
1393 rw_init(&result->svp_lock, NULL, RW_DRIVER, NULL);
1394 avl_create(&result->svp_mr_list, srpt_vmem_mr_compare,
1395 sizeof (srpt_mr_t), offsetof(srpt_mr_t, mr_avl));
1396
1397 chunk = srpt_vmem_chunk_alloc(result, chunksize);
1398
1399 avl_add(&result->svp_mr_list, chunk);
1400 result->svp_total_size = chunksize;
1401
1402 result->svp_vmem = vmem_create(name,
1403 (void*)(uintptr_t)chunk->mr_va,
1404 (size_t)chunk->mr_len, SRPT_MR_QUANTSIZE,
1405 NULL, NULL, NULL, 0, VM_SLEEP);
1406
1407 return (result);
1408 }
1409
1410 static void
srpt_vmem_destroy(srpt_vmem_pool_t * vm_pool)1411 srpt_vmem_destroy(srpt_vmem_pool_t *vm_pool)
1412 {
1413 srpt_mr_t *chunk;
1414 srpt_mr_t *next;
1415
1416 rw_enter(&vm_pool->svp_lock, RW_WRITER);
1417 vmem_destroy(vm_pool->svp_vmem);
1418
1419 chunk = avl_first(&vm_pool->svp_mr_list);
1420
1421 while (chunk != NULL) {
1422 next = AVL_NEXT(&vm_pool->svp_mr_list, chunk);
1423 avl_remove(&vm_pool->svp_mr_list, chunk);
1424 srpt_vmem_chunk_free(vm_pool, chunk);
1425 chunk = next;
1426 }
1427
1428 avl_destroy(&vm_pool->svp_mr_list);
1429
1430 rw_exit(&vm_pool->svp_lock);
1431 rw_destroy(&vm_pool->svp_lock);
1432
1433 kmem_free(vm_pool, sizeof (srpt_vmem_pool_t));
1434 }
1435
1436 static void *
srpt_vmem_alloc(srpt_vmem_pool_t * vm_pool,size_t size)1437 srpt_vmem_alloc(srpt_vmem_pool_t *vm_pool, size_t size)
1438 {
1439 void *result;
1440 srpt_mr_t *next;
1441 ib_memlen_t chunklen;
1442
1443 ASSERT(vm_pool != NULL);
1444
1445 result = vmem_alloc(vm_pool->svp_vmem, size,
1446 VM_NOSLEEP | VM_FIRSTFIT);
1447
1448 if (result != NULL) {
1449 /* memory successfully allocated */
1450 return (result);
1451 }
1452
1453 /* need more vmem */
1454 rw_enter(&vm_pool->svp_lock, RW_WRITER);
1455 chunklen = vm_pool->svp_chunksize;
1456
1457 if (vm_pool->svp_total_size >= vm_pool->svp_max_size) {
1458 /* no more room to alloc */
1459 rw_exit(&vm_pool->svp_lock);
1460 return (NULL);
1461 }
1462
1463 if ((vm_pool->svp_total_size + chunklen) > vm_pool->svp_max_size) {
1464 chunklen = vm_pool->svp_max_size - vm_pool->svp_total_size;
1465 }
1466
1467 next = srpt_vmem_chunk_alloc(vm_pool, chunklen);
1468 if (next != NULL) {
1469 /*
1470 * Note that the size of the chunk we got
1471 * may not be the size we requested. Use the
1472 * length returned in the chunk itself.
1473 */
1474 if (vmem_add(vm_pool->svp_vmem, (void*)(uintptr_t)next->mr_va,
1475 next->mr_len, VM_NOSLEEP) == NULL) {
1476 srpt_vmem_chunk_free(vm_pool, next);
1477 SRPT_DPRINTF_L2("vmem_add failed");
1478 } else {
1479 vm_pool->svp_total_size += next->mr_len;
1480 avl_add(&vm_pool->svp_mr_list, next);
1481 }
1482 }
1483
1484 rw_exit(&vm_pool->svp_lock);
1485
1486 result = vmem_alloc(vm_pool->svp_vmem, size, VM_NOSLEEP | VM_FIRSTFIT);
1487
1488 return (result);
1489 }
1490
1491 static void
srpt_vmem_free(srpt_vmem_pool_t * vm_pool,void * vaddr,size_t size)1492 srpt_vmem_free(srpt_vmem_pool_t *vm_pool, void *vaddr, size_t size)
1493 {
1494 vmem_free(vm_pool->svp_vmem, vaddr, size);
1495 }
1496
1497 static int
srpt_vmem_mr(srpt_vmem_pool_t * vm_pool,void * vaddr,size_t size,srpt_mr_t * mr)1498 srpt_vmem_mr(srpt_vmem_pool_t *vm_pool, void *vaddr, size_t size,
1499 srpt_mr_t *mr)
1500 {
1501 avl_index_t where;
1502 ib_vaddr_t mrva = (ib_vaddr_t)(uintptr_t)vaddr;
1503 srpt_mr_t chunk;
1504 srpt_mr_t *nearest;
1505 ib_vaddr_t chunk_end;
1506 int status = DDI_FAILURE;
1507
1508 rw_enter(&vm_pool->svp_lock, RW_READER);
1509
1510 chunk.mr_va = mrva;
1511 nearest = avl_find(&vm_pool->svp_mr_list, &chunk, &where);
1512
1513 if (nearest == NULL) {
1514 nearest = avl_nearest(&vm_pool->svp_mr_list, where,
1515 AVL_BEFORE);
1516 }
1517
1518 if (nearest != NULL) {
1519 /* Verify this chunk contains the specified address range */
1520 ASSERT(nearest->mr_va <= mrva);
1521
1522 chunk_end = nearest->mr_va + nearest->mr_len;
1523 if (chunk_end >= mrva + size) {
1524 mr->mr_hdl = nearest->mr_hdl;
1525 mr->mr_va = mrva;
1526 mr->mr_len = size;
1527 mr->mr_lkey = nearest->mr_lkey;
1528 mr->mr_rkey = nearest->mr_rkey;
1529 status = DDI_SUCCESS;
1530 }
1531 }
1532
1533 rw_exit(&vm_pool->svp_lock);
1534 return (status);
1535 }
1536
1537 static srpt_mr_t *
srpt_vmem_chunk_alloc(srpt_vmem_pool_t * vm_pool,ib_memlen_t chunksize)1538 srpt_vmem_chunk_alloc(srpt_vmem_pool_t *vm_pool, ib_memlen_t chunksize)
1539 {
1540 void *chunk = NULL;
1541 srpt_mr_t *result = NULL;
1542
1543 while ((chunk == NULL) && (chunksize >= SRPT_MIN_CHUNKSIZE)) {
1544 chunk = kmem_alloc(chunksize, KM_NOSLEEP);
1545 if (chunk == NULL) {
1546 SRPT_DPRINTF_L2("srpt_vmem_chunk_alloc: "
1547 "failed to alloc chunk of %d, trying %d",
1548 (int)chunksize, (int)chunksize/2);
1549 chunksize /= 2;
1550 }
1551 }
1552
1553 if (chunk != NULL) {
1554 result = srpt_reg_mem(vm_pool, (ib_vaddr_t)(uintptr_t)chunk,
1555 chunksize);
1556 if (result == NULL) {
1557 SRPT_DPRINTF_L2("srpt_vmem_chunk_alloc: "
1558 "chunk registration failed");
1559 kmem_free(chunk, chunksize);
1560 }
1561 }
1562
1563 return (result);
1564 }
1565
1566 static void
srpt_vmem_chunk_free(srpt_vmem_pool_t * vm_pool,srpt_mr_t * mr)1567 srpt_vmem_chunk_free(srpt_vmem_pool_t *vm_pool, srpt_mr_t *mr)
1568 {
1569 void *chunk = (void *)(uintptr_t)mr->mr_va;
1570 ib_memlen_t chunksize = mr->mr_len;
1571
1572 srpt_dereg_mem(vm_pool->svp_ioc, mr);
1573 kmem_free(chunk, chunksize);
1574 }
1575
1576 static srpt_mr_t *
srpt_reg_mem(srpt_vmem_pool_t * vm_pool,ib_vaddr_t vaddr,ib_memlen_t len)1577 srpt_reg_mem(srpt_vmem_pool_t *vm_pool, ib_vaddr_t vaddr, ib_memlen_t len)
1578 {
1579 srpt_mr_t *result = NULL;
1580 ibt_mr_attr_t mr_attr;
1581 ibt_mr_desc_t mr_desc;
1582 ibt_status_t status;
1583 srpt_ioc_t *ioc = vm_pool->svp_ioc;
1584
1585 result = kmem_zalloc(sizeof (srpt_mr_t), KM_NOSLEEP);
1586 if (result == NULL) {
1587 SRPT_DPRINTF_L2("srpt_reg_mem: failed to allocate");
1588 return (NULL);
1589 }
1590
1591 bzero(&mr_attr, sizeof (ibt_mr_attr_t));
1592 bzero(&mr_desc, sizeof (ibt_mr_desc_t));
1593
1594 mr_attr.mr_vaddr = vaddr;
1595 mr_attr.mr_len = len;
1596 mr_attr.mr_as = NULL;
1597 mr_attr.mr_flags = vm_pool->svp_flags;
1598
1599 status = ibt_register_mr(ioc->ioc_ibt_hdl, ioc->ioc_pd_hdl,
1600 &mr_attr, &result->mr_hdl, &mr_desc);
1601 if (status != IBT_SUCCESS) {
1602 SRPT_DPRINTF_L2("srpt_reg_mem: ibt_register_mr "
1603 "failed %d", status);
1604 kmem_free(result, sizeof (srpt_mr_t));
1605 return (NULL);
1606 }
1607
1608 result->mr_va = mr_attr.mr_vaddr;
1609 result->mr_len = mr_attr.mr_len;
1610 result->mr_lkey = mr_desc.md_lkey;
1611 result->mr_rkey = mr_desc.md_rkey;
1612
1613 return (result);
1614 }
1615
1616 static void
srpt_dereg_mem(srpt_ioc_t * ioc,srpt_mr_t * mr)1617 srpt_dereg_mem(srpt_ioc_t *ioc, srpt_mr_t *mr)
1618 {
1619 ibt_status_t status;
1620
1621 status = ibt_deregister_mr(ioc->ioc_ibt_hdl, mr->mr_hdl);
1622 if (status != IBT_SUCCESS) {
1623 SRPT_DPRINTF_L1("srpt_dereg_mem, error deregistering MR (%d)",
1624 status);
1625 }
1626 kmem_free(mr, sizeof (srpt_mr_t));
1627 }
1628
1629 static int
srpt_vmem_mr_compare(const void * a,const void * b)1630 srpt_vmem_mr_compare(const void *a, const void *b)
1631 {
1632 srpt_mr_t *mr1 = (srpt_mr_t *)a;
1633 srpt_mr_t *mr2 = (srpt_mr_t *)b;
1634
1635 /* sort and match by virtual address */
1636 if (mr1->mr_va < mr2->mr_va) {
1637 return (-1);
1638 } else if (mr1->mr_va > mr2->mr_va) {
1639 return (1);
1640 }
1641
1642 return (0);
1643 }
1644