11bdd6c0eSSue Gleeson /*
21bdd6c0eSSue Gleeson * CDDL HEADER START
31bdd6c0eSSue Gleeson *
41bdd6c0eSSue Gleeson * The contents of this file are subject to the terms of the
51bdd6c0eSSue Gleeson * Common Development and Distribution License (the "License").
61bdd6c0eSSue Gleeson * You may not use this file except in compliance with the License.
71bdd6c0eSSue Gleeson *
81bdd6c0eSSue Gleeson * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91bdd6c0eSSue Gleeson * or http://www.opensolaris.org/os/licensing.
101bdd6c0eSSue Gleeson * See the License for the specific language governing permissions
111bdd6c0eSSue Gleeson * and limitations under the License.
121bdd6c0eSSue Gleeson *
131bdd6c0eSSue Gleeson * When distributing Covered Code, include this CDDL HEADER in each
141bdd6c0eSSue Gleeson * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151bdd6c0eSSue Gleeson * If applicable, add the following below this CDDL HEADER, with the
161bdd6c0eSSue Gleeson * fields enclosed by brackets "[]" replaced with your own identifying
171bdd6c0eSSue Gleeson * information: Portions Copyright [yyyy] [name of copyright owner]
181bdd6c0eSSue Gleeson *
191bdd6c0eSSue Gleeson * CDDL HEADER END
201bdd6c0eSSue Gleeson */
211bdd6c0eSSue Gleeson
221bdd6c0eSSue Gleeson /*
23c3a558e7SSue Gleeson * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
241bdd6c0eSSue Gleeson */
251bdd6c0eSSue Gleeson
261bdd6c0eSSue Gleeson /*
271bdd6c0eSSue Gleeson * I/O Controller functions for the Solaris COMSTAR SCSI RDMA Protocol
281bdd6c0eSSue Gleeson * Target (SRPT) port provider.
291bdd6c0eSSue Gleeson */
301bdd6c0eSSue Gleeson
311bdd6c0eSSue Gleeson #include <sys/types.h>
321bdd6c0eSSue Gleeson #include <sys/ddi.h>
331bdd6c0eSSue Gleeson #include <sys/types.h>
341bdd6c0eSSue Gleeson #include <sys/sunddi.h>
351bdd6c0eSSue Gleeson #include <sys/atomic.h>
361bdd6c0eSSue Gleeson #include <sys/sysmacros.h>
371bdd6c0eSSue Gleeson #include <sys/ib/ibtl/ibti.h>
38191c289bSCharles Ting #include <sys/sdt.h>
391bdd6c0eSSue Gleeson
401bdd6c0eSSue Gleeson #include "srp.h"
411bdd6c0eSSue Gleeson #include "srpt_impl.h"
421bdd6c0eSSue Gleeson #include "srpt_ioc.h"
431bdd6c0eSSue Gleeson #include "srpt_stp.h"
441bdd6c0eSSue Gleeson #include "srpt_ch.h"
45c3a558e7SSue Gleeson #include "srpt_common.h"
461bdd6c0eSSue Gleeson
471bdd6c0eSSue Gleeson /*
481bdd6c0eSSue Gleeson * srpt_ioc_srq_size - Tunable parameter that specifies the number
491bdd6c0eSSue Gleeson * of receive WQ entries that can be posted to the IOC shared
501bdd6c0eSSue Gleeson * receive queue.
511bdd6c0eSSue Gleeson */
52c3a558e7SSue Gleeson uint32_t srpt_ioc_srq_size = SRPT_DEFAULT_IOC_SRQ_SIZE;
53c3a558e7SSue Gleeson extern uint16_t srpt_send_msg_depth;
54c3a558e7SSue Gleeson extern uint32_t srpt_iu_size;
55c3a558e7SSue Gleeson extern boolean_t srpt_enable_by_default;
561bdd6c0eSSue Gleeson
571bdd6c0eSSue Gleeson /* IOC profile capabilities mask must be big-endian */
581bdd6c0eSSue Gleeson typedef struct srpt_ioc_opcap_bits_s {
591bdd6c0eSSue Gleeson #if defined(_BIT_FIELDS_LTOH)
601bdd6c0eSSue Gleeson uint8_t af:1,
611bdd6c0eSSue Gleeson at:1,
621bdd6c0eSSue Gleeson wf:1,
631bdd6c0eSSue Gleeson wt:1,
641bdd6c0eSSue Gleeson rf:1,
651bdd6c0eSSue Gleeson rt:1,
661bdd6c0eSSue Gleeson sf:1,
671bdd6c0eSSue Gleeson st:1;
681bdd6c0eSSue Gleeson #elif defined(_BIT_FIELDS_HTOL)
691bdd6c0eSSue Gleeson uint8_t st:1,
701bdd6c0eSSue Gleeson sf:1,
711bdd6c0eSSue Gleeson rt:1,
721bdd6c0eSSue Gleeson rf:1,
731bdd6c0eSSue Gleeson wt:1,
741bdd6c0eSSue Gleeson wf:1,
751bdd6c0eSSue Gleeson at:1,
761bdd6c0eSSue Gleeson af:1;
771bdd6c0eSSue Gleeson #else
781bdd6c0eSSue Gleeson #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
791bdd6c0eSSue Gleeson #endif
801bdd6c0eSSue Gleeson } srpt_ioc_opcap_bits_t;
811bdd6c0eSSue Gleeson
821bdd6c0eSSue Gleeson typedef union {
831bdd6c0eSSue Gleeson srpt_ioc_opcap_bits_t bits;
841bdd6c0eSSue Gleeson uint8_t mask;
851bdd6c0eSSue Gleeson } srpt_ioc_opcap_mask_t;
861bdd6c0eSSue Gleeson
871bdd6c0eSSue Gleeson /*
881bdd6c0eSSue Gleeson * vmem arena variables - values derived from iSER
891bdd6c0eSSue Gleeson */
901bdd6c0eSSue Gleeson #define SRPT_MR_QUANTSIZE 0x400 /* 1K */
911bdd6c0eSSue Gleeson #define SRPT_MIN_CHUNKSIZE 0x100000 /* 1MB */
921bdd6c0eSSue Gleeson
931bdd6c0eSSue Gleeson /* use less memory on 32-bit kernels as it's much more constrained */
941bdd6c0eSSue Gleeson #ifdef _LP64
951bdd6c0eSSue Gleeson #define SRPT_BUF_MR_CHUNKSIZE 0x1000000 /* 16MB */
961bdd6c0eSSue Gleeson #define SRPT_BUF_POOL_MAX 0x40000000 /* 1GB */
971bdd6c0eSSue Gleeson #else
981bdd6c0eSSue Gleeson #define SRPT_BUF_MR_CHUNKSIZE 0x400000 /* 4MB */
991bdd6c0eSSue Gleeson #define SRPT_BUF_POOL_MAX 0x4000000 /* 64MB */
1001bdd6c0eSSue Gleeson #endif
1011bdd6c0eSSue Gleeson
1021bdd6c0eSSue Gleeson static ibt_mr_flags_t srpt_dbuf_mr_flags =
1031bdd6c0eSSue Gleeson IBT_MR_ENABLE_LOCAL_WRITE | IBT_MR_ENABLE_REMOTE_WRITE |
1041bdd6c0eSSue Gleeson IBT_MR_ENABLE_REMOTE_READ;
1051bdd6c0eSSue Gleeson
1061bdd6c0eSSue Gleeson void srpt_ioc_ib_async_hdlr(void *clnt, ibt_hca_hdl_t hdl,
1071bdd6c0eSSue Gleeson ibt_async_code_t code, ibt_async_event_t *event);
1081bdd6c0eSSue Gleeson
1091bdd6c0eSSue Gleeson static struct ibt_clnt_modinfo_s srpt_ibt_modinfo = {
1101bdd6c0eSSue Gleeson IBTI_V_CURR,
1111bdd6c0eSSue Gleeson IBT_STORAGE_DEV,
1121bdd6c0eSSue Gleeson srpt_ioc_ib_async_hdlr,
1131bdd6c0eSSue Gleeson NULL,
1141bdd6c0eSSue Gleeson "srpt"
1151bdd6c0eSSue Gleeson };
1161bdd6c0eSSue Gleeson
1171bdd6c0eSSue Gleeson static srpt_ioc_t *srpt_ioc_init(ib_guid_t guid);
1181bdd6c0eSSue Gleeson static void srpt_ioc_fini(srpt_ioc_t *ioc);
119c3a558e7SSue Gleeson static boolean_t srpt_check_hca_cfg_enabled(ib_guid_t hca_guid);
1201bdd6c0eSSue Gleeson
1211bdd6c0eSSue Gleeson static srpt_vmem_pool_t *srpt_vmem_create(const char *name, srpt_ioc_t *ioc,
1221bdd6c0eSSue Gleeson ib_memlen_t chunksize, uint64_t maxsize, ibt_mr_flags_t flags);
1231bdd6c0eSSue Gleeson static void *srpt_vmem_alloc(srpt_vmem_pool_t *vm_pool, size_t size);
1241bdd6c0eSSue Gleeson static int srpt_vmem_mr_compare(const void *a, const void *b);
1251bdd6c0eSSue Gleeson static srpt_mr_t *srpt_vmem_chunk_alloc(srpt_vmem_pool_t *ioc,
1261bdd6c0eSSue Gleeson ib_memlen_t chunksize);
1271bdd6c0eSSue Gleeson static void srpt_vmem_destroy(srpt_vmem_pool_t *vm_pool);
1281bdd6c0eSSue Gleeson static void srpt_vmem_free(srpt_vmem_pool_t *vm_pool, void *vaddr, size_t size);
1291bdd6c0eSSue Gleeson static srpt_mr_t *srpt_reg_mem(srpt_vmem_pool_t *vm_pool, ib_vaddr_t vaddr,
1301bdd6c0eSSue Gleeson ib_memlen_t len);
1311bdd6c0eSSue Gleeson static void srpt_vmem_chunk_free(srpt_vmem_pool_t *vm_pool, srpt_mr_t *mr);
1321bdd6c0eSSue Gleeson static void srpt_dereg_mem(srpt_ioc_t *ioc, srpt_mr_t *mr);
1331bdd6c0eSSue Gleeson static int srpt_vmem_mr(srpt_vmem_pool_t *vm_pool, void *vaddr, size_t size,
1341bdd6c0eSSue Gleeson srpt_mr_t *mr);
1351bdd6c0eSSue Gleeson
1361bdd6c0eSSue Gleeson /*
1371bdd6c0eSSue Gleeson * srpt_ioc_attach() - I/O Controller attach
1381bdd6c0eSSue Gleeson *
1391bdd6c0eSSue Gleeson * Attach to IBTF and initialize I/O controllers. The srpt_ctxt->sc_rwlock
1401bdd6c0eSSue Gleeson * should be held outside of this call.
1411bdd6c0eSSue Gleeson */
1421bdd6c0eSSue Gleeson int
srpt_ioc_attach()1431bdd6c0eSSue Gleeson srpt_ioc_attach()
1441bdd6c0eSSue Gleeson {
1451bdd6c0eSSue Gleeson int status;
1461bdd6c0eSSue Gleeson int hca_cnt;
1471bdd6c0eSSue Gleeson int hca_ndx;
1481bdd6c0eSSue Gleeson ib_guid_t *guid;
1491bdd6c0eSSue Gleeson
1501bdd6c0eSSue Gleeson ASSERT(srpt_ctxt != NULL);
1511bdd6c0eSSue Gleeson
1521bdd6c0eSSue Gleeson /*
1531bdd6c0eSSue Gleeson * Attach to IBTF and initialize a list of IB devices. Each
1541bdd6c0eSSue Gleeson * HCA will be represented by an I/O Controller.
1551bdd6c0eSSue Gleeson */
1561bdd6c0eSSue Gleeson status = ibt_attach(&srpt_ibt_modinfo, srpt_ctxt->sc_dip,
1571bdd6c0eSSue Gleeson srpt_ctxt, &srpt_ctxt->sc_ibt_hdl);
1581bdd6c0eSSue Gleeson if (status != DDI_SUCCESS) {
1591bdd6c0eSSue Gleeson SRPT_DPRINTF_L1("ioc_attach, ibt_attach failed (0x%x)",
1601bdd6c0eSSue Gleeson status);
1611bdd6c0eSSue Gleeson return (DDI_FAILURE);
1621bdd6c0eSSue Gleeson }
1631bdd6c0eSSue Gleeson
1641bdd6c0eSSue Gleeson hca_cnt = ibt_get_hca_list(&guid);
1651bdd6c0eSSue Gleeson if (hca_cnt < 1) {
166168665f7SSue Gleeson /*
167168665f7SSue Gleeson * not a fatal error. Service will be up and
168168665f7SSue Gleeson * waiting for ATTACH events.
169168665f7SSue Gleeson */
1701bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("ioc_attach, no HCA found");
171168665f7SSue Gleeson return (DDI_SUCCESS);
1721bdd6c0eSSue Gleeson }
1731bdd6c0eSSue Gleeson
1741bdd6c0eSSue Gleeson for (hca_ndx = 0; hca_ndx < hca_cnt; hca_ndx++) {
175c3a558e7SSue Gleeson SRPT_DPRINTF_L2("ioc_attach, attaching HCA %016llx",
176c3a558e7SSue Gleeson (u_longlong_t)guid[hca_ndx]);
177c3a558e7SSue Gleeson srpt_ioc_attach_hca(guid[hca_ndx], B_FALSE);
1781bdd6c0eSSue Gleeson }
1791bdd6c0eSSue Gleeson
1801bdd6c0eSSue Gleeson ibt_free_hca_list(guid, hca_cnt);
1811bdd6c0eSSue Gleeson SRPT_DPRINTF_L3("ioc_attach, added %d I/O Controller(s)",
1821bdd6c0eSSue Gleeson srpt_ctxt->sc_num_iocs);
1831bdd6c0eSSue Gleeson return (DDI_SUCCESS);
1841bdd6c0eSSue Gleeson }
1851bdd6c0eSSue Gleeson
186c3a558e7SSue Gleeson /*
187c3a558e7SSue Gleeson * Initialize I/O Controllers. sprt_ctxt->sc_rwlock must be locked by the
188c3a558e7SSue Gleeson * caller.
189c3a558e7SSue Gleeson *
190c3a558e7SSue Gleeson * 'checked' indicates no need to lookup the hca in the HCA configuration
191c3a558e7SSue Gleeson * list.
192c3a558e7SSue Gleeson */
193c3a558e7SSue Gleeson void
srpt_ioc_attach_hca(ib_guid_t hca_guid,boolean_t checked)194c3a558e7SSue Gleeson srpt_ioc_attach_hca(ib_guid_t hca_guid, boolean_t checked)
195c3a558e7SSue Gleeson {
196c3a558e7SSue Gleeson boolean_t enable_hca = B_TRUE;
197c3a558e7SSue Gleeson srpt_ioc_t *ioc;
198c3a558e7SSue Gleeson
199c3a558e7SSue Gleeson if (!checked) {
200c3a558e7SSue Gleeson enable_hca = srpt_check_hca_cfg_enabled(hca_guid);
201c3a558e7SSue Gleeson
202c3a558e7SSue Gleeson if (!enable_hca) {
203c3a558e7SSue Gleeson /* nothing to do */
204c3a558e7SSue Gleeson SRPT_DPRINTF_L2(
205c3a558e7SSue Gleeson "ioc_attach_hca, HCA %016llx disabled "
206c3a558e7SSue Gleeson "by srpt config",
207c3a558e7SSue Gleeson (u_longlong_t)hca_guid);
208c3a558e7SSue Gleeson return;
209c3a558e7SSue Gleeson }
210c3a558e7SSue Gleeson }
211c3a558e7SSue Gleeson
212c3a558e7SSue Gleeson SRPT_DPRINTF_L2("ioc_attach_hca, adding I/O"
213c3a558e7SSue Gleeson " Controller (%016llx)", (u_longlong_t)hca_guid);
214c3a558e7SSue Gleeson
215c3a558e7SSue Gleeson ioc = srpt_ioc_init(hca_guid);
216c3a558e7SSue Gleeson if (ioc == NULL) {
217c3a558e7SSue Gleeson /*
218c3a558e7SSue Gleeson * IOC already exists or an error occurred. Already
219c3a558e7SSue Gleeson * logged by srpt_ioc_init()
220c3a558e7SSue Gleeson */
221c3a558e7SSue Gleeson return;
222c3a558e7SSue Gleeson }
223c3a558e7SSue Gleeson
224c3a558e7SSue Gleeson /*
225c3a558e7SSue Gleeson * Create the COMSTAR SRP Target for this IOC. If this fails,
226c3a558e7SSue Gleeson * remove the IOC.
227c3a558e7SSue Gleeson */
228c3a558e7SSue Gleeson rw_enter(&ioc->ioc_rwlock, RW_WRITER);
229c3a558e7SSue Gleeson ioc->ioc_tgt_port = srpt_stp_alloc_port(ioc, ioc->ioc_guid);
230c3a558e7SSue Gleeson if (ioc->ioc_tgt_port == NULL) {
231c3a558e7SSue Gleeson SRPT_DPRINTF_L1("ioc_attach_hca: alloc SCSI"
232c3a558e7SSue Gleeson " Target Port error on GUID(%016llx)",
233c3a558e7SSue Gleeson (u_longlong_t)ioc->ioc_guid);
234c3a558e7SSue Gleeson rw_exit(&ioc->ioc_rwlock);
235c3a558e7SSue Gleeson srpt_ioc_fini(ioc);
236c3a558e7SSue Gleeson return;
237c3a558e7SSue Gleeson }
238c3a558e7SSue Gleeson rw_exit(&ioc->ioc_rwlock);
239c3a558e7SSue Gleeson
240c3a558e7SSue Gleeson /*
241c3a558e7SSue Gleeson * New HCA added with default SCSI Target Port, SRP service
242c3a558e7SSue Gleeson * will be started when SCSI Target Port is brought
243c3a558e7SSue Gleeson * on-line by STMF.
244c3a558e7SSue Gleeson */
245c3a558e7SSue Gleeson list_insert_tail(&srpt_ctxt->sc_ioc_list, ioc);
246c3a558e7SSue Gleeson SRPT_DPRINTF_L2("ioc_attach_hca, I/O Controller ibt HCA hdl (%p)",
247c3a558e7SSue Gleeson (void *)ioc->ioc_ibt_hdl);
248c3a558e7SSue Gleeson
249c3a558e7SSue Gleeson srpt_ctxt->sc_num_iocs++;
250c3a558e7SSue Gleeson }
251c3a558e7SSue Gleeson
252c3a558e7SSue Gleeson /*
253c3a558e7SSue Gleeson * srpt_check_hca_cfg_enabled()
254c3a558e7SSue Gleeson *
255c3a558e7SSue Gleeson * Function to check the configuration for the enabled status of a given
256c3a558e7SSue Gleeson * HCA. Returns B_TRUE if SRPT services should be activated for this HCA,
257c3a558e7SSue Gleeson * B_FALSE if it should be disabled.
258c3a558e7SSue Gleeson */
259c3a558e7SSue Gleeson static boolean_t
srpt_check_hca_cfg_enabled(ib_guid_t hca_guid)260c3a558e7SSue Gleeson srpt_check_hca_cfg_enabled(ib_guid_t hca_guid)
261c3a558e7SSue Gleeson {
262c3a558e7SSue Gleeson int status;
263c3a558e7SSue Gleeson char buf[32];
264c3a558e7SSue Gleeson nvlist_t *hcanv;
265c3a558e7SSue Gleeson boolean_t enable_hca;
266c3a558e7SSue Gleeson
267c3a558e7SSue Gleeson enable_hca = srpt_enable_by_default;
268c3a558e7SSue Gleeson
269c3a558e7SSue Gleeson SRPT_FORMAT_HCAKEY(buf, sizeof (buf), (u_longlong_t)hca_guid);
270c3a558e7SSue Gleeson
271c3a558e7SSue Gleeson if (srpt_ctxt->sc_cfg_hca_nv != NULL) {
272c3a558e7SSue Gleeson status = nvlist_lookup_nvlist(srpt_ctxt->sc_cfg_hca_nv,
273c3a558e7SSue Gleeson buf, &hcanv);
274c3a558e7SSue Gleeson if (status == 0) {
275c3a558e7SSue Gleeson SRPT_DPRINTF_L3("check_hca_cfg, found guid %s", buf);
276c3a558e7SSue Gleeson (void) nvlist_lookup_boolean_value(hcanv,
277c3a558e7SSue Gleeson SRPT_PROP_ENABLED, &enable_hca);
278c3a558e7SSue Gleeson } else {
279c3a558e7SSue Gleeson SRPT_DPRINTF_L3("check_hca_cfg, did not find guid %s",
280c3a558e7SSue Gleeson buf);
281c3a558e7SSue Gleeson }
282c3a558e7SSue Gleeson }
283c3a558e7SSue Gleeson
284c3a558e7SSue Gleeson return (enable_hca);
285c3a558e7SSue Gleeson }
286c3a558e7SSue Gleeson
287c3a558e7SSue Gleeson /*
288c3a558e7SSue Gleeson * srpt_ioc_update()
289c3a558e7SSue Gleeson *
290c3a558e7SSue Gleeson * Using the configuration nvlist, enables or disables SRP services
291c3a558e7SSue Gleeson * the provided HCAs. srpt_ctxt->sc_rwlock should be held outside of this call.
292c3a558e7SSue Gleeson */
293c3a558e7SSue Gleeson void
srpt_ioc_update(void)294c3a558e7SSue Gleeson srpt_ioc_update(void)
295c3a558e7SSue Gleeson {
296c3a558e7SSue Gleeson boolean_t enabled;
297c3a558e7SSue Gleeson nvpair_t *nvp = NULL;
298c3a558e7SSue Gleeson uint64_t hca_guid;
299c3a558e7SSue Gleeson nvlist_t *nvl;
300c3a558e7SSue Gleeson nvlist_t *cfg = srpt_ctxt->sc_cfg_hca_nv;
301c3a558e7SSue Gleeson
302c3a558e7SSue Gleeson if (cfg == NULL) {
303c3a558e7SSue Gleeson SRPT_DPRINTF_L2("ioc_update, no configuration data");
304c3a558e7SSue Gleeson return;
305c3a558e7SSue Gleeson }
306c3a558e7SSue Gleeson
307c3a558e7SSue Gleeson while ((nvp = nvlist_next_nvpair(cfg, nvp)) != NULL) {
308c3a558e7SSue Gleeson enabled = srpt_enable_by_default;
309c3a558e7SSue Gleeson
310c3a558e7SSue Gleeson if ((nvpair_value_nvlist(nvp, &nvl)) != 0) {
311c3a558e7SSue Gleeson SRPT_DPRINTF_L2("ioc_update, did not find an nvlist");
312c3a558e7SSue Gleeson continue;
313c3a558e7SSue Gleeson }
314c3a558e7SSue Gleeson
315c3a558e7SSue Gleeson if ((nvlist_lookup_uint64(nvl, SRPT_PROP_GUID, &hca_guid))
316c3a558e7SSue Gleeson != 0) {
317c3a558e7SSue Gleeson SRPT_DPRINTF_L2("ioc_update, did not find a guid");
318c3a558e7SSue Gleeson continue;
319c3a558e7SSue Gleeson }
320c3a558e7SSue Gleeson
321c3a558e7SSue Gleeson (void) nvlist_lookup_boolean_value(nvl, SRPT_PROP_ENABLED,
322c3a558e7SSue Gleeson &enabled);
323c3a558e7SSue Gleeson
324c3a558e7SSue Gleeson if (enabled) {
325c3a558e7SSue Gleeson SRPT_DPRINTF_L2("ioc_update, enabling guid %016llx",
326c3a558e7SSue Gleeson (u_longlong_t)hca_guid);
327c3a558e7SSue Gleeson srpt_ioc_attach_hca(hca_guid, B_TRUE);
328c3a558e7SSue Gleeson } else {
329c3a558e7SSue Gleeson SRPT_DPRINTF_L2("ioc_update, disabling guid %016llx",
330c3a558e7SSue Gleeson (u_longlong_t)hca_guid);
331c3a558e7SSue Gleeson srpt_ioc_detach_hca(hca_guid);
332c3a558e7SSue Gleeson }
333c3a558e7SSue Gleeson }
334c3a558e7SSue Gleeson }
335c3a558e7SSue Gleeson
3361bdd6c0eSSue Gleeson /*
3371bdd6c0eSSue Gleeson * srpt_ioc_detach() - I/O Controller detach
3381bdd6c0eSSue Gleeson *
3391bdd6c0eSSue Gleeson * srpt_ctxt->sc_rwlock should be held outside of this call.
3401bdd6c0eSSue Gleeson */
3411bdd6c0eSSue Gleeson void
srpt_ioc_detach()3421bdd6c0eSSue Gleeson srpt_ioc_detach()
3431bdd6c0eSSue Gleeson {
3441bdd6c0eSSue Gleeson srpt_ioc_t *ioc;
3451bdd6c0eSSue Gleeson
346c3a558e7SSue Gleeson /*
347c3a558e7SSue Gleeson * All SRP targets must be destroyed before calling this
348c3a558e7SSue Gleeson * function.
349c3a558e7SSue Gleeson */
3501bdd6c0eSSue Gleeson while ((ioc = list_head(&srpt_ctxt->sc_ioc_list)) != NULL) {
3511bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("ioc_detach, removing I/O Controller(%p)"
3521bdd6c0eSSue Gleeson " (%016llx), ibt_hdl(%p)",
3531bdd6c0eSSue Gleeson (void *)ioc,
3541bdd6c0eSSue Gleeson ioc ? (u_longlong_t)ioc->ioc_guid : 0x0ll,
3551bdd6c0eSSue Gleeson (void *)ioc->ioc_ibt_hdl);
356c3a558e7SSue Gleeson
357c3a558e7SSue Gleeson list_remove(&srpt_ctxt->sc_ioc_list, ioc);
3581bdd6c0eSSue Gleeson srpt_ioc_fini(ioc);
359c3a558e7SSue Gleeson srpt_ctxt->sc_num_iocs--;
3601bdd6c0eSSue Gleeson }
3611bdd6c0eSSue Gleeson
3621bdd6c0eSSue Gleeson srpt_ctxt->sc_ibt_hdl = NULL;
3631bdd6c0eSSue Gleeson }
3641bdd6c0eSSue Gleeson
365c3a558e7SSue Gleeson /*
366c3a558e7SSue Gleeson * srpt_ioc_detach_hca()
367c3a558e7SSue Gleeson *
368c3a558e7SSue Gleeson * Stop SRP Target services on this HCA
369c3a558e7SSue Gleeson *
370c3a558e7SSue Gleeson * Note that this is not entirely synchronous with srpt_ioc_attach_hca()
371c3a558e7SSue Gleeson * in that we don't need to check the configuration to know whether to
372c3a558e7SSue Gleeson * disable an HCA. We get here either because the IB framework has told
373c3a558e7SSue Gleeson * us the HCA has been detached, or because the administrator has explicitly
374c3a558e7SSue Gleeson * disabled this HCA.
375c3a558e7SSue Gleeson *
376c3a558e7SSue Gleeson * Must be called with srpt_ctxt->sc_rwlock locked as RW_WRITER.
377c3a558e7SSue Gleeson */
378c3a558e7SSue Gleeson void
srpt_ioc_detach_hca(ib_guid_t hca_guid)379c3a558e7SSue Gleeson srpt_ioc_detach_hca(ib_guid_t hca_guid)
380c3a558e7SSue Gleeson {
381c3a558e7SSue Gleeson srpt_ioc_t *ioc;
382c3a558e7SSue Gleeson srpt_target_port_t *tgt;
383c3a558e7SSue Gleeson stmf_status_t stmf_status = STMF_SUCCESS;
384c3a558e7SSue Gleeson
385c3a558e7SSue Gleeson ioc = srpt_ioc_get_locked(hca_guid);
386c3a558e7SSue Gleeson if (ioc == NULL) {
387c3a558e7SSue Gleeson /* doesn't exist, nothing to do */
388c3a558e7SSue Gleeson return;
389c3a558e7SSue Gleeson }
390c3a558e7SSue Gleeson
391c3a558e7SSue Gleeson rw_enter(&ioc->ioc_rwlock, RW_WRITER);
392c3a558e7SSue Gleeson tgt = ioc->ioc_tgt_port;
393c3a558e7SSue Gleeson
394c3a558e7SSue Gleeson if (tgt != NULL) {
395c3a558e7SSue Gleeson stmf_status = srpt_stp_destroy_port(tgt);
396c3a558e7SSue Gleeson if (stmf_status == STMF_SUCCESS) {
397c3a558e7SSue Gleeson ioc->ioc_tgt_port = NULL;
398c3a558e7SSue Gleeson (void) srpt_stp_free_port(tgt);
399c3a558e7SSue Gleeson }
400c3a558e7SSue Gleeson }
401c3a558e7SSue Gleeson
402c3a558e7SSue Gleeson rw_exit(&ioc->ioc_rwlock);
403c3a558e7SSue Gleeson
404c3a558e7SSue Gleeson if (stmf_status != STMF_SUCCESS) {
405c3a558e7SSue Gleeson /* should never happen */
406c3a558e7SSue Gleeson return;
407c3a558e7SSue Gleeson }
408c3a558e7SSue Gleeson
409c3a558e7SSue Gleeson list_remove(&srpt_ctxt->sc_ioc_list, ioc);
410c3a558e7SSue Gleeson srpt_ctxt->sc_num_iocs--;
411c3a558e7SSue Gleeson
412c3a558e7SSue Gleeson srpt_ioc_fini(ioc);
413c3a558e7SSue Gleeson SRPT_DPRINTF_L2("ioc_detach_hca, HCA %016llx detached",
414c3a558e7SSue Gleeson (u_longlong_t)hca_guid);
415c3a558e7SSue Gleeson }
416c3a558e7SSue Gleeson
4171bdd6c0eSSue Gleeson /*
4181bdd6c0eSSue Gleeson * srpt_ioc_init() - I/O Controller initialization
4191bdd6c0eSSue Gleeson *
4201bdd6c0eSSue Gleeson * Requires srpt_ctxt->rw_lock be held outside of call.
4211bdd6c0eSSue Gleeson */
4221bdd6c0eSSue Gleeson static srpt_ioc_t *
srpt_ioc_init(ib_guid_t guid)4231bdd6c0eSSue Gleeson srpt_ioc_init(ib_guid_t guid)
4241bdd6c0eSSue Gleeson {
4251bdd6c0eSSue Gleeson ibt_status_t status;
4261bdd6c0eSSue Gleeson srpt_ioc_t *ioc;
4271bdd6c0eSSue Gleeson ibt_hca_attr_t hca_attr;
4281bdd6c0eSSue Gleeson uint_t iu_ndx;
4291bdd6c0eSSue Gleeson uint_t err_ndx;
4301bdd6c0eSSue Gleeson ibt_mr_attr_t mr_attr;
4311bdd6c0eSSue Gleeson ibt_mr_desc_t mr_desc;
4321bdd6c0eSSue Gleeson srpt_iu_t *iu;
4331bdd6c0eSSue Gleeson ibt_srq_sizes_t srq_attr;
4341bdd6c0eSSue Gleeson char namebuf[32];
4351bdd6c0eSSue Gleeson size_t iu_offset;
436989ca640SSue Gleeson uint_t srq_sz;
4371bdd6c0eSSue Gleeson
4381bdd6c0eSSue Gleeson status = ibt_query_hca_byguid(guid, &hca_attr);
4391bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
4401bdd6c0eSSue Gleeson SRPT_DPRINTF_L1("ioc_init, HCA query error (%d)",
4411bdd6c0eSSue Gleeson status);
4421bdd6c0eSSue Gleeson return (NULL);
4431bdd6c0eSSue Gleeson }
4441bdd6c0eSSue Gleeson
4451bdd6c0eSSue Gleeson ioc = srpt_ioc_get_locked(guid);
4461bdd6c0eSSue Gleeson if (ioc != NULL) {
447c3a558e7SSue Gleeson SRPT_DPRINTF_L2("ioc_init, HCA already exists");
4481bdd6c0eSSue Gleeson return (NULL);
4491bdd6c0eSSue Gleeson }
4501bdd6c0eSSue Gleeson
4511bdd6c0eSSue Gleeson ioc = kmem_zalloc(sizeof (srpt_ioc_t), KM_SLEEP);
4521bdd6c0eSSue Gleeson
4531bdd6c0eSSue Gleeson rw_init(&ioc->ioc_rwlock, NULL, RW_DRIVER, NULL);
4541bdd6c0eSSue Gleeson rw_enter(&ioc->ioc_rwlock, RW_WRITER);
4551bdd6c0eSSue Gleeson
4561bdd6c0eSSue Gleeson bcopy(&hca_attr, &ioc->ioc_attr, sizeof (ibt_hca_attr_t));
4571bdd6c0eSSue Gleeson
4581bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("ioc_init, HCA max mr=%d, mrlen=%lld",
4591bdd6c0eSSue Gleeson hca_attr.hca_max_memr, (u_longlong_t)hca_attr.hca_max_memr_len);
4601bdd6c0eSSue Gleeson ioc->ioc_guid = guid;
4611bdd6c0eSSue Gleeson
4621bdd6c0eSSue Gleeson status = ibt_open_hca(srpt_ctxt->sc_ibt_hdl, guid, &ioc->ioc_ibt_hdl);
4631bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
4641bdd6c0eSSue Gleeson SRPT_DPRINTF_L1("ioc_init, IBT open failed (%d)", status);
4651bdd6c0eSSue Gleeson goto hca_open_err;
4661bdd6c0eSSue Gleeson }
4671bdd6c0eSSue Gleeson
4681bdd6c0eSSue Gleeson status = ibt_alloc_pd(ioc->ioc_ibt_hdl, IBT_PD_NO_FLAGS,
4691bdd6c0eSSue Gleeson &ioc->ioc_pd_hdl);
4701bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
4711bdd6c0eSSue Gleeson SRPT_DPRINTF_L1("ioc_init, IBT create PD failed (%d)", status);
4721bdd6c0eSSue Gleeson goto pd_alloc_err;
4731bdd6c0eSSue Gleeson }
4741bdd6c0eSSue Gleeson
4751bdd6c0eSSue Gleeson /*
4761bdd6c0eSSue Gleeson * We require hardware support for SRQs. We use a common SRQ to
4771bdd6c0eSSue Gleeson * reduce channel memory consumption.
4781bdd6c0eSSue Gleeson */
4791bdd6c0eSSue Gleeson if ((ioc->ioc_attr.hca_flags & IBT_HCA_SRQ) == 0) {
480989ca640SSue Gleeson SRPT_DPRINTF_L0(
481989ca640SSue Gleeson "ioc_init, no SRQ capability, HCA not supported");
4821bdd6c0eSSue Gleeson goto srq_alloc_err;
4831bdd6c0eSSue Gleeson }
4841bdd6c0eSSue Gleeson
4851bdd6c0eSSue Gleeson SRPT_DPRINTF_L3("ioc_init, Using shared receive queues, max srq work"
4861bdd6c0eSSue Gleeson " queue size(%d), def size = %d", ioc->ioc_attr.hca_max_srqs_sz,
4871bdd6c0eSSue Gleeson srpt_ioc_srq_size);
488989ca640SSue Gleeson srq_sz = srq_attr.srq_wr_sz = min(srpt_ioc_srq_size,
489989ca640SSue Gleeson ioc->ioc_attr.hca_max_srqs_sz) - 1;
4901bdd6c0eSSue Gleeson srq_attr.srq_sgl_sz = 1;
4911bdd6c0eSSue Gleeson
4921bdd6c0eSSue Gleeson status = ibt_alloc_srq(ioc->ioc_ibt_hdl, IBT_SRQ_NO_FLAGS,
4931bdd6c0eSSue Gleeson ioc->ioc_pd_hdl, &srq_attr, &ioc->ioc_srq_hdl,
4941bdd6c0eSSue Gleeson &ioc->ioc_srq_attr);
4951bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
4961bdd6c0eSSue Gleeson SRPT_DPRINTF_L1("ioc_init, IBT create SRQ failed(%d)", status);
4971bdd6c0eSSue Gleeson goto srq_alloc_err;
4981bdd6c0eSSue Gleeson }
4991bdd6c0eSSue Gleeson
500989ca640SSue Gleeson SRPT_DPRINTF_L2("ioc_init, Using SRQ size(%d), MAX SG size(%d)",
501989ca640SSue Gleeson srq_sz, 1);
5021bdd6c0eSSue Gleeson
5031bdd6c0eSSue Gleeson ibt_set_srq_private(ioc->ioc_srq_hdl, ioc);
5041bdd6c0eSSue Gleeson
5051bdd6c0eSSue Gleeson /*
5061bdd6c0eSSue Gleeson * Allocate a pool of SRP IU message buffers and post them to
5071bdd6c0eSSue Gleeson * the I/O Controller SRQ. We let the SRQ manage the free IU
5081bdd6c0eSSue Gleeson * messages.
5091bdd6c0eSSue Gleeson */
510989ca640SSue Gleeson ioc->ioc_num_iu_entries = srq_sz;
5111bdd6c0eSSue Gleeson
5121bdd6c0eSSue Gleeson ioc->ioc_iu_pool = kmem_zalloc(sizeof (srpt_iu_t) *
5131bdd6c0eSSue Gleeson ioc->ioc_num_iu_entries, KM_SLEEP);
5141bdd6c0eSSue Gleeson
515989ca640SSue Gleeson ioc->ioc_iu_bufs = kmem_alloc(srpt_iu_size *
5161bdd6c0eSSue Gleeson ioc->ioc_num_iu_entries, KM_SLEEP);
5171bdd6c0eSSue Gleeson
5181bdd6c0eSSue Gleeson if ((ioc->ioc_iu_pool == NULL) || (ioc->ioc_iu_bufs == NULL)) {
5191bdd6c0eSSue Gleeson SRPT_DPRINTF_L1("ioc_init, failed to allocate SRQ IUs");
5201bdd6c0eSSue Gleeson goto srq_iu_alloc_err;
5211bdd6c0eSSue Gleeson }
5221bdd6c0eSSue Gleeson
5231bdd6c0eSSue Gleeson mr_attr.mr_vaddr = (ib_vaddr_t)(uintptr_t)ioc->ioc_iu_bufs;
524989ca640SSue Gleeson mr_attr.mr_len = srpt_iu_size * ioc->ioc_num_iu_entries;
5251bdd6c0eSSue Gleeson mr_attr.mr_as = NULL;
5261bdd6c0eSSue Gleeson mr_attr.mr_flags = IBT_MR_ENABLE_LOCAL_WRITE;
5271bdd6c0eSSue Gleeson
5281bdd6c0eSSue Gleeson status = ibt_register_mr(ioc->ioc_ibt_hdl, ioc->ioc_pd_hdl,
5291bdd6c0eSSue Gleeson &mr_attr, &ioc->ioc_iu_mr_hdl, &mr_desc);
5301bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
5311bdd6c0eSSue Gleeson SRPT_DPRINTF_L1("ioc_init, IU buffer pool MR err(%d)",
5321bdd6c0eSSue Gleeson status);
5331bdd6c0eSSue Gleeson goto srq_iu_alloc_err;
5341bdd6c0eSSue Gleeson }
5351bdd6c0eSSue Gleeson
5361bdd6c0eSSue Gleeson for (iu_ndx = 0, iu = ioc->ioc_iu_pool; iu_ndx <
5371bdd6c0eSSue Gleeson ioc->ioc_num_iu_entries; iu_ndx++, iu++) {
5381bdd6c0eSSue Gleeson
539989ca640SSue Gleeson iu_offset = (iu_ndx * srpt_iu_size);
5401bdd6c0eSSue Gleeson iu->iu_buf = (void *)((uintptr_t)ioc->ioc_iu_bufs + iu_offset);
5411bdd6c0eSSue Gleeson
5421bdd6c0eSSue Gleeson mutex_init(&iu->iu_lock, NULL, MUTEX_DRIVER, NULL);
5431bdd6c0eSSue Gleeson
5441bdd6c0eSSue Gleeson iu->iu_sge.ds_va = mr_desc.md_vaddr + iu_offset;
5451bdd6c0eSSue Gleeson iu->iu_sge.ds_key = mr_desc.md_lkey;
546989ca640SSue Gleeson iu->iu_sge.ds_len = srpt_iu_size;
5471bdd6c0eSSue Gleeson iu->iu_ioc = ioc;
5481bdd6c0eSSue Gleeson iu->iu_pool_ndx = iu_ndx;
5491bdd6c0eSSue Gleeson
5501bdd6c0eSSue Gleeson status = srpt_ioc_post_recv_iu(ioc, &ioc->ioc_iu_pool[iu_ndx]);
5511bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
5521bdd6c0eSSue Gleeson SRPT_DPRINTF_L1("ioc_init, SRQ IU post err(%d)",
5531bdd6c0eSSue Gleeson status);
5541bdd6c0eSSue Gleeson goto srq_iu_post_err;
5551bdd6c0eSSue Gleeson }
5561bdd6c0eSSue Gleeson }
5571bdd6c0eSSue Gleeson
5581bdd6c0eSSue Gleeson /*
5591bdd6c0eSSue Gleeson * Initialize the dbuf vmem arena
5601bdd6c0eSSue Gleeson */
5611bdd6c0eSSue Gleeson (void) snprintf(namebuf, sizeof (namebuf),
5621bdd6c0eSSue Gleeson "srpt_buf_pool_%16llX", (u_longlong_t)guid);
5631bdd6c0eSSue Gleeson ioc->ioc_dbuf_pool = srpt_vmem_create(namebuf, ioc,
5641bdd6c0eSSue Gleeson SRPT_BUF_MR_CHUNKSIZE, SRPT_BUF_POOL_MAX, srpt_dbuf_mr_flags);
5651bdd6c0eSSue Gleeson
5661bdd6c0eSSue Gleeson if (ioc->ioc_dbuf_pool == NULL) {
5671bdd6c0eSSue Gleeson goto stmf_db_alloc_err;
5681bdd6c0eSSue Gleeson }
5691bdd6c0eSSue Gleeson
5701bdd6c0eSSue Gleeson /*
5711bdd6c0eSSue Gleeson * Allocate the I/O Controller STMF data buffer allocator. The
5721bdd6c0eSSue Gleeson * data store will span all targets associated with this IOC.
5731bdd6c0eSSue Gleeson */
5741bdd6c0eSSue Gleeson ioc->ioc_stmf_ds = stmf_alloc(STMF_STRUCT_DBUF_STORE, 0, 0);
5751bdd6c0eSSue Gleeson if (ioc->ioc_stmf_ds == NULL) {
5761bdd6c0eSSue Gleeson SRPT_DPRINTF_L1("ioc_attach, STMF DBUF alloc failure for IOC");
5771bdd6c0eSSue Gleeson goto stmf_db_alloc_err;
5781bdd6c0eSSue Gleeson }
5791bdd6c0eSSue Gleeson ioc->ioc_stmf_ds->ds_alloc_data_buf = &srpt_ioc_ds_alloc_dbuf;
5801bdd6c0eSSue Gleeson ioc->ioc_stmf_ds->ds_free_data_buf = &srpt_ioc_ds_free_dbuf;
5811bdd6c0eSSue Gleeson ioc->ioc_stmf_ds->ds_port_private = ioc;
5821bdd6c0eSSue Gleeson
5831bdd6c0eSSue Gleeson rw_exit(&ioc->ioc_rwlock);
5841bdd6c0eSSue Gleeson return (ioc);
5851bdd6c0eSSue Gleeson
5861bdd6c0eSSue Gleeson stmf_db_alloc_err:
5871bdd6c0eSSue Gleeson if (ioc->ioc_dbuf_pool != NULL) {
5881bdd6c0eSSue Gleeson srpt_vmem_destroy(ioc->ioc_dbuf_pool);
5891bdd6c0eSSue Gleeson }
5901bdd6c0eSSue Gleeson
5911bdd6c0eSSue Gleeson srq_iu_post_err:
5921bdd6c0eSSue Gleeson if (ioc->ioc_iu_mr_hdl != NULL) {
5931bdd6c0eSSue Gleeson status = ibt_deregister_mr(ioc->ioc_ibt_hdl,
5941bdd6c0eSSue Gleeson ioc->ioc_iu_mr_hdl);
5951bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
5961bdd6c0eSSue Gleeson SRPT_DPRINTF_L1("ioc_init, error deregistering"
5971bdd6c0eSSue Gleeson " memory region (%d)", status);
5981bdd6c0eSSue Gleeson }
5991bdd6c0eSSue Gleeson }
6001bdd6c0eSSue Gleeson for (err_ndx = 0, iu = ioc->ioc_iu_pool; err_ndx < iu_ndx;
6011bdd6c0eSSue Gleeson err_ndx++, iu++) {
6021bdd6c0eSSue Gleeson mutex_destroy(&iu->iu_lock);
6031bdd6c0eSSue Gleeson }
6041bdd6c0eSSue Gleeson
6051bdd6c0eSSue Gleeson srq_iu_alloc_err:
6061bdd6c0eSSue Gleeson if (ioc->ioc_iu_bufs != NULL) {
607989ca640SSue Gleeson kmem_free(ioc->ioc_iu_bufs, srpt_iu_size *
6081bdd6c0eSSue Gleeson ioc->ioc_num_iu_entries);
6091bdd6c0eSSue Gleeson }
6101bdd6c0eSSue Gleeson if (ioc->ioc_iu_pool != NULL) {
6111bdd6c0eSSue Gleeson kmem_free(ioc->ioc_iu_pool,
6121bdd6c0eSSue Gleeson sizeof (srpt_iu_t) * ioc->ioc_num_iu_entries);
6131bdd6c0eSSue Gleeson }
6141bdd6c0eSSue Gleeson if (ioc->ioc_srq_hdl != NULL) {
6151bdd6c0eSSue Gleeson status = ibt_free_srq(ioc->ioc_srq_hdl);
6161bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
6171bdd6c0eSSue Gleeson SRPT_DPRINTF_L1("ioc_init, error freeing SRQ (%d)",
6181bdd6c0eSSue Gleeson status);
6191bdd6c0eSSue Gleeson }
6201bdd6c0eSSue Gleeson
6211bdd6c0eSSue Gleeson }
6221bdd6c0eSSue Gleeson
6231bdd6c0eSSue Gleeson srq_alloc_err:
6241bdd6c0eSSue Gleeson status = ibt_free_pd(ioc->ioc_ibt_hdl, ioc->ioc_pd_hdl);
6251bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
6261bdd6c0eSSue Gleeson SRPT_DPRINTF_L1("ioc_init, free PD error (%d)", status);
6271bdd6c0eSSue Gleeson }
6281bdd6c0eSSue Gleeson
6291bdd6c0eSSue Gleeson pd_alloc_err:
6301bdd6c0eSSue Gleeson status = ibt_close_hca(ioc->ioc_ibt_hdl);
6311bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
6321bdd6c0eSSue Gleeson SRPT_DPRINTF_L1("ioc_init, close ioc error (%d)", status);
6331bdd6c0eSSue Gleeson }
6341bdd6c0eSSue Gleeson
6351bdd6c0eSSue Gleeson hca_open_err:
6361bdd6c0eSSue Gleeson rw_exit(&ioc->ioc_rwlock);
6371bdd6c0eSSue Gleeson rw_destroy(&ioc->ioc_rwlock);
6381bdd6c0eSSue Gleeson kmem_free(ioc, sizeof (*ioc));
6391bdd6c0eSSue Gleeson return (NULL);
6401bdd6c0eSSue Gleeson }
6411bdd6c0eSSue Gleeson
6421bdd6c0eSSue Gleeson /*
6431bdd6c0eSSue Gleeson * srpt_ioc_fini() - I/O Controller Cleanup
6441bdd6c0eSSue Gleeson *
6451bdd6c0eSSue Gleeson * Requires srpt_ctxt->sc_rwlock be held outside of call.
6461bdd6c0eSSue Gleeson */
6471bdd6c0eSSue Gleeson static void
srpt_ioc_fini(srpt_ioc_t * ioc)6481bdd6c0eSSue Gleeson srpt_ioc_fini(srpt_ioc_t *ioc)
6491bdd6c0eSSue Gleeson {
6501bdd6c0eSSue Gleeson int status;
6511bdd6c0eSSue Gleeson int ndx;
6521bdd6c0eSSue Gleeson
6531bdd6c0eSSue Gleeson /*
6541bdd6c0eSSue Gleeson * Note driver flows will have already taken all SRP
6551bdd6c0eSSue Gleeson * services running on the I/O Controller off-line.
6561bdd6c0eSSue Gleeson */
657*b1d7ec75SPeter Cudhea - Oracle Corporation - Burlington, MA United States ASSERT(ioc->ioc_tgt_port == NULL);
6581bdd6c0eSSue Gleeson rw_enter(&ioc->ioc_rwlock, RW_WRITER);
6591bdd6c0eSSue Gleeson if (ioc->ioc_ibt_hdl != NULL) {
6601bdd6c0eSSue Gleeson if (ioc->ioc_stmf_ds != NULL) {
6611bdd6c0eSSue Gleeson stmf_free(ioc->ioc_stmf_ds);
6621bdd6c0eSSue Gleeson }
6631bdd6c0eSSue Gleeson
6641bdd6c0eSSue Gleeson if (ioc->ioc_srq_hdl != NULL) {
6651bdd6c0eSSue Gleeson SRPT_DPRINTF_L4("ioc_fini, freeing SRQ");
6661bdd6c0eSSue Gleeson status = ibt_free_srq(ioc->ioc_srq_hdl);
6671bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
6681bdd6c0eSSue Gleeson SRPT_DPRINTF_L1("ioc_fini, free SRQ"
6691bdd6c0eSSue Gleeson " error (%d)", status);
6701bdd6c0eSSue Gleeson }
6711bdd6c0eSSue Gleeson }
6721bdd6c0eSSue Gleeson
6731bdd6c0eSSue Gleeson if (ioc->ioc_iu_mr_hdl != NULL) {
6741bdd6c0eSSue Gleeson status = ibt_deregister_mr(
6751bdd6c0eSSue Gleeson ioc->ioc_ibt_hdl, ioc->ioc_iu_mr_hdl);
6761bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
6771bdd6c0eSSue Gleeson SRPT_DPRINTF_L1("ioc_fini, error deregistering"
6781bdd6c0eSSue Gleeson " memory region (%d)", status);
6791bdd6c0eSSue Gleeson }
6801bdd6c0eSSue Gleeson }
6811bdd6c0eSSue Gleeson
6821bdd6c0eSSue Gleeson if (ioc->ioc_iu_bufs != NULL) {
683989ca640SSue Gleeson kmem_free(ioc->ioc_iu_bufs, srpt_iu_size *
6841bdd6c0eSSue Gleeson ioc->ioc_num_iu_entries);
6851bdd6c0eSSue Gleeson }
6861bdd6c0eSSue Gleeson
6871bdd6c0eSSue Gleeson if (ioc->ioc_iu_pool != NULL) {
6881bdd6c0eSSue Gleeson SRPT_DPRINTF_L4("ioc_fini, freeing IU entries");
6891bdd6c0eSSue Gleeson for (ndx = 0; ndx < ioc->ioc_num_iu_entries; ndx++) {
6901bdd6c0eSSue Gleeson mutex_destroy(&ioc->ioc_iu_pool[ndx].iu_lock);
6911bdd6c0eSSue Gleeson }
6921bdd6c0eSSue Gleeson
6931bdd6c0eSSue Gleeson SRPT_DPRINTF_L4("ioc_fini, free IU pool struct");
6941bdd6c0eSSue Gleeson kmem_free(ioc->ioc_iu_pool,
6951bdd6c0eSSue Gleeson sizeof (srpt_iu_t) * (ioc->ioc_num_iu_entries));
6961bdd6c0eSSue Gleeson ioc->ioc_iu_pool = NULL;
6971bdd6c0eSSue Gleeson ioc->ioc_num_iu_entries = 0;
6981bdd6c0eSSue Gleeson }
6991bdd6c0eSSue Gleeson
7001bdd6c0eSSue Gleeson if (ioc->ioc_dbuf_pool != NULL) {
7011bdd6c0eSSue Gleeson srpt_vmem_destroy(ioc->ioc_dbuf_pool);
7021bdd6c0eSSue Gleeson }
7031bdd6c0eSSue Gleeson
7041bdd6c0eSSue Gleeson if (ioc->ioc_pd_hdl != NULL) {
7051bdd6c0eSSue Gleeson status = ibt_free_pd(ioc->ioc_ibt_hdl,
7061bdd6c0eSSue Gleeson ioc->ioc_pd_hdl);
7071bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
7081bdd6c0eSSue Gleeson SRPT_DPRINTF_L1("ioc_fini, free PD"
7091bdd6c0eSSue Gleeson " error (%d)", status);
7101bdd6c0eSSue Gleeson }
7111bdd6c0eSSue Gleeson }
7121bdd6c0eSSue Gleeson
7131bdd6c0eSSue Gleeson status = ibt_close_hca(ioc->ioc_ibt_hdl);
7141bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
7151bdd6c0eSSue Gleeson SRPT_DPRINTF_L1(
7161bdd6c0eSSue Gleeson "ioc_fini, close ioc error (%d)", status);
7171bdd6c0eSSue Gleeson }
7181bdd6c0eSSue Gleeson }
7191bdd6c0eSSue Gleeson rw_exit(&ioc->ioc_rwlock);
7201bdd6c0eSSue Gleeson rw_destroy(&ioc->ioc_rwlock);
7211bdd6c0eSSue Gleeson kmem_free(ioc, sizeof (srpt_ioc_t));
7221bdd6c0eSSue Gleeson }
7231bdd6c0eSSue Gleeson
7241bdd6c0eSSue Gleeson /*
7251bdd6c0eSSue Gleeson * srpt_ioc_port_active() - I/O Controller port active
7261bdd6c0eSSue Gleeson */
7271bdd6c0eSSue Gleeson static void
srpt_ioc_port_active(ibt_async_event_t * event)7281bdd6c0eSSue Gleeson srpt_ioc_port_active(ibt_async_event_t *event)
7291bdd6c0eSSue Gleeson {
7301bdd6c0eSSue Gleeson ibt_status_t status;
7311bdd6c0eSSue Gleeson srpt_ioc_t *ioc;
7323baa0db4SSue Gleeson srpt_target_port_t *tgt = NULL;
7333baa0db4SSue Gleeson boolean_t online_target = B_FALSE;
7343baa0db4SSue Gleeson stmf_change_status_t cstatus;
7351bdd6c0eSSue Gleeson
7361bdd6c0eSSue Gleeson ASSERT(event != NULL);
7371bdd6c0eSSue Gleeson
7381bdd6c0eSSue Gleeson SRPT_DPRINTF_L3("ioc_port_active event handler, invoked");
7391bdd6c0eSSue Gleeson
7401bdd6c0eSSue Gleeson /*
7411bdd6c0eSSue Gleeson * Find the HCA in question and if the HCA has completed
7421bdd6c0eSSue Gleeson * initialization, and the SRP Target service for the
7431bdd6c0eSSue Gleeson * the I/O Controller exists, then bind this port.
7441bdd6c0eSSue Gleeson */
7451bdd6c0eSSue Gleeson ioc = srpt_ioc_get(event->ev_hca_guid);
7461bdd6c0eSSue Gleeson
7471bdd6c0eSSue Gleeson if (ioc == NULL) {
7481bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("ioc_port_active, I/O Controller not"
7491bdd6c0eSSue Gleeson " active");
7501bdd6c0eSSue Gleeson return;
7511bdd6c0eSSue Gleeson }
7521bdd6c0eSSue Gleeson
7533baa0db4SSue Gleeson tgt = ioc->ioc_tgt_port;
7543baa0db4SSue Gleeson if (tgt == NULL) {
7551bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("ioc_port_active, no I/O Controller target"
7561bdd6c0eSSue Gleeson " undefined");
7571bdd6c0eSSue Gleeson return;
7581bdd6c0eSSue Gleeson }
7591bdd6c0eSSue Gleeson
7601bdd6c0eSSue Gleeson
7611bdd6c0eSSue Gleeson /*
7621bdd6c0eSSue Gleeson * We take the target lock here to serialize this operation
7631bdd6c0eSSue Gleeson * with any STMF initiated target state transitions. If
7641bdd6c0eSSue Gleeson * SRP is off-line then the service handle is NULL.
7651bdd6c0eSSue Gleeson */
7663baa0db4SSue Gleeson mutex_enter(&tgt->tp_lock);
7671bdd6c0eSSue Gleeson
7683baa0db4SSue Gleeson if (tgt->tp_ibt_svc_hdl != NULL) {
7693baa0db4SSue Gleeson status = srpt_ioc_svc_bind(tgt, event->ev_port);
7703baa0db4SSue Gleeson if ((status != IBT_SUCCESS) &&
7713baa0db4SSue Gleeson (status != IBT_HCA_PORT_NOT_ACTIVE)) {
7721bdd6c0eSSue Gleeson SRPT_DPRINTF_L1("ioc_port_active, bind failed (%d)",
7731bdd6c0eSSue Gleeson status);
7741bdd6c0eSSue Gleeson }
7753baa0db4SSue Gleeson } else {
7763baa0db4SSue Gleeson /* if we were offline because of no ports, try onlining now */
7773baa0db4SSue Gleeson if ((tgt->tp_num_active_ports == 0) &&
7783baa0db4SSue Gleeson (tgt->tp_requested_state != tgt->tp_state) &&
7793baa0db4SSue Gleeson (tgt->tp_requested_state == SRPT_TGT_STATE_ONLINE)) {
7803baa0db4SSue Gleeson online_target = B_TRUE;
7813baa0db4SSue Gleeson cstatus.st_completion_status = STMF_SUCCESS;
7823baa0db4SSue Gleeson cstatus.st_additional_info = "port active";
7833baa0db4SSue Gleeson }
7843baa0db4SSue Gleeson }
7853baa0db4SSue Gleeson
7863baa0db4SSue Gleeson mutex_exit(&tgt->tp_lock);
7873baa0db4SSue Gleeson
7883baa0db4SSue Gleeson if (online_target) {
7893baa0db4SSue Gleeson stmf_status_t ret;
7903baa0db4SSue Gleeson
7913baa0db4SSue Gleeson ret = stmf_ctl(STMF_CMD_LPORT_ONLINE, tgt->tp_lport, &cstatus);
7923baa0db4SSue Gleeson
7933baa0db4SSue Gleeson if (ret == STMF_SUCCESS) {
7943baa0db4SSue Gleeson SRPT_DPRINTF_L1("ioc_port_active, port %d active, "
7953baa0db4SSue Gleeson "target %016llx online requested", event->ev_port,
7963baa0db4SSue Gleeson (u_longlong_t)ioc->ioc_guid);
7973baa0db4SSue Gleeson } else if (ret != STMF_ALREADY) {
7983baa0db4SSue Gleeson SRPT_DPRINTF_L1("ioc_port_active, port %d active, "
7993baa0db4SSue Gleeson "target %016llx failed online request: %d",
8003baa0db4SSue Gleeson event->ev_port, (u_longlong_t)ioc->ioc_guid,
8013baa0db4SSue Gleeson (int)ret);
8023baa0db4SSue Gleeson }
8031bdd6c0eSSue Gleeson }
8041bdd6c0eSSue Gleeson }
8051bdd6c0eSSue Gleeson
8061bdd6c0eSSue Gleeson /*
8071bdd6c0eSSue Gleeson * srpt_ioc_port_down()
8081bdd6c0eSSue Gleeson */
8091bdd6c0eSSue Gleeson static void
srpt_ioc_port_down(ibt_async_event_t * event)8101bdd6c0eSSue Gleeson srpt_ioc_port_down(ibt_async_event_t *event)
8111bdd6c0eSSue Gleeson {
8121bdd6c0eSSue Gleeson srpt_ioc_t *ioc;
8131bdd6c0eSSue Gleeson srpt_target_port_t *tgt;
8141bdd6c0eSSue Gleeson srpt_channel_t *ch;
8151bdd6c0eSSue Gleeson srpt_channel_t *next_ch;
8163baa0db4SSue Gleeson boolean_t offline_target = B_FALSE;
8173baa0db4SSue Gleeson stmf_change_status_t cstatus;
8181bdd6c0eSSue Gleeson
8191bdd6c0eSSue Gleeson SRPT_DPRINTF_L3("ioc_port_down event handler, invoked");
8201bdd6c0eSSue Gleeson
8211bdd6c0eSSue Gleeson /*
8221bdd6c0eSSue Gleeson * Find the HCA in question and if the HCA has completed
8231bdd6c0eSSue Gleeson * initialization, and the SRP Target service for the
8241bdd6c0eSSue Gleeson * the I/O Controller exists, then logout initiators
8251bdd6c0eSSue Gleeson * through this port.
8261bdd6c0eSSue Gleeson */
8271bdd6c0eSSue Gleeson ioc = srpt_ioc_get(event->ev_hca_guid);
8281bdd6c0eSSue Gleeson
8291bdd6c0eSSue Gleeson if (ioc == NULL) {
8301bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("ioc_port_down, I/O Controller not"
8311bdd6c0eSSue Gleeson " active");
8321bdd6c0eSSue Gleeson return;
8331bdd6c0eSSue Gleeson }
8341bdd6c0eSSue Gleeson
8351bdd6c0eSSue Gleeson /*
8361bdd6c0eSSue Gleeson * We only have one target now, but we could go through all
8371bdd6c0eSSue Gleeson * SCSI target ports if more are added.
8381bdd6c0eSSue Gleeson */
8391bdd6c0eSSue Gleeson tgt = ioc->ioc_tgt_port;
8401bdd6c0eSSue Gleeson if (tgt == NULL) {
8411bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("ioc_port_down, no I/O Controller target"
8421bdd6c0eSSue Gleeson " undefined");
8431bdd6c0eSSue Gleeson return;
8441bdd6c0eSSue Gleeson }
8451bdd6c0eSSue Gleeson mutex_enter(&tgt->tp_lock);
8461bdd6c0eSSue Gleeson
8471bdd6c0eSSue Gleeson /*
8481bdd6c0eSSue Gleeson * For all channel's logged in through this port, initiate a
8491bdd6c0eSSue Gleeson * disconnect.
8501bdd6c0eSSue Gleeson */
8511bdd6c0eSSue Gleeson mutex_enter(&tgt->tp_ch_list_lock);
8521bdd6c0eSSue Gleeson ch = list_head(&tgt->tp_ch_list);
8531bdd6c0eSSue Gleeson while (ch != NULL) {
8541bdd6c0eSSue Gleeson next_ch = list_next(&tgt->tp_ch_list, ch);
8551bdd6c0eSSue Gleeson if (ch->ch_session && (ch->ch_session->ss_hw_port ==
8561bdd6c0eSSue Gleeson event->ev_port)) {
8571bdd6c0eSSue Gleeson srpt_ch_disconnect(ch);
8581bdd6c0eSSue Gleeson }
8591bdd6c0eSSue Gleeson ch = next_ch;
8601bdd6c0eSSue Gleeson }
8611bdd6c0eSSue Gleeson mutex_exit(&tgt->tp_ch_list_lock);
8621bdd6c0eSSue Gleeson
8633baa0db4SSue Gleeson tgt->tp_num_active_ports--;
8643baa0db4SSue Gleeson
8653baa0db4SSue Gleeson /* if we have no active ports, take the target offline */
8663baa0db4SSue Gleeson if ((tgt->tp_num_active_ports == 0) &&
8673baa0db4SSue Gleeson (tgt->tp_state == SRPT_TGT_STATE_ONLINE)) {
8683baa0db4SSue Gleeson cstatus.st_completion_status = STMF_SUCCESS;
8693baa0db4SSue Gleeson cstatus.st_additional_info = "no ports active";
8703baa0db4SSue Gleeson offline_target = B_TRUE;
8713baa0db4SSue Gleeson }
8723baa0db4SSue Gleeson
8731bdd6c0eSSue Gleeson mutex_exit(&tgt->tp_lock);
8743baa0db4SSue Gleeson
8753baa0db4SSue Gleeson if (offline_target) {
8763baa0db4SSue Gleeson stmf_status_t ret;
8773baa0db4SSue Gleeson
8783baa0db4SSue Gleeson ret = stmf_ctl(STMF_CMD_LPORT_OFFLINE, tgt->tp_lport, &cstatus);
8793baa0db4SSue Gleeson
8803baa0db4SSue Gleeson if (ret == STMF_SUCCESS) {
8813baa0db4SSue Gleeson SRPT_DPRINTF_L1("ioc_port_down, port %d down, target "
8823baa0db4SSue Gleeson "%016llx offline requested", event->ev_port,
8833baa0db4SSue Gleeson (u_longlong_t)ioc->ioc_guid);
8843baa0db4SSue Gleeson } else if (ret != STMF_ALREADY) {
8853baa0db4SSue Gleeson SRPT_DPRINTF_L1("ioc_port_down, port %d down, target "
8863baa0db4SSue Gleeson "%016llx failed offline request: %d",
8873baa0db4SSue Gleeson event->ev_port,
8883baa0db4SSue Gleeson (u_longlong_t)ioc->ioc_guid, (int)ret);
8893baa0db4SSue Gleeson }
8903baa0db4SSue Gleeson }
8911bdd6c0eSSue Gleeson }
8921bdd6c0eSSue Gleeson
8931bdd6c0eSSue Gleeson /*
8941bdd6c0eSSue Gleeson * srpt_ioc_ib_async_hdlr - I/O Controller IB asynchronous events
8951bdd6c0eSSue Gleeson */
8961bdd6c0eSSue Gleeson /* ARGSUSED */
8971bdd6c0eSSue Gleeson void
srpt_ioc_ib_async_hdlr(void * clnt,ibt_hca_hdl_t hdl,ibt_async_code_t code,ibt_async_event_t * event)8981bdd6c0eSSue Gleeson srpt_ioc_ib_async_hdlr(void *clnt, ibt_hca_hdl_t hdl,
8991bdd6c0eSSue Gleeson ibt_async_code_t code, ibt_async_event_t *event)
9001bdd6c0eSSue Gleeson {
9011bdd6c0eSSue Gleeson srpt_channel_t *ch;
9021bdd6c0eSSue Gleeson
9031bdd6c0eSSue Gleeson switch (code) {
9041bdd6c0eSSue Gleeson case IBT_EVENT_PORT_UP:
9051bdd6c0eSSue Gleeson srpt_ioc_port_active(event);
9061bdd6c0eSSue Gleeson break;
9071bdd6c0eSSue Gleeson
9081bdd6c0eSSue Gleeson case IBT_ERROR_PORT_DOWN:
9091bdd6c0eSSue Gleeson srpt_ioc_port_down(event);
9101bdd6c0eSSue Gleeson break;
9111bdd6c0eSSue Gleeson
9121bdd6c0eSSue Gleeson case IBT_HCA_ATTACH_EVENT:
913c3a558e7SSue Gleeson SRPT_DPRINTF_L2(
914c3a558e7SSue Gleeson "ib_async_hdlr, received attach event for HCA 0x%016llx",
915c3a558e7SSue Gleeson (u_longlong_t)event->ev_hca_guid);
9161bdd6c0eSSue Gleeson
917c3a558e7SSue Gleeson rw_enter(&srpt_ctxt->sc_rwlock, RW_WRITER);
918c3a558e7SSue Gleeson srpt_ioc_attach_hca(event->ev_hca_guid, B_FALSE);
9191bdd6c0eSSue Gleeson rw_exit(&srpt_ctxt->sc_rwlock);
920c3a558e7SSue Gleeson
9211bdd6c0eSSue Gleeson break;
9221bdd6c0eSSue Gleeson
9231bdd6c0eSSue Gleeson case IBT_HCA_DETACH_EVENT:
9241bdd6c0eSSue Gleeson SRPT_DPRINTF_L1(
925c3a558e7SSue Gleeson "ioc_iob_async_hdlr, received HCA_DETACH_EVENT for "
926c3a558e7SSue Gleeson "HCA 0x%016llx",
927c3a558e7SSue Gleeson (u_longlong_t)event->ev_hca_guid);
928c3a558e7SSue Gleeson
929c3a558e7SSue Gleeson rw_enter(&srpt_ctxt->sc_rwlock, RW_WRITER);
930c3a558e7SSue Gleeson srpt_ioc_detach_hca(event->ev_hca_guid);
931c3a558e7SSue Gleeson rw_exit(&srpt_ctxt->sc_rwlock);
932c3a558e7SSue Gleeson
9331bdd6c0eSSue Gleeson break;
9341bdd6c0eSSue Gleeson
9351bdd6c0eSSue Gleeson case IBT_EVENT_EMPTY_CHAN:
9361bdd6c0eSSue Gleeson /* Channel in ERROR state is now empty */
9371bdd6c0eSSue Gleeson ch = (srpt_channel_t *)ibt_get_chan_private(event->ev_chan_hdl);
9381bdd6c0eSSue Gleeson SRPT_DPRINTF_L3(
9391bdd6c0eSSue Gleeson "ioc_iob_async_hdlr, received empty channel error on %p",
9401bdd6c0eSSue Gleeson (void *)ch);
9411bdd6c0eSSue Gleeson break;
9421bdd6c0eSSue Gleeson
9431bdd6c0eSSue Gleeson default:
9441bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("ioc_ib_async_hdlr, event not "
9451bdd6c0eSSue Gleeson "handled (%d)", code);
9461bdd6c0eSSue Gleeson break;
9471bdd6c0eSSue Gleeson }
9481bdd6c0eSSue Gleeson }
9491bdd6c0eSSue Gleeson
9501bdd6c0eSSue Gleeson /*
9511bdd6c0eSSue Gleeson * srpt_ioc_svc_bind()
9521bdd6c0eSSue Gleeson */
9531bdd6c0eSSue Gleeson ibt_status_t
srpt_ioc_svc_bind(srpt_target_port_t * tgt,uint_t portnum)9541bdd6c0eSSue Gleeson srpt_ioc_svc_bind(srpt_target_port_t *tgt, uint_t portnum)
9551bdd6c0eSSue Gleeson {
9561bdd6c0eSSue Gleeson ibt_status_t status;
9571bdd6c0eSSue Gleeson srpt_hw_port_t *port;
9581bdd6c0eSSue Gleeson ibt_hca_portinfo_t *portinfo;
9591bdd6c0eSSue Gleeson uint_t qportinfo_sz;
9601bdd6c0eSSue Gleeson uint_t qportnum;
9611bdd6c0eSSue Gleeson ib_gid_t new_gid;
9621bdd6c0eSSue Gleeson srpt_ioc_t *ioc;
963191c289bSCharles Ting srpt_session_t sess;
9641bdd6c0eSSue Gleeson
9651bdd6c0eSSue Gleeson ASSERT(tgt != NULL);
9661bdd6c0eSSue Gleeson ASSERT(tgt->tp_ioc != NULL);
9671bdd6c0eSSue Gleeson ioc = tgt->tp_ioc;
9681bdd6c0eSSue Gleeson
9691bdd6c0eSSue Gleeson if (tgt->tp_ibt_svc_hdl == NULL) {
9701bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("ioc_svc_bind, NULL SCSI target port"
9711bdd6c0eSSue Gleeson " service");
9721bdd6c0eSSue Gleeson return (IBT_INVALID_PARAM);
9731bdd6c0eSSue Gleeson }
9741bdd6c0eSSue Gleeson
9751bdd6c0eSSue Gleeson if (portnum == 0 || portnum > tgt->tp_nports) {
9761bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("ioc_svc_bind, bad port (%d)", portnum);
9771bdd6c0eSSue Gleeson return (IBT_INVALID_PARAM);
9781bdd6c0eSSue Gleeson }
9791bdd6c0eSSue Gleeson status = ibt_query_hca_ports(ioc->ioc_ibt_hdl, portnum,
9801bdd6c0eSSue Gleeson &portinfo, &qportnum, &qportinfo_sz);
9811bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
9821bdd6c0eSSue Gleeson SRPT_DPRINTF_L1("ioc_svc_bind, query port error (%d)",
9831bdd6c0eSSue Gleeson portnum);
9841bdd6c0eSSue Gleeson return (IBT_INVALID_PARAM);
9851bdd6c0eSSue Gleeson }
9861bdd6c0eSSue Gleeson
9871bdd6c0eSSue Gleeson ASSERT(portinfo != NULL);
9881bdd6c0eSSue Gleeson
9891bdd6c0eSSue Gleeson /*
9901bdd6c0eSSue Gleeson * If port is not active do nothing, caller should attempt to bind
9911bdd6c0eSSue Gleeson * after the port goes active.
9921bdd6c0eSSue Gleeson */
9931bdd6c0eSSue Gleeson if (portinfo->p_linkstate != IBT_PORT_ACTIVE) {
9941bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("ioc_svc_bind, port %d not in active state",
9951bdd6c0eSSue Gleeson portnum);
9961bdd6c0eSSue Gleeson ibt_free_portinfo(portinfo, qportinfo_sz);
9971bdd6c0eSSue Gleeson return (IBT_HCA_PORT_NOT_ACTIVE);
9981bdd6c0eSSue Gleeson }
9991bdd6c0eSSue Gleeson
10001bdd6c0eSSue Gleeson port = &tgt->tp_hw_port[portnum-1];
10011bdd6c0eSSue Gleeson new_gid = portinfo->p_sgid_tbl[0];
10021bdd6c0eSSue Gleeson ibt_free_portinfo(portinfo, qportinfo_sz);
10031bdd6c0eSSue Gleeson
10041bdd6c0eSSue Gleeson /*
10051bdd6c0eSSue Gleeson * If previously bound and the port GID has changed,
1006285c05bcSSue Gleeson * unbind the old GID.
10071bdd6c0eSSue Gleeson */
10081bdd6c0eSSue Gleeson if (port->hwp_bind_hdl != NULL) {
10091bdd6c0eSSue Gleeson if (new_gid.gid_guid != port->hwp_gid.gid_guid ||
10101bdd6c0eSSue Gleeson new_gid.gid_prefix != port->hwp_gid.gid_prefix) {
10111bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("ioc_svc_bind, unregister current"
10121bdd6c0eSSue Gleeson " bind");
1013aedf2b3bSsrivijitha dugganapalli (void) ibt_unbind_service(tgt->tp_ibt_svc_hdl,
10141bdd6c0eSSue Gleeson port->hwp_bind_hdl);
10151bdd6c0eSSue Gleeson port->hwp_bind_hdl = NULL;
1016285c05bcSSue Gleeson } else {
1017285c05bcSSue Gleeson SRPT_DPRINTF_L2("ioc_svc_bind, port %d already bound",
1018285c05bcSSue Gleeson portnum);
10191bdd6c0eSSue Gleeson }
10201bdd6c0eSSue Gleeson }
10211bdd6c0eSSue Gleeson
1022285c05bcSSue Gleeson /* bind the new port GID */
1023285c05bcSSue Gleeson if (port->hwp_bind_hdl == NULL) {
1024285c05bcSSue Gleeson SRPT_DPRINTF_L2("ioc_svc_bind, bind service, %016llx:%016llx",
1025285c05bcSSue Gleeson (u_longlong_t)new_gid.gid_prefix,
1026285c05bcSSue Gleeson (u_longlong_t)new_gid.gid_guid);
1027285c05bcSSue Gleeson
1028285c05bcSSue Gleeson /*
1029285c05bcSSue Gleeson * Pass SCSI Target Port as CM private data, the target will
1030285c05bcSSue Gleeson * always exist while this service is bound.
1031285c05bcSSue Gleeson */
1032285c05bcSSue Gleeson status = ibt_bind_service(tgt->tp_ibt_svc_hdl, new_gid, NULL,
1033285c05bcSSue Gleeson tgt, &port->hwp_bind_hdl);
1034285c05bcSSue Gleeson if (status != IBT_SUCCESS && status != IBT_CM_SERVICE_EXISTS) {
1035285c05bcSSue Gleeson SRPT_DPRINTF_L1("ioc_svc_bind, bind error (%d)",
1036285c05bcSSue Gleeson status);
1037285c05bcSSue Gleeson return (status);
1038285c05bcSSue Gleeson }
1039285c05bcSSue Gleeson port->hwp_gid.gid_prefix = new_gid.gid_prefix;
1040285c05bcSSue Gleeson port->hwp_gid.gid_guid = new_gid.gid_guid;
10411bdd6c0eSSue Gleeson }
1042285c05bcSSue Gleeson
1043285c05bcSSue Gleeson /* port is now active */
10443baa0db4SSue Gleeson tgt->tp_num_active_ports++;
1045191c289bSCharles Ting
1046191c289bSCharles Ting /* setting up a transient structure for the dtrace probe. */
1047191c289bSCharles Ting bzero(&sess, sizeof (srpt_session_t));
1048191c289bSCharles Ting ALIAS_STR(sess.ss_t_gid, new_gid.gid_prefix, new_gid.gid_guid);
1049191c289bSCharles Ting EUI_STR(sess.ss_t_name, tgt->tp_ibt_svc_id);
1050191c289bSCharles Ting
1051191c289bSCharles Ting DTRACE_SRP_1(service__up, srpt_session_t, &sess);
10521bdd6c0eSSue Gleeson
10531bdd6c0eSSue Gleeson return (IBT_SUCCESS);
10541bdd6c0eSSue Gleeson }
10551bdd6c0eSSue Gleeson
10561bdd6c0eSSue Gleeson /*
10571bdd6c0eSSue Gleeson * srpt_ioc_svc_unbind()
10581bdd6c0eSSue Gleeson */
10591bdd6c0eSSue Gleeson void
srpt_ioc_svc_unbind(srpt_target_port_t * tgt,uint_t portnum)10601bdd6c0eSSue Gleeson srpt_ioc_svc_unbind(srpt_target_port_t *tgt, uint_t portnum)
10611bdd6c0eSSue Gleeson {
10621bdd6c0eSSue Gleeson srpt_hw_port_t *port;
1063191c289bSCharles Ting srpt_session_t sess;
10643baa0db4SSue Gleeson ibt_status_t ret;
10651bdd6c0eSSue Gleeson
10661bdd6c0eSSue Gleeson if (tgt == NULL) {
10671bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("ioc_svc_unbind, SCSI target does not exist");
10681bdd6c0eSSue Gleeson return;
10691bdd6c0eSSue Gleeson }
10701bdd6c0eSSue Gleeson
10711bdd6c0eSSue Gleeson if (portnum == 0 || portnum > tgt->tp_nports) {
10721bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("ioc_svc_unbind, bad port (%d)", portnum);
10731bdd6c0eSSue Gleeson return;
10741bdd6c0eSSue Gleeson }
10751bdd6c0eSSue Gleeson port = &tgt->tp_hw_port[portnum-1];
10761bdd6c0eSSue Gleeson
1077191c289bSCharles Ting /* setting up a transient structure for the dtrace probe. */
1078191c289bSCharles Ting bzero(&sess, sizeof (srpt_session_t));
1079191c289bSCharles Ting ALIAS_STR(sess.ss_t_gid, port->hwp_gid.gid_prefix,
1080191c289bSCharles Ting port->hwp_gid.gid_guid);
1081191c289bSCharles Ting EUI_STR(sess.ss_t_name, tgt->tp_ibt_svc_id);
1082191c289bSCharles Ting
1083191c289bSCharles Ting DTRACE_SRP_1(service__down, srpt_session_t, &sess);
1084191c289bSCharles Ting
10851bdd6c0eSSue Gleeson if (tgt->tp_ibt_svc_hdl != NULL && port->hwp_bind_hdl != NULL) {
10861bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("ioc_svc_unbind, unregister current bind");
10873baa0db4SSue Gleeson ret = ibt_unbind_service(tgt->tp_ibt_svc_hdl,
1088aedf2b3bSsrivijitha dugganapalli port->hwp_bind_hdl);
10893baa0db4SSue Gleeson if (ret != IBT_SUCCESS) {
10903baa0db4SSue Gleeson SRPT_DPRINTF_L1(
10913baa0db4SSue Gleeson "ioc_svc_unbind, unregister port %d failed: %d",
10923baa0db4SSue Gleeson portnum, ret);
10933baa0db4SSue Gleeson } else {
10943baa0db4SSue Gleeson port->hwp_bind_hdl = NULL;
10953baa0db4SSue Gleeson port->hwp_gid.gid_prefix = 0;
10963baa0db4SSue Gleeson port->hwp_gid.gid_guid = 0;
10973baa0db4SSue Gleeson }
10981bdd6c0eSSue Gleeson }
10991bdd6c0eSSue Gleeson }
11001bdd6c0eSSue Gleeson
11011bdd6c0eSSue Gleeson /*
11021bdd6c0eSSue Gleeson * srpt_ioc_svc_unbind_all()
11031bdd6c0eSSue Gleeson */
11041bdd6c0eSSue Gleeson void
srpt_ioc_svc_unbind_all(srpt_target_port_t * tgt)11051bdd6c0eSSue Gleeson srpt_ioc_svc_unbind_all(srpt_target_port_t *tgt)
11061bdd6c0eSSue Gleeson {
11071bdd6c0eSSue Gleeson uint_t portnum;
11081bdd6c0eSSue Gleeson
11091bdd6c0eSSue Gleeson if (tgt == NULL) {
11101bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("ioc_svc_unbind_all, NULL SCSI target port"
11111bdd6c0eSSue Gleeson " specified");
11121bdd6c0eSSue Gleeson return;
11131bdd6c0eSSue Gleeson }
11141bdd6c0eSSue Gleeson for (portnum = 1; portnum <= tgt->tp_nports; portnum++) {
11151bdd6c0eSSue Gleeson srpt_ioc_svc_unbind(tgt, portnum);
11161bdd6c0eSSue Gleeson }
11171bdd6c0eSSue Gleeson }
11181bdd6c0eSSue Gleeson
11191bdd6c0eSSue Gleeson /*
11201bdd6c0eSSue Gleeson * srpt_ioc_get_locked()
11211bdd6c0eSSue Gleeson *
11221bdd6c0eSSue Gleeson * Requires srpt_ctxt->rw_lock be held outside of call.
11231bdd6c0eSSue Gleeson */
11241bdd6c0eSSue Gleeson srpt_ioc_t *
srpt_ioc_get_locked(ib_guid_t guid)11251bdd6c0eSSue Gleeson srpt_ioc_get_locked(ib_guid_t guid)
11261bdd6c0eSSue Gleeson {
11271bdd6c0eSSue Gleeson srpt_ioc_t *ioc;
11281bdd6c0eSSue Gleeson
11291bdd6c0eSSue Gleeson ioc = list_head(&srpt_ctxt->sc_ioc_list);
11301bdd6c0eSSue Gleeson while (ioc != NULL) {
11311bdd6c0eSSue Gleeson if (ioc->ioc_guid == guid) {
11321bdd6c0eSSue Gleeson break;
11331bdd6c0eSSue Gleeson }
11341bdd6c0eSSue Gleeson ioc = list_next(&srpt_ctxt->sc_ioc_list, ioc);
11351bdd6c0eSSue Gleeson }
11361bdd6c0eSSue Gleeson return (ioc);
11371bdd6c0eSSue Gleeson }
11381bdd6c0eSSue Gleeson
11391bdd6c0eSSue Gleeson /*
11401bdd6c0eSSue Gleeson * srpt_ioc_get()
11411bdd6c0eSSue Gleeson */
11421bdd6c0eSSue Gleeson srpt_ioc_t *
srpt_ioc_get(ib_guid_t guid)11431bdd6c0eSSue Gleeson srpt_ioc_get(ib_guid_t guid)
11441bdd6c0eSSue Gleeson {
11451bdd6c0eSSue Gleeson srpt_ioc_t *ioc;
11461bdd6c0eSSue Gleeson
11471bdd6c0eSSue Gleeson rw_enter(&srpt_ctxt->sc_rwlock, RW_READER);
11481bdd6c0eSSue Gleeson ioc = srpt_ioc_get_locked(guid);
11491bdd6c0eSSue Gleeson rw_exit(&srpt_ctxt->sc_rwlock);
11501bdd6c0eSSue Gleeson return (ioc);
11511bdd6c0eSSue Gleeson }
11521bdd6c0eSSue Gleeson
11531bdd6c0eSSue Gleeson /*
11541bdd6c0eSSue Gleeson * srpt_ioc_post_recv_iu()
11551bdd6c0eSSue Gleeson */
11561bdd6c0eSSue Gleeson ibt_status_t
srpt_ioc_post_recv_iu(srpt_ioc_t * ioc,srpt_iu_t * iu)11571bdd6c0eSSue Gleeson srpt_ioc_post_recv_iu(srpt_ioc_t *ioc, srpt_iu_t *iu)
11581bdd6c0eSSue Gleeson {
11591bdd6c0eSSue Gleeson ibt_status_t status;
11601bdd6c0eSSue Gleeson ibt_recv_wr_t wr;
11611bdd6c0eSSue Gleeson uint_t posted;
11621bdd6c0eSSue Gleeson
11631bdd6c0eSSue Gleeson ASSERT(ioc != NULL);
11641bdd6c0eSSue Gleeson ASSERT(iu != NULL);
11651bdd6c0eSSue Gleeson
11661bdd6c0eSSue Gleeson wr.wr_id = (ibt_wrid_t)(uintptr_t)iu;
11671bdd6c0eSSue Gleeson wr.wr_nds = 1;
11681bdd6c0eSSue Gleeson wr.wr_sgl = &iu->iu_sge;
11691bdd6c0eSSue Gleeson posted = 0;
11701bdd6c0eSSue Gleeson
11711bdd6c0eSSue Gleeson status = ibt_post_srq(ioc->ioc_srq_hdl, &wr, 1, &posted);
11721bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
11731bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("ioc_post_recv_iu, post error (%d)",
11741bdd6c0eSSue Gleeson status);
11751bdd6c0eSSue Gleeson }
11761bdd6c0eSSue Gleeson return (status);
11771bdd6c0eSSue Gleeson }
11781bdd6c0eSSue Gleeson
11791bdd6c0eSSue Gleeson /*
11801bdd6c0eSSue Gleeson * srpt_ioc_repost_recv_iu()
11811bdd6c0eSSue Gleeson */
11821bdd6c0eSSue Gleeson void
srpt_ioc_repost_recv_iu(srpt_ioc_t * ioc,srpt_iu_t * iu)11831bdd6c0eSSue Gleeson srpt_ioc_repost_recv_iu(srpt_ioc_t *ioc, srpt_iu_t *iu)
11841bdd6c0eSSue Gleeson {
11851bdd6c0eSSue Gleeson srpt_channel_t *ch;
11861bdd6c0eSSue Gleeson ibt_status_t status;
11871bdd6c0eSSue Gleeson
11881bdd6c0eSSue Gleeson ASSERT(iu != NULL);
11891bdd6c0eSSue Gleeson ASSERT(mutex_owned(&iu->iu_lock));
11901bdd6c0eSSue Gleeson
11911bdd6c0eSSue Gleeson /*
11921bdd6c0eSSue Gleeson * Some additional sanity checks while in debug state, all STMF
11931bdd6c0eSSue Gleeson * related task activities should be complete prior to returning
11941bdd6c0eSSue Gleeson * this IU to the available pool.
11951bdd6c0eSSue Gleeson */
11961bdd6c0eSSue Gleeson ASSERT(iu->iu_stmf_task == NULL);
11971bdd6c0eSSue Gleeson ASSERT(iu->iu_sq_posted_cnt == 0);
11981bdd6c0eSSue Gleeson
11991bdd6c0eSSue Gleeson ch = iu->iu_ch;
12001bdd6c0eSSue Gleeson iu->iu_ch = NULL;
12011bdd6c0eSSue Gleeson iu->iu_num_rdescs = 0;
12021bdd6c0eSSue Gleeson iu->iu_rdescs = NULL;
12031bdd6c0eSSue Gleeson iu->iu_tot_xfer_len = 0;
12041bdd6c0eSSue Gleeson iu->iu_tag = 0;
12051bdd6c0eSSue Gleeson iu->iu_flags = 0;
12061bdd6c0eSSue Gleeson iu->iu_sq_posted_cnt = 0;
12071bdd6c0eSSue Gleeson
12081bdd6c0eSSue Gleeson status = srpt_ioc_post_recv_iu(ioc, iu);
12091bdd6c0eSSue Gleeson
12101bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
12111bdd6c0eSSue Gleeson /*
12121bdd6c0eSSue Gleeson * Very bad, we should initiate a shutdown of the I/O
12131bdd6c0eSSue Gleeson * Controller here, off-lining any targets associated
12141bdd6c0eSSue Gleeson * with this I/O Controller (and therefore disconnecting
12151bdd6c0eSSue Gleeson * any logins that remain).
12161bdd6c0eSSue Gleeson *
12171bdd6c0eSSue Gleeson * In practice this should never happen so we put
12181bdd6c0eSSue Gleeson * the code near the bottom of the implementation list.
12191bdd6c0eSSue Gleeson */
12201bdd6c0eSSue Gleeson SRPT_DPRINTF_L0("ioc_repost_recv_iu, error RX IU (%d)",
12211bdd6c0eSSue Gleeson status);
12221bdd6c0eSSue Gleeson ASSERT(0);
12231bdd6c0eSSue Gleeson } else if (ch != NULL) {
12241bdd6c0eSSue Gleeson atomic_inc_32(&ch->ch_req_lim_delta);
12251bdd6c0eSSue Gleeson }
12261bdd6c0eSSue Gleeson }
12271bdd6c0eSSue Gleeson
12281bdd6c0eSSue Gleeson /*
12291bdd6c0eSSue Gleeson * srpt_ioc_init_profile()
12301bdd6c0eSSue Gleeson *
12311bdd6c0eSSue Gleeson * SRP I/O Controller serialization lock must be held when this
12321bdd6c0eSSue Gleeson * routine is invoked.
12331bdd6c0eSSue Gleeson */
12341bdd6c0eSSue Gleeson void
srpt_ioc_init_profile(srpt_ioc_t * ioc)12351bdd6c0eSSue Gleeson srpt_ioc_init_profile(srpt_ioc_t *ioc)
12361bdd6c0eSSue Gleeson {
12371bdd6c0eSSue Gleeson srpt_ioc_opcap_mask_t capmask = {0};
12381bdd6c0eSSue Gleeson
12391bdd6c0eSSue Gleeson ASSERT(ioc != NULL);
12401bdd6c0eSSue Gleeson
12411bdd6c0eSSue Gleeson ioc->ioc_profile.ioc_guid = h2b64(ioc->ioc_guid);
12421bdd6c0eSSue Gleeson (void) memcpy(ioc->ioc_profile.ioc_id_string,
12431bdd6c0eSSue Gleeson "Solaris SRP Target 0.9a", 23);
12441bdd6c0eSSue Gleeson
12451bdd6c0eSSue Gleeson /*
12461bdd6c0eSSue Gleeson * Note vendor ID and subsystem ID are 24 bit values. Low order
12471bdd6c0eSSue Gleeson * 8 bits in vendor ID field is slot and is initialized to zero.
12481bdd6c0eSSue Gleeson * Low order 8 bits of subsystem ID is a reserved field and
12491bdd6c0eSSue Gleeson * initialized to zero.
12501bdd6c0eSSue Gleeson */
12511bdd6c0eSSue Gleeson ioc->ioc_profile.ioc_vendorid =
12521bdd6c0eSSue Gleeson h2b32((uint32_t)(ioc->ioc_attr.hca_vendor_id << 8));
12531bdd6c0eSSue Gleeson ioc->ioc_profile.ioc_deviceid =
12541bdd6c0eSSue Gleeson h2b32((uint32_t)ioc->ioc_attr.hca_device_id);
12551bdd6c0eSSue Gleeson ioc->ioc_profile.ioc_device_ver =
12561bdd6c0eSSue Gleeson h2b16((uint16_t)ioc->ioc_attr.hca_version_id);
12571bdd6c0eSSue Gleeson ioc->ioc_profile.ioc_subsys_vendorid =
12581bdd6c0eSSue Gleeson h2b32((uint32_t)(ioc->ioc_attr.hca_vendor_id << 8));
12591bdd6c0eSSue Gleeson ioc->ioc_profile.ioc_subsys_id = h2b32(0);
12601bdd6c0eSSue Gleeson ioc->ioc_profile.ioc_io_class = h2b16(SRP_REV_16A_IO_CLASS);
12611bdd6c0eSSue Gleeson ioc->ioc_profile.ioc_io_subclass = h2b16(SRP_IO_SUBCLASS);
12621bdd6c0eSSue Gleeson ioc->ioc_profile.ioc_protocol = h2b16(SRP_PROTOCOL);
12631bdd6c0eSSue Gleeson ioc->ioc_profile.ioc_protocol_ver = h2b16(SRP_PROTOCOL_VERSION);
12641bdd6c0eSSue Gleeson ioc->ioc_profile.ioc_send_msg_qdepth = h2b16(srpt_send_msg_depth);
12651bdd6c0eSSue Gleeson ioc->ioc_profile.ioc_rdma_read_qdepth =
12661bdd6c0eSSue Gleeson ioc->ioc_attr.hca_max_rdma_out_chan;
1267989ca640SSue Gleeson ioc->ioc_profile.ioc_send_msg_sz = h2b32(srpt_iu_size);
12681bdd6c0eSSue Gleeson ioc->ioc_profile.ioc_rdma_xfer_sz = h2b32(SRPT_DEFAULT_MAX_RDMA_SIZE);
12691bdd6c0eSSue Gleeson
12701bdd6c0eSSue Gleeson capmask.bits.st = 1; /* Messages can be sent to IOC */
12711bdd6c0eSSue Gleeson capmask.bits.sf = 1; /* Messages can be sent from IOC */
12721bdd6c0eSSue Gleeson capmask.bits.rf = 1; /* RDMA Reads can be sent from IOC */
12731bdd6c0eSSue Gleeson capmask.bits.wf = 1; /* RDMA Writes can be sent from IOC */
12741bdd6c0eSSue Gleeson ioc->ioc_profile.ioc_ctrl_opcap_mask = capmask.mask;
12751bdd6c0eSSue Gleeson
12761bdd6c0eSSue Gleeson /*
12771bdd6c0eSSue Gleeson * We currently only have one target, but if we had a list we would
12781bdd6c0eSSue Gleeson * go through that list and only count those that are ONLINE when
12791bdd6c0eSSue Gleeson * setting the services count and entries.
12801bdd6c0eSSue Gleeson */
12811bdd6c0eSSue Gleeson if (ioc->ioc_tgt_port->tp_srp_enabled) {
12821bdd6c0eSSue Gleeson ioc->ioc_profile.ioc_service_entries = 1;
12831bdd6c0eSSue Gleeson ioc->ioc_svc.srv_id = h2b64(ioc->ioc_guid);
12841bdd6c0eSSue Gleeson (void) snprintf((char *)ioc->ioc_svc.srv_name,
12851bdd6c0eSSue Gleeson IB_DM_MAX_SVC_NAME_LEN, "SRP.T10:%016llx",
12861bdd6c0eSSue Gleeson (u_longlong_t)ioc->ioc_guid);
12871bdd6c0eSSue Gleeson } else {
12881bdd6c0eSSue Gleeson ioc->ioc_profile.ioc_service_entries = 0;
12891bdd6c0eSSue Gleeson ioc->ioc_svc.srv_id = 0;
12901bdd6c0eSSue Gleeson }
12911bdd6c0eSSue Gleeson }
12921bdd6c0eSSue Gleeson
12931bdd6c0eSSue Gleeson /*
12941bdd6c0eSSue Gleeson * srpt_ioc_ds_alloc_dbuf()
12951bdd6c0eSSue Gleeson */
12961bdd6c0eSSue Gleeson /* ARGSUSED */
12971bdd6c0eSSue Gleeson stmf_data_buf_t *
srpt_ioc_ds_alloc_dbuf(struct scsi_task * task,uint32_t size,uint32_t * pminsize,uint32_t flags)12981bdd6c0eSSue Gleeson srpt_ioc_ds_alloc_dbuf(struct scsi_task *task, uint32_t size,
12991bdd6c0eSSue Gleeson uint32_t *pminsize, uint32_t flags)
13001bdd6c0eSSue Gleeson {
13011bdd6c0eSSue Gleeson srpt_iu_t *iu;
13021bdd6c0eSSue Gleeson srpt_ioc_t *ioc;
13031bdd6c0eSSue Gleeson srpt_ds_dbuf_t *dbuf;
13041bdd6c0eSSue Gleeson stmf_data_buf_t *stmf_dbuf;
13051bdd6c0eSSue Gleeson void *buf;
13061bdd6c0eSSue Gleeson srpt_mr_t mr;
13071bdd6c0eSSue Gleeson
13081bdd6c0eSSue Gleeson ASSERT(task != NULL);
13091bdd6c0eSSue Gleeson iu = task->task_port_private;
13101bdd6c0eSSue Gleeson ioc = iu->iu_ioc;
13111bdd6c0eSSue Gleeson
13121bdd6c0eSSue Gleeson SRPT_DPRINTF_L4("ioc_ds_alloc_dbuf, invoked ioc(%p)"
13131bdd6c0eSSue Gleeson " size(%d), flags(%x)",
13141bdd6c0eSSue Gleeson (void *)ioc, size, flags);
13151bdd6c0eSSue Gleeson
13161bdd6c0eSSue Gleeson buf = srpt_vmem_alloc(ioc->ioc_dbuf_pool, size);
13171bdd6c0eSSue Gleeson if (buf == NULL) {
13181bdd6c0eSSue Gleeson return (NULL);
13191bdd6c0eSSue Gleeson }
13201bdd6c0eSSue Gleeson
13211bdd6c0eSSue Gleeson if (srpt_vmem_mr(ioc->ioc_dbuf_pool, buf, size, &mr) != 0) {
13221bdd6c0eSSue Gleeson goto stmf_alloc_err;
13231bdd6c0eSSue Gleeson }
13241bdd6c0eSSue Gleeson
13251bdd6c0eSSue Gleeson stmf_dbuf = stmf_alloc(STMF_STRUCT_DATA_BUF, sizeof (srpt_ds_dbuf_t),
13261bdd6c0eSSue Gleeson 0);
13271bdd6c0eSSue Gleeson if (stmf_dbuf == NULL) {
13281bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("ioc_ds_alloc_dbuf, stmf_alloc failed");
13291bdd6c0eSSue Gleeson goto stmf_alloc_err;
13301bdd6c0eSSue Gleeson }
13311bdd6c0eSSue Gleeson
13321bdd6c0eSSue Gleeson dbuf = stmf_dbuf->db_port_private;
13331bdd6c0eSSue Gleeson dbuf->db_stmf_buf = stmf_dbuf;
13341bdd6c0eSSue Gleeson dbuf->db_mr_hdl = mr.mr_hdl;
13351bdd6c0eSSue Gleeson dbuf->db_ioc = ioc;
13361bdd6c0eSSue Gleeson dbuf->db_sge.ds_va = mr.mr_va;
13371bdd6c0eSSue Gleeson dbuf->db_sge.ds_key = mr.mr_lkey;
13381bdd6c0eSSue Gleeson dbuf->db_sge.ds_len = size;
13391bdd6c0eSSue Gleeson
13401bdd6c0eSSue Gleeson stmf_dbuf->db_buf_size = size;
13411bdd6c0eSSue Gleeson stmf_dbuf->db_data_size = size;
13421bdd6c0eSSue Gleeson stmf_dbuf->db_relative_offset = 0;
13431bdd6c0eSSue Gleeson stmf_dbuf->db_flags = 0;
13441bdd6c0eSSue Gleeson stmf_dbuf->db_xfer_status = 0;
13451bdd6c0eSSue Gleeson stmf_dbuf->db_sglist_length = 1;
13461bdd6c0eSSue Gleeson stmf_dbuf->db_sglist[0].seg_addr = buf;
13471bdd6c0eSSue Gleeson stmf_dbuf->db_sglist[0].seg_length = size;
13481bdd6c0eSSue Gleeson
13491bdd6c0eSSue Gleeson return (stmf_dbuf);
13501bdd6c0eSSue Gleeson
13511bdd6c0eSSue Gleeson buf_mr_err:
13521bdd6c0eSSue Gleeson stmf_free(stmf_dbuf);
13531bdd6c0eSSue Gleeson
13541bdd6c0eSSue Gleeson stmf_alloc_err:
13551bdd6c0eSSue Gleeson srpt_vmem_free(ioc->ioc_dbuf_pool, buf, size);
13561bdd6c0eSSue Gleeson
13571bdd6c0eSSue Gleeson return (NULL);
13581bdd6c0eSSue Gleeson }
13591bdd6c0eSSue Gleeson
13601bdd6c0eSSue Gleeson void
srpt_ioc_ds_free_dbuf(struct stmf_dbuf_store * ds,stmf_data_buf_t * dbuf)13611bdd6c0eSSue Gleeson srpt_ioc_ds_free_dbuf(struct stmf_dbuf_store *ds,
13621bdd6c0eSSue Gleeson stmf_data_buf_t *dbuf)
13631bdd6c0eSSue Gleeson {
13641bdd6c0eSSue Gleeson srpt_ioc_t *ioc;
13651bdd6c0eSSue Gleeson
13661bdd6c0eSSue Gleeson SRPT_DPRINTF_L4("ioc_ds_free_dbuf, invoked buf (%p)",
13671bdd6c0eSSue Gleeson (void *)dbuf);
13681bdd6c0eSSue Gleeson ioc = ds->ds_port_private;
13691bdd6c0eSSue Gleeson
13701bdd6c0eSSue Gleeson srpt_vmem_free(ioc->ioc_dbuf_pool, dbuf->db_sglist[0].seg_addr,
13711bdd6c0eSSue Gleeson dbuf->db_buf_size);
13721bdd6c0eSSue Gleeson stmf_free(dbuf);
13731bdd6c0eSSue Gleeson }
13741bdd6c0eSSue Gleeson
13751bdd6c0eSSue Gleeson /* Memory arena routines */
13761bdd6c0eSSue Gleeson
13771bdd6c0eSSue Gleeson 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)13781bdd6c0eSSue Gleeson srpt_vmem_create(const char *name, srpt_ioc_t *ioc, ib_memlen_t chunksize,
13791bdd6c0eSSue Gleeson uint64_t maxsize, ibt_mr_flags_t flags)
13801bdd6c0eSSue Gleeson {
13811bdd6c0eSSue Gleeson srpt_mr_t *chunk;
13821bdd6c0eSSue Gleeson srpt_vmem_pool_t *result;
13831bdd6c0eSSue Gleeson
13841bdd6c0eSSue Gleeson ASSERT(chunksize <= maxsize);
13851bdd6c0eSSue Gleeson
13861bdd6c0eSSue Gleeson result = kmem_zalloc(sizeof (srpt_vmem_pool_t), KM_SLEEP);
13871bdd6c0eSSue Gleeson
13881bdd6c0eSSue Gleeson result->svp_ioc = ioc;
13891bdd6c0eSSue Gleeson result->svp_chunksize = chunksize;
13901bdd6c0eSSue Gleeson result->svp_max_size = maxsize;
13911bdd6c0eSSue Gleeson result->svp_flags = flags;
13921bdd6c0eSSue Gleeson
13931bdd6c0eSSue Gleeson rw_init(&result->svp_lock, NULL, RW_DRIVER, NULL);
13941bdd6c0eSSue Gleeson avl_create(&result->svp_mr_list, srpt_vmem_mr_compare,
13951bdd6c0eSSue Gleeson sizeof (srpt_mr_t), offsetof(srpt_mr_t, mr_avl));
13961bdd6c0eSSue Gleeson
13971bdd6c0eSSue Gleeson chunk = srpt_vmem_chunk_alloc(result, chunksize);
13981bdd6c0eSSue Gleeson
13991bdd6c0eSSue Gleeson avl_add(&result->svp_mr_list, chunk);
14001bdd6c0eSSue Gleeson result->svp_total_size = chunksize;
14011bdd6c0eSSue Gleeson
14021bdd6c0eSSue Gleeson result->svp_vmem = vmem_create(name,
14031bdd6c0eSSue Gleeson (void*)(uintptr_t)chunk->mr_va,
14041bdd6c0eSSue Gleeson (size_t)chunk->mr_len, SRPT_MR_QUANTSIZE,
14051bdd6c0eSSue Gleeson NULL, NULL, NULL, 0, VM_SLEEP);
14061bdd6c0eSSue Gleeson
14071bdd6c0eSSue Gleeson return (result);
14081bdd6c0eSSue Gleeson }
14091bdd6c0eSSue Gleeson
14101bdd6c0eSSue Gleeson static void
srpt_vmem_destroy(srpt_vmem_pool_t * vm_pool)14111bdd6c0eSSue Gleeson srpt_vmem_destroy(srpt_vmem_pool_t *vm_pool)
14121bdd6c0eSSue Gleeson {
14131bdd6c0eSSue Gleeson srpt_mr_t *chunk;
14141bdd6c0eSSue Gleeson srpt_mr_t *next;
14151bdd6c0eSSue Gleeson
14161bdd6c0eSSue Gleeson rw_enter(&vm_pool->svp_lock, RW_WRITER);
14171bdd6c0eSSue Gleeson vmem_destroy(vm_pool->svp_vmem);
14181bdd6c0eSSue Gleeson
14191bdd6c0eSSue Gleeson chunk = avl_first(&vm_pool->svp_mr_list);
14201bdd6c0eSSue Gleeson
14211bdd6c0eSSue Gleeson while (chunk != NULL) {
14221bdd6c0eSSue Gleeson next = AVL_NEXT(&vm_pool->svp_mr_list, chunk);
14231bdd6c0eSSue Gleeson avl_remove(&vm_pool->svp_mr_list, chunk);
14241bdd6c0eSSue Gleeson srpt_vmem_chunk_free(vm_pool, chunk);
14251bdd6c0eSSue Gleeson chunk = next;
14261bdd6c0eSSue Gleeson }
14271bdd6c0eSSue Gleeson
14281bdd6c0eSSue Gleeson avl_destroy(&vm_pool->svp_mr_list);
14291bdd6c0eSSue Gleeson
14301bdd6c0eSSue Gleeson rw_exit(&vm_pool->svp_lock);
14311bdd6c0eSSue Gleeson rw_destroy(&vm_pool->svp_lock);
14321bdd6c0eSSue Gleeson
14331bdd6c0eSSue Gleeson kmem_free(vm_pool, sizeof (srpt_vmem_pool_t));
14341bdd6c0eSSue Gleeson }
14351bdd6c0eSSue Gleeson
14361bdd6c0eSSue Gleeson static void *
srpt_vmem_alloc(srpt_vmem_pool_t * vm_pool,size_t size)14371bdd6c0eSSue Gleeson srpt_vmem_alloc(srpt_vmem_pool_t *vm_pool, size_t size)
14381bdd6c0eSSue Gleeson {
14391bdd6c0eSSue Gleeson void *result;
14401bdd6c0eSSue Gleeson srpt_mr_t *next;
14411bdd6c0eSSue Gleeson ib_memlen_t chunklen;
14421bdd6c0eSSue Gleeson
14431bdd6c0eSSue Gleeson ASSERT(vm_pool != NULL);
14441bdd6c0eSSue Gleeson
14451bdd6c0eSSue Gleeson result = vmem_alloc(vm_pool->svp_vmem, size,
14461bdd6c0eSSue Gleeson VM_NOSLEEP | VM_FIRSTFIT);
14471bdd6c0eSSue Gleeson
14481bdd6c0eSSue Gleeson if (result != NULL) {
14491bdd6c0eSSue Gleeson /* memory successfully allocated */
14501bdd6c0eSSue Gleeson return (result);
14511bdd6c0eSSue Gleeson }
14521bdd6c0eSSue Gleeson
14531bdd6c0eSSue Gleeson /* need more vmem */
14541bdd6c0eSSue Gleeson rw_enter(&vm_pool->svp_lock, RW_WRITER);
14551bdd6c0eSSue Gleeson chunklen = vm_pool->svp_chunksize;
14561bdd6c0eSSue Gleeson
14571bdd6c0eSSue Gleeson if (vm_pool->svp_total_size >= vm_pool->svp_max_size) {
14581bdd6c0eSSue Gleeson /* no more room to alloc */
14591bdd6c0eSSue Gleeson rw_exit(&vm_pool->svp_lock);
14601bdd6c0eSSue Gleeson return (NULL);
14611bdd6c0eSSue Gleeson }
14621bdd6c0eSSue Gleeson
14631bdd6c0eSSue Gleeson if ((vm_pool->svp_total_size + chunklen) > vm_pool->svp_max_size) {
14641bdd6c0eSSue Gleeson chunklen = vm_pool->svp_max_size - vm_pool->svp_total_size;
14651bdd6c0eSSue Gleeson }
14661bdd6c0eSSue Gleeson
14671bdd6c0eSSue Gleeson next = srpt_vmem_chunk_alloc(vm_pool, chunklen);
14681bdd6c0eSSue Gleeson if (next != NULL) {
14691bdd6c0eSSue Gleeson /*
14701bdd6c0eSSue Gleeson * Note that the size of the chunk we got
14711bdd6c0eSSue Gleeson * may not be the size we requested. Use the
14721bdd6c0eSSue Gleeson * length returned in the chunk itself.
14731bdd6c0eSSue Gleeson */
14741bdd6c0eSSue Gleeson if (vmem_add(vm_pool->svp_vmem, (void*)(uintptr_t)next->mr_va,
14751bdd6c0eSSue Gleeson next->mr_len, VM_NOSLEEP) == NULL) {
14761bdd6c0eSSue Gleeson srpt_vmem_chunk_free(vm_pool, next);
14771bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("vmem_add failed");
14781bdd6c0eSSue Gleeson } else {
14791bdd6c0eSSue Gleeson vm_pool->svp_total_size += next->mr_len;
14801bdd6c0eSSue Gleeson avl_add(&vm_pool->svp_mr_list, next);
14811bdd6c0eSSue Gleeson }
14821bdd6c0eSSue Gleeson }
14831bdd6c0eSSue Gleeson
14841bdd6c0eSSue Gleeson rw_exit(&vm_pool->svp_lock);
14851bdd6c0eSSue Gleeson
14861bdd6c0eSSue Gleeson result = vmem_alloc(vm_pool->svp_vmem, size, VM_NOSLEEP | VM_FIRSTFIT);
14871bdd6c0eSSue Gleeson
14881bdd6c0eSSue Gleeson return (result);
14891bdd6c0eSSue Gleeson }
14901bdd6c0eSSue Gleeson
14911bdd6c0eSSue Gleeson static void
srpt_vmem_free(srpt_vmem_pool_t * vm_pool,void * vaddr,size_t size)14921bdd6c0eSSue Gleeson srpt_vmem_free(srpt_vmem_pool_t *vm_pool, void *vaddr, size_t size)
14931bdd6c0eSSue Gleeson {
14941bdd6c0eSSue Gleeson vmem_free(vm_pool->svp_vmem, vaddr, size);
14951bdd6c0eSSue Gleeson }
14961bdd6c0eSSue Gleeson
14971bdd6c0eSSue Gleeson static int
srpt_vmem_mr(srpt_vmem_pool_t * vm_pool,void * vaddr,size_t size,srpt_mr_t * mr)14981bdd6c0eSSue Gleeson srpt_vmem_mr(srpt_vmem_pool_t *vm_pool, void *vaddr, size_t size,
14991bdd6c0eSSue Gleeson srpt_mr_t *mr)
15001bdd6c0eSSue Gleeson {
15011bdd6c0eSSue Gleeson avl_index_t where;
15021bdd6c0eSSue Gleeson ib_vaddr_t mrva = (ib_vaddr_t)(uintptr_t)vaddr;
15031bdd6c0eSSue Gleeson srpt_mr_t chunk;
15041bdd6c0eSSue Gleeson srpt_mr_t *nearest;
15051bdd6c0eSSue Gleeson ib_vaddr_t chunk_end;
15061bdd6c0eSSue Gleeson int status = DDI_FAILURE;
15071bdd6c0eSSue Gleeson
15081bdd6c0eSSue Gleeson rw_enter(&vm_pool->svp_lock, RW_READER);
15091bdd6c0eSSue Gleeson
15101bdd6c0eSSue Gleeson chunk.mr_va = mrva;
15111bdd6c0eSSue Gleeson nearest = avl_find(&vm_pool->svp_mr_list, &chunk, &where);
15121bdd6c0eSSue Gleeson
15131bdd6c0eSSue Gleeson if (nearest == NULL) {
15141bdd6c0eSSue Gleeson nearest = avl_nearest(&vm_pool->svp_mr_list, where,
15151bdd6c0eSSue Gleeson AVL_BEFORE);
15161bdd6c0eSSue Gleeson }
15171bdd6c0eSSue Gleeson
15181bdd6c0eSSue Gleeson if (nearest != NULL) {
15191bdd6c0eSSue Gleeson /* Verify this chunk contains the specified address range */
15201bdd6c0eSSue Gleeson ASSERT(nearest->mr_va <= mrva);
15211bdd6c0eSSue Gleeson
15221bdd6c0eSSue Gleeson chunk_end = nearest->mr_va + nearest->mr_len;
15231bdd6c0eSSue Gleeson if (chunk_end >= mrva + size) {
15241bdd6c0eSSue Gleeson mr->mr_hdl = nearest->mr_hdl;
15251bdd6c0eSSue Gleeson mr->mr_va = mrva;
15261bdd6c0eSSue Gleeson mr->mr_len = size;
15271bdd6c0eSSue Gleeson mr->mr_lkey = nearest->mr_lkey;
15281bdd6c0eSSue Gleeson mr->mr_rkey = nearest->mr_rkey;
15291bdd6c0eSSue Gleeson status = DDI_SUCCESS;
15301bdd6c0eSSue Gleeson }
15311bdd6c0eSSue Gleeson }
15321bdd6c0eSSue Gleeson
15331bdd6c0eSSue Gleeson rw_exit(&vm_pool->svp_lock);
15341bdd6c0eSSue Gleeson return (status);
15351bdd6c0eSSue Gleeson }
15361bdd6c0eSSue Gleeson
15371bdd6c0eSSue Gleeson static srpt_mr_t *
srpt_vmem_chunk_alloc(srpt_vmem_pool_t * vm_pool,ib_memlen_t chunksize)15381bdd6c0eSSue Gleeson srpt_vmem_chunk_alloc(srpt_vmem_pool_t *vm_pool, ib_memlen_t chunksize)
15391bdd6c0eSSue Gleeson {
15401bdd6c0eSSue Gleeson void *chunk = NULL;
15411bdd6c0eSSue Gleeson srpt_mr_t *result = NULL;
15421bdd6c0eSSue Gleeson
15431bdd6c0eSSue Gleeson while ((chunk == NULL) && (chunksize >= SRPT_MIN_CHUNKSIZE)) {
15441bdd6c0eSSue Gleeson chunk = kmem_alloc(chunksize, KM_NOSLEEP);
15451bdd6c0eSSue Gleeson if (chunk == NULL) {
15461bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("srpt_vmem_chunk_alloc: "
15471bdd6c0eSSue Gleeson "failed to alloc chunk of %d, trying %d",
15481bdd6c0eSSue Gleeson (int)chunksize, (int)chunksize/2);
15491bdd6c0eSSue Gleeson chunksize /= 2;
15501bdd6c0eSSue Gleeson }
15511bdd6c0eSSue Gleeson }
15521bdd6c0eSSue Gleeson
15531bdd6c0eSSue Gleeson if (chunk != NULL) {
15541bdd6c0eSSue Gleeson result = srpt_reg_mem(vm_pool, (ib_vaddr_t)(uintptr_t)chunk,
15551bdd6c0eSSue Gleeson chunksize);
15561bdd6c0eSSue Gleeson if (result == NULL) {
15571bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("srpt_vmem_chunk_alloc: "
15581bdd6c0eSSue Gleeson "chunk registration failed");
15591bdd6c0eSSue Gleeson kmem_free(chunk, chunksize);
15601bdd6c0eSSue Gleeson }
15611bdd6c0eSSue Gleeson }
15621bdd6c0eSSue Gleeson
15631bdd6c0eSSue Gleeson return (result);
15641bdd6c0eSSue Gleeson }
15651bdd6c0eSSue Gleeson
15661bdd6c0eSSue Gleeson static void
srpt_vmem_chunk_free(srpt_vmem_pool_t * vm_pool,srpt_mr_t * mr)15671bdd6c0eSSue Gleeson srpt_vmem_chunk_free(srpt_vmem_pool_t *vm_pool, srpt_mr_t *mr)
15681bdd6c0eSSue Gleeson {
15691bdd6c0eSSue Gleeson void *chunk = (void *)(uintptr_t)mr->mr_va;
15701bdd6c0eSSue Gleeson ib_memlen_t chunksize = mr->mr_len;
15711bdd6c0eSSue Gleeson
15721bdd6c0eSSue Gleeson srpt_dereg_mem(vm_pool->svp_ioc, mr);
15731bdd6c0eSSue Gleeson kmem_free(chunk, chunksize);
15741bdd6c0eSSue Gleeson }
15751bdd6c0eSSue Gleeson
15761bdd6c0eSSue Gleeson static srpt_mr_t *
srpt_reg_mem(srpt_vmem_pool_t * vm_pool,ib_vaddr_t vaddr,ib_memlen_t len)15771bdd6c0eSSue Gleeson srpt_reg_mem(srpt_vmem_pool_t *vm_pool, ib_vaddr_t vaddr, ib_memlen_t len)
15781bdd6c0eSSue Gleeson {
15791bdd6c0eSSue Gleeson srpt_mr_t *result = NULL;
15801bdd6c0eSSue Gleeson ibt_mr_attr_t mr_attr;
15811bdd6c0eSSue Gleeson ibt_mr_desc_t mr_desc;
15821bdd6c0eSSue Gleeson ibt_status_t status;
15831bdd6c0eSSue Gleeson srpt_ioc_t *ioc = vm_pool->svp_ioc;
15841bdd6c0eSSue Gleeson
15851bdd6c0eSSue Gleeson result = kmem_zalloc(sizeof (srpt_mr_t), KM_NOSLEEP);
15861bdd6c0eSSue Gleeson if (result == NULL) {
15871bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("srpt_reg_mem: failed to allocate");
15881bdd6c0eSSue Gleeson return (NULL);
15891bdd6c0eSSue Gleeson }
15901bdd6c0eSSue Gleeson
15911bdd6c0eSSue Gleeson bzero(&mr_attr, sizeof (ibt_mr_attr_t));
15921bdd6c0eSSue Gleeson bzero(&mr_desc, sizeof (ibt_mr_desc_t));
15931bdd6c0eSSue Gleeson
15941bdd6c0eSSue Gleeson mr_attr.mr_vaddr = vaddr;
15951bdd6c0eSSue Gleeson mr_attr.mr_len = len;
15961bdd6c0eSSue Gleeson mr_attr.mr_as = NULL;
15971bdd6c0eSSue Gleeson mr_attr.mr_flags = vm_pool->svp_flags;
15981bdd6c0eSSue Gleeson
15991bdd6c0eSSue Gleeson status = ibt_register_mr(ioc->ioc_ibt_hdl, ioc->ioc_pd_hdl,
16001bdd6c0eSSue Gleeson &mr_attr, &result->mr_hdl, &mr_desc);
16011bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
16021bdd6c0eSSue Gleeson SRPT_DPRINTF_L2("srpt_reg_mem: ibt_register_mr "
16031bdd6c0eSSue Gleeson "failed %d", status);
16041bdd6c0eSSue Gleeson kmem_free(result, sizeof (srpt_mr_t));
16051bdd6c0eSSue Gleeson return (NULL);
16061bdd6c0eSSue Gleeson }
16071bdd6c0eSSue Gleeson
16081bdd6c0eSSue Gleeson result->mr_va = mr_attr.mr_vaddr;
16091bdd6c0eSSue Gleeson result->mr_len = mr_attr.mr_len;
16101bdd6c0eSSue Gleeson result->mr_lkey = mr_desc.md_lkey;
16111bdd6c0eSSue Gleeson result->mr_rkey = mr_desc.md_rkey;
16121bdd6c0eSSue Gleeson
16131bdd6c0eSSue Gleeson return (result);
16141bdd6c0eSSue Gleeson }
16151bdd6c0eSSue Gleeson
16161bdd6c0eSSue Gleeson static void
srpt_dereg_mem(srpt_ioc_t * ioc,srpt_mr_t * mr)16171bdd6c0eSSue Gleeson srpt_dereg_mem(srpt_ioc_t *ioc, srpt_mr_t *mr)
16181bdd6c0eSSue Gleeson {
16191bdd6c0eSSue Gleeson ibt_status_t status;
16201bdd6c0eSSue Gleeson
16211bdd6c0eSSue Gleeson status = ibt_deregister_mr(ioc->ioc_ibt_hdl, mr->mr_hdl);
16221bdd6c0eSSue Gleeson if (status != IBT_SUCCESS) {
1623c3a558e7SSue Gleeson SRPT_DPRINTF_L1("srpt_dereg_mem, error deregistering MR (%d)",
16241bdd6c0eSSue Gleeson status);
16251bdd6c0eSSue Gleeson }
16261bdd6c0eSSue Gleeson kmem_free(mr, sizeof (srpt_mr_t));
16271bdd6c0eSSue Gleeson }
16281bdd6c0eSSue Gleeson
16291bdd6c0eSSue Gleeson static int
srpt_vmem_mr_compare(const void * a,const void * b)16301bdd6c0eSSue Gleeson srpt_vmem_mr_compare(const void *a, const void *b)
16311bdd6c0eSSue Gleeson {
16321bdd6c0eSSue Gleeson srpt_mr_t *mr1 = (srpt_mr_t *)a;
16331bdd6c0eSSue Gleeson srpt_mr_t *mr2 = (srpt_mr_t *)b;
16341bdd6c0eSSue Gleeson
16351bdd6c0eSSue Gleeson /* sort and match by virtual address */
16361bdd6c0eSSue Gleeson if (mr1->mr_va < mr2->mr_va) {
16371bdd6c0eSSue Gleeson return (-1);
16381bdd6c0eSSue Gleeson } else if (mr1->mr_va > mr2->mr_va) {
16391bdd6c0eSSue Gleeson return (1);
16401bdd6c0eSSue Gleeson }
16411bdd6c0eSSue Gleeson
16421bdd6c0eSSue Gleeson return (0);
16431bdd6c0eSSue Gleeson }
1644